Универсальность цикла, увеличение дальшейней поддержки

Имеется следующий цикл, который распределяет полученную информацию из запроса, который соответствует i. общий цикл for i := 1 to maxI do, где maxI задан перед началом цикла и равняется 13-и при каждом i выполняется свой запрос

и при каждом i выполняется свой порядок и свои значения из запросов. Далее создаются файлы, они немного разные по расположению и наполнению ячеек.

Т.е если i=1, то выполнится 1 запрос, наполнение ячеек будет происходить на основе цикла while, который в свою очередь по условию i запихнёт значение в определённые значения и после создастся определённый файл исходя из i.

Сейчас выглядит так:

maxI:=13;
for i := 1 to maxI do
begin
  if i = 1 then
  dm.zapros.SQL.Text := 'запрос1'
  else if
  if i = 2 then
  dm.zapros.SQL.Text := 'запрос2'
  else if
  if i = 3 then
  dm.zapros.SQL.Text := 'запрос3'; 
  //И так 13 запросов
  
  dm.zapros.Open;
  if  not dm.zapros.IsEmpty then
    begin
      try
        Exsel := CreateOleObject('Excel.Application');
        Exsel.DisplayAlerts := false;
        WorkBook := Exsel.Workbooks.Add;
        Sheet := WorkBook.WorkSheets[1];
        r:=1;

        while not dm.zapros.Eof do
        begin

          if (i in [1,2,3,4,5,6,7,8,9,10,11,12,13] then
            begin
               Sheet.Cells[r,1].Value := dm.zapros.FieldByName('path').AsString;
               Sheet.Cells[r,2].Value := dm.zapros.FieldByName('kol').AsInteger;
            end;

          if (i in [1,2,8,11,12,13]) then
            begin
              Sheet.Cells[r,5].Value := dm.zapros.FieldByName('E').AsInteger;
            end;

          if (i in [3,4,7,9,10]) then
            begin
              Sheet.Cells[r,4].Value:=dm.zapros.FieldByName('E').AsInteger;
            end;

          if (i in [9,10]) then
            begin
              Sheet.Cells[r,7].Value := dm.zapros.FieldByName('F').AsString;
            end;

          if (i in [1,10,12,13]) then
            begin
              Sheet.Cells[r,6].Value := dm.zapros.FieldByName('F').AsString;
            end;

          if (i in [5,6]) then
            begin
              Sheet.Cells[r,6].Value := dm.zapros.FieldByName('G').AsString;
            end;

          if (i in [1,2,4,13]) then
            begin
              Sheet.Cells[r,7].Value := dm.zapros.FieldByName('G').AsString;
            end;

          if (i in [9,10,]) then
            begin
              Sheet.Cells[r,8].Value := dm.zapros.FieldByName('G').AsString;
            end;
          inc(r);
          dm.aqLoc.Next;
        end;
      finally
        case i of
          1: WorkBook.SaveAs(Tempkp+'\файл1 от '+dt+'.csv',6);
          2: WorkBook.SaveAs(Tempkp+'\файл2 от '+dt+'.csv',6);
          3: WorkBook.SaveAs(Tempkp+'\файл3 от '+dt+'.csv',6);
          //и так 13 файлов
         

        end;
        WorkBook.Close;
        Exsel.Application.Quit;
        Exsel := Unassigned;
      end;
    end;



end;

Собсно говоря меня интересует цикл while. Поверьте, прежний вид был куда хуже, что-то из разряда "тронул листик - всё дерево упало".

Хотелось бы поинтересоваться, Что с этим можно сделать, чтобы увеличить возможность воздействия на этот цикл, его переделки, добавления чего-то нового без применения костылей?


Ответы (2 шт):

Автор решения: Igor

Поместите в массив объекты, содержащие SQL запросы и методы - Start, HandleRow, Finish.

for i := Low(HANDLERS) to High(HANDLERS) do
begin
  dm.zapros.SQL.Text := HANDLERS[i].SQL;
  dm.zapros.Open;
  ...

      while not dm.zapros.Eof do
      begin
        HANDLERS[i].HandleRow(dm.zapros, Sheet, r);
        inc(r);
        dm.aqLoc.Next;
      end;
    finally
      HANDLERS[i].Finish(WorkBook);
    end;
→ Ссылка
Автор решения: Alex R.

Пытаться в один блок кода засунуть 13 отчетов не очень хорошая идея. Будут проблемы с сопровождением.

Лучше создать одну функцию выгрузки в Excel. Внутрь передавать минимум TDataSet и имя файла.

Можно также координаты начальной ячейки или callback-функцию для динамического определения номера колонки. Чтобы сместить колонки в отчете можно также сделать пустые столбцы в запросе или назвать имена колонок также как в Excel (A, B, C).

Пример с внешним определением номера колонки

type
  TColumnFunc = function(AFieldName: string): Integer;

procedure ExportToExcel(ADataSet: TDataSet; AFileName: string; AGetColumnFunc: TColumnFunc);
var
  i: Integer;
  vCol: Integer;
  Exsel, WorkBook, Sheet: OleVariant;
begin
  ADataSet.Open;

  if not ADataSet.IsEmpty then
    try
      Exsel := CreateOleObject('Excel.Application');
      Exsel.DisplayAlerts := false;
      WorkBook := Exsel.Workbooks.Add;
      Sheet := WorkBook.WorkSheets[1];

      while not ADataSet.Eof do
        begin
          for i := 0 to ADataSet.FieldCount - 1 do
            begin
              vCol := i + 1;
              if Assigned(AGetColumnFunc) then
                vCol := AGetColumnFunc(ADataSet.Fields[i].FieldName);

              Sheet.Cells[ADataSet.RecNo, vCol].Value := ADataSet.Fields[i].AsString;
            end;

          ADataSet.Next;
        end;

      WorkBook.SaveAs(AFileName, 6);
    finally
      WorkBook.Close;
      Exsel.Application.Quit;
      Exsel := Unassigned;
    end;

  ADataSet.Close;
end;

Возможно будут сложности с типом поля в Excel, тогда надо анализировать Field[i].FieldKind.

→ Ссылка