FDQuery и OnCalcFields, получить предыдущую строку - PullRequest
0 голосов
/ 29 апреля 2020

Delphi 10.3.3 FireDA C: DBGrid / FDQuery / MySQL VCL

Привет всем,

У меня есть таблица с этими полями

----------------------
|  id  |    data      |
----------------------
|  1   | 0=A;1=B;2=C  |
|  2   | 2=Z          |
|  3   |              |
|  4   | 0=Y;1=X      |
|  5   |              |
|  6   |              |

Каждая строка данных представляет только изменение в таблице.

Я бы хотел, чтобы это отображалось в DBGRID:

-----------------------
|  id  | C0 | C1 | C2 |
-----------------------
|  1   | A  | B  | C  |
|  2   | A  | B  | Z  |
|  3   | A  | B  | Z  |
|  4   | Y  | X  | Z  |
|  5   | Y  | X  | Z  |
|  6   | Y  | X  | Z  |

. На данный момент я могу сделать только следующее table:

-----------------------
|  id  | C0 | C1 | C2 |
-----------------------
|  1   | A  | B  | C  |
|  2   |    |    | Z  |
|  3   |    |    |    |
|  4   | Y  | X  |    |
|  5   |    |    |    |
|  6   |    |    |    |

Чтобы получить этот результат, я создаю дополнительные столбцы в событии FDQuery1.BeforeOpen И в событии OnCreateFields я заполняю каждый столбец, но Я не знаю содержимое предыдущей строки ,

Итак, как мне заполнить недостающие поля в DBgrid? Спасибо, Франк

1 Ответ

1 голос
/ 29 апреля 2020

Я думаю, что вы имеете в виду OnCalcFields, а не OnCreateFields.

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

Проблема с выполнением расчетов на стороне клиента с использованием другой строки набора данных заключается в том, что для этого необходимо иметь возможность перемещать курсор набора данных во время события OnCalcFields. Однако в то время DataSet будет находиться либо в состоянии dsCalcFields, либо в dsInternalCal c, и, хотя это так, вы не можете легко перейти к другой строке в наборе данных. возможно сделать это, но требует объявления класса набора данных-потомков (TMyFDQuery), чтобы вы могли получить доступ к SetTempState, необходимому для возврата в предыдущее состояние после того, как вы собрали необходимую информацию из «другая» строка и, если вам нужно больше одного поля, вам нужно где-то временно хранить значения. Таким образом, все становится беспорядочно.

Гораздо более чистый подход предполагает использование функционального сходства между наборами данных FireDA C и TClientDataSets. Одной из приятных особенностей TClientDatasSets является легкость, с которой вы можете перемещать содержимое набора данных между двумя CDS, просто выполняя

CDS2.Data := CDS1.Data;

FireDA C наборов данных, которые могут выполнять те же приемы, но между любыми типами наборов данных FD. , Вот что я бы сделал в вашей ситуации:

  1. Добавьте FDMemTable в вашу форму / модуль данных и скопируйте в него данные запроса в событии AfterOpen FDQuery, например:
procedure TForm2.FDQuery1AfterOpen(DataSet: TDataSet);
begin
  FDQuery1.DisableControls;
  try
    FDMemTable1.Data := FDQuery1.Data;
    FDMemTable1.Open;
  finally
    FDQuery1.First;
    FDQuery1.EnableControls;
  end;
end;

FDQuery1.First должен заставить его пересмотреть вычисленные поля после того, как станут доступны данные FDMemTable (во время начального FDQuery1.Open, конечно, это не может быть).

В событии FDQuery OnCalcFields используйте подобный код, чтобы основывать значения вычисляемых полей на значениях, взятых из предыдущей строки (если, конечно, есть одна, первая строка не может иметь "предыдущую" строку):
procedure TForm2.FDQuery1CalcFields(DataSet: TDataSet);
begin
  if FDMemTable1.Active then begin
    if FDMemTable1.Locate('ContactID', FDQuery1.FieldByName('ContactID').AsInteger, []) then begin
      FDMemTable1.Prior;
      if not FDMemTable1.Bof then begin
        //  Set FDQuery1's calculated fields that depend on prior row
        FDQuery1.FieldByName('PriorRowID').AsInteger := FDMemTable1.FieldByName('ContactID').AsInteger;
      end;
    end;
  end;
end;

В этом примере мой запрашиваемый набор данных имеет первичный ключ ContactID, а вычисленное значение - это просто значение ContactID из предыдущей строки. Конечно, в реальной жизни было бы более эффективно использовать постоянные переменные поля, а не продолжать вызывать FieldByName.

Я полагаю, что другой возможностью может быть использование метода CloneCursor для получения курсора поиска для доступа к «предыдущая» строка, но я сам не пробовал, и это все равно может оказаться невозможным (что происходит с вычисляемыми полями в копии CloneCuror?).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...