Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Для новичков > Работа с файлом. Ведомость


Автор: Beren 13.4.2011, 11:02
Вот в чём суть. На форме 2 кнопки и таблица строк. Одна кнопка загружает файл и выводит в StringGrid имена и оценки в двух колонках. Это у меня получилось. Теперь надо, чтобы пользователь изменил значение оценки и сохранил в файл. goEditing =true поставил. Вот код. Спасибо.
Код

implementation
 
{$R *.dfm}
 const
N=50;
 type
 Trec=record
 Name:string;
 mark:integer;
 end ;
 Tgroup=array [1..n] of Trec;
 var
 Xgroup:Tgroup;
 Ngroup:integer;
 F:Textfile;
  i:integer;
 
procedure TForm1.Button1Click(Sender: TObject);
var
s:string ;
begin
StringGrid1.Cells [0,0]:='Name';
StringGrid1.Cells [1,0]:='Mark';
AssignFile(F,'C:\Text.txt');
Reset (F);
Ngroup:=0;
  while not EOF(f) do
      begin
      Ngroup:= NGroup+1;
      Readln(F,S);
      XGroup[Ngroup].Name:=s;
      Readln(F,S);
      XGroup[Ngroup].mark:=StrToInt(s);
      StringGrid1.Cells[0,Ngroup]:=Xgroup[Ngroup].name;
      StringGrid1.Cells[1,Ngroup]:= IntToStr(Xgroup[Ngroup].mark);
      end;
      CloseFile(F);
end;
 
procedure TForm1.Button2Click(Sender: TObject);
  var
  s :string;
  sel1,sel2,j:integer;
 begin
    for i:=0 to StringGrid1.RowCount-1 do
    for j:=0 to StringGrid1.ColCount-1 do
   begin
   if                                                               //выбрана какая-то строка в колонке mark. В том и вопрос
   then
                  begin
         sel1:=i+1;
         sel2:=j+1;
         break
                  end;
   end;
   if sel>0 then
   begin
    Xgroup[sel].mark:=StrToInt (StringGrid1.Cells[sel1,sel2]);
      end;
         end;
 
      ASsignFile(F,'C:\Text.txt');
    Rewrite(F);
 
    for I:=1 to Ngroup do
    begin
       s:= Xgroup[i].name ;
        writeln(F,s);
        s:=IntToStr(Xgroup[i].mark);
         writeln(F,s);
 
    end;
    closeFile(F);
 
end;
 
 
end.


Автор: amsoft 14.4.2011, 12:08
если вся загвоздка в определении позиции текущей ячейки, то вот эти свойства тебе в помощь:
TCustomGrid.Row - индекс строки текущей ячейки
TCustomGrid.Col - индекс столбца текущей ячейки

Тогда и циклы тебе не нужны будут

Автор: Beren 14.4.2011, 20:41
Поконкретней можно ?

Автор: amsoft 15.4.2011, 07:19
Цитата(Beren @  13.4.2011,  14:02 Найти цитируемый пост)
    for i:=0 to StringGrid1.RowCount-1 do
    for j:=0 to StringGrid1.ColCount-1 do
   begin
   if                                                               //выбрана какая-то строка в колонке mark. В том и вопрос
   then
                  begin
         sel1:=i+1;
         sel2:=j+1;
         break
                  end;
   end;


Как я понял в этих циклах ты пробегаешь по всем строкам и столбцам в поисках активной ячейки.
Вместо этого можно воспользоваться вышеуказанными свойствами компонента StringGrid. Тогда данный кусок кода примет следующий вид:

Код

sel1 := StringGrid1.Row+1;
sel2 := StringGrid1.Col+1;


Автор: Beren 15.4.2011, 10:56
Не получается (. При нажатии на Button2 появляется ошибка "is not a valid integer value". 

Код

procedure TForm1.Button2Click(Sender: TObject);
  var
  s :string;
  sel1,sel2,j:integer;

 begin
   sel1:=-1;
   sel2:=-1;
   sel1:= StringGrid1.Row+1;
sel2 := StringGrid1.Col+1;
   if (sel1>0) and (sel2>0) then
   begin
   for i:=0 to Ngroup do
    Xgroup[i].mark:=StrToInt (StringGrid1.Cells[sel1,sel2]);   //Вот здесь я совсем не уверен. Как сделать так, чтобы в выбранной ячейке оценка перезаписалась ?
      end;


     ASsignFile(F,'C:\Text.txt');
    Rewrite(F);

    for I:=1 to Ngroup do
    begin
       s:= Xgroup[i].name ;
        writeln(F,s);
        s:=IntToStr(Xgroup[i].mark);
         writeln(F,s);

    end;
    closeFile(F);

end;


end.


Автор: amsoft 15.4.2011, 11:18
Цитата(Beren @  15.4.2011,  13:56 Найти цитируемый пост)
появляется ошибка "is not a valid integer value


Это означает, что в данной ячейке нет данных или текст не может быть распознан как число
вместо StrToInt попробуй использовать TryStrToInt

Добавлено через 2 минуты и 35 секунд
TryStrToInt(StringGrid1.Cells[sel1,sel2],Xgroup[i].mark)

Автор: Beren 15.4.2011, 12:10
А теперь при нажатии на button2 оценки обнуляютя

Автор: amsoft 16.4.2011, 14:25
Код

var
X: integer;
...
if TryStrToInt(StringGrid1.Cells[sel1,sel2],X)
then Xgroup[i].mark := X;



Автор: Beren 16.4.2011, 20:16
Теперь не обнуляется ). Но и не сохраняет изменённую оценку (
Код

procedure TForm1.Button2Click(Sender: TObject);
  var
  s :string;
  sel1,sel2,j,X:integer;
begin
   sel1:=-1;
   sel2:=-1;
sel1:= StringGrid1.Row+1;
sel2 := StringGrid1.Col+1;
   if (sel1>0) and (sel2>0) and TryStrToInt(StringGrid1.Cells[sel1,sel2],X) then
          begin
          for i:=1 to Ngroup do
          Xgroup[i].mark := X;
           end;
      for i:=1 to Ngroup do
      ASsignFile(F,'C:\Text.txt');
      Rewrite(F);
    for I:=1 to Ngroup do
                          begin
                          s:= Xgroup[i].name ;
                          writeln(F,s);
                          s:=IntToStr(Xgroup[i].mark);
                          writeln(F,s);
                           end;
       closeFile(F);

end;

Автор: amsoft 17.4.2011, 08:07
Код

sel1:= StringGrid1.Row;
sel2 := StringGrid1.Col;


Сразу не узрел ошибку - единицу прибавлять не надо

Автор: Beren 17.4.2011, 12:46
Тогда и условие (sel1>0) and (sel2>0) получается не нужно.... Но всё равно не сохраняет
Код

procedure TForm1.Button2Click(Sender: TObject);
  var
  s :string;
  sel1,sel2,X:integer;
  begin
sel1:= StringGrid1.Row;
sel2 := StringGrid1.Col;
   if (TryStrToInt(StringGrid1.Cells[sel1,sel2],X)) then
       begin
       for i:=1 to Ngroup do
       Xgroup[i].mark := X;
        end;

    ASsignFile(F,'C:\Text.txt');
    Rewrite(F);

    for I:=1 to Ngroup do
               begin
                s:= Xgroup[i].name ;
                writeln(F,s);
                s:=IntToStr(Xgroup[i].mark);
               writeln(F,s);
                end;
    closeFile(F);

end;


end.


Автор: amsoft 17.4.2011, 16:44
Вообще не сохраняет или неверно сохраняет?
Цитата(Beren @  17.4.2011,  15:46 Найти цитируемый пост)
       
for i:=1 to Ngroup do
    Xgroup[i].mark := X;

У тебя неверно организован этот цикл. Здесь ты пробегаешь по списку всех учеников и для каждого ученика ставишь одну и ту же оценку (которая стоит в активной ячейке), тогда как оценку надо менять только для отдельного ученика (с индексом равным номеру строки текущей ячейки). ИМХО неудобный вариант.
Если у тебя сохранение списка идет по нажатию кнопки, то гораздо лучше обновить сразу весь массив и сохранить его в файл. 
В этом случае вообще отпадает необходимость поиска активной ячейки, да и без массива Xgroup вполне можно обойтись.

Загружаем список в таблицу:

Код

procedure TForm1.Button1Click(Sender: TObject);
var
Y: integer;
F: TextFile;
S: string;
begin
Y := 0;
AssignFile(F,'C:\1.txt');
Reset (F);
while not EOF(f) do
      begin
      Readln(F,S);
      StringGrid1.Cells[0,Y] := S;
      Readln(F,S);
      StringGrid1.Cells[1,Y] := S;
      Inc(Y);
      end;
CloseFile(F);
end;


Сохраняем список:

Код

procedure TForm1.Button2Click(Sender: TObject);
var
Y: integer;
F: TextFile;
begin
AssignFile(F,'C:\1.txt');
Rewrite(F);
for Y:=1 to StringGrid1.RowCount do
    begin
    writeln(F,StringGrid1.Cells[0,Y-1]);
    writeln(F,StringGrid1.Cells[1,Y-1]);
    end;
CloseFile(F);
end;


Текстовый файл должен иметь следующий формат:

ученик1
оценка1
ученик2
оценка2
...

Автор: Beren 17.4.2011, 18:18
Вообще не сохраняет. Хотелось бы , чтобы вы исправили мой вариант с циклом, а то получится, что вы просто всё за меня сделали.  Да, файл такой
Иванов
5
Петров
4
Сидоров
3
 

Автор: amsoft 17.4.2011, 18:31
У меня сохраняет, проверено.

Добавлено через 3 минуты и 52 секунды
PS Это оптимальный вариант для решения твоей задачи

Автор: Beren 17.4.2011, 20:11
Ну всё равно спасибо

Автор: Beren 18.4.2011, 15:57
А как сделать чтобы были названия колонок Name  и Mark . ТО есть , чтобы таблица выводилась так : Name               Mark
                                                                                                                                                                      Сидоров            5
                                                                                                                                                                       Петров             4
                                                                                                                                                                       Иванов             3

Автор: amsoft 19.4.2011, 10:02
Два варианта:

1. Если шапка таблицы у тебя уже забита заранее, то загружай/сохраняй таблицу не с первой строки, а со второй
В коде загрузки исправь 
Код

Y := 0 

на
Код

Y := 1;

В коде сохранения исправь
Код

for Y:=1 to StringGrid1.RowCount do

на
Код

for Y:=2 to StringGrid1.RowCount do


2. Можно шапку таблицы забить в файл со списком учеников, тогда вообще код менять не надо

Автор: Beren 19.4.2011, 12:48
Спасибо

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)