Есть несколько вещей, которые, если не "неправильные", не совсем верны с вашим кодом.
Вы должны использовать Next
, а не FindNext
, чтобы перейти кследующий ряд в наборе данных.Next
перемещает к следующей строке в наборе данных, тогда как FindNext
перемещает к следующей строке, которая соответствует критериям поиска, которые вы уже установили, например, используя DataSet.SetKey; ...
- прочитайте онлайн-справку для использования FindKey
.
Вы НЕ должны пытаться пройти набор данных, используя цикл For
;используйте петлю While not FDMemData.Eof do
.Eof
означает «Конец файла» и возвращает true, когда набор данных находится в последней строке.
Вы должны вызывать FDMemTable1.DisableControls
перед циклом и FDMemTable1.EnableControls
после него,Это предотвращает обновление элементов управления с поддержкой db, таких как DBGrid, внутри цикла, что в противном случае замедляло бы цикл при обновлении сетки.
Если у вас нет веских причин не делать этого,ВСЕГДА очищайте фильтр набора данных в том же методе, в котором вы его установили, в противном случае вы можете получить некоторые очень запутанные ошибки, если забудете, что фильтр активен.
Старайтесь избегать использования RecordCount
привам не обязательноВ зависимости от используемой вами RDMS это может привести к значительным издержкам обработки, которых можно избежать на сервере и, возможно, в сети (поскольку при некоторых типах серверов это приведет к тому, что весь набор данных будет получен клиентом).
Измените свой первый цикл на
procedure TForm1.Button1Click(Sender: TObject);
var
_ValueSum : Integer;
begin
_ValueSum := 0;
FDMemTable1.Filter := 'ID like ' + QuotedStr('A%');
try
FDMemTable1.DisableControls;
FDMemTable1.First;
while not FDMemTable1.Eof do begin
_ValueSum:= _ValueSum + FDMemTable1.FieldByName('Value').AsInteger;
FDMemTable1.Next;
end
finally
FDMemTable1.Filter := '';
FDMemTable1.Filtered := False;
FDMemTable1.EnableControls;
end;
Button1.Caption := IntToStr(_ValueSum);
end;
Если вы сделаете это, вам вообще не понадобится ваш метод Button2Click.
Как отмечено в комментарии, вы можетеиспользуйте TBookMark, чтобы записать свою позицию в наборе данных перед циклом и вернуться к нему позже, как в
var
_ValueSum : Integer;
BM : TBookMark;
begin
_ValueSum := 0;
BM := FDMemTable.GetBookMark;
FDMemTable1.Filter := 'ID like ' + QuotedStr('A%');
try
[etc]
finally
FDMemTable1.Filter := '';
FDMemTable1.Filtered := False;
FDMemTable1.GotoBookMark(BM);
FDMemTable1.FeeBookMark(BM);
FDMemTable1.EnableControls;
end;
Кстати, вы можете сэкономить некоторую печать и получить более краткий код, используя InsertRecord
метод, как в
FDMemTable1.InsertRecord(['A1', 1]);
FDMemTable1.InsertRecord(['B1', 2]);
FDMemTable1.InsertRecord(['A2', 3]);
FDMemTable1.InsertRecord(['B2', 4]);
Кстати # 2: Время использования FindKey
наступает после того, как вы настроили ключ для поиска, с помощью вызова SetKey
, чем затем установка значения ключа (с)).
Для обычной навигации по набору данных используйте стандартные методы навигации, например Next
, Prior
, First
, Last
, MoveBy
и т. Д.