Оптимизация

DenDen
отредактировано November 2006 Раздел: FastReport 4.0
Есть основной цикл формирующий композитный отчет. Из этого основного цикла запускаются процедуры. В процедурах выполняются хранимые процедуры, доступ к данным через ADO компоненты, затем следует вызов PreparedReport(False), который очень медленно отрабатывает при чем закономерность такая, чем больше страниц загружено тем медленнее выполняется PreparedReport(False). Как с этим можно бороться? Заранее благодарен всем откликнувшимся.

Комментарии

  • отредактировано 20:07
    Такая же проблема, очень неудобно, приходиться сидеть в части проектов на 2-йке, у которой все на ура, т.к. объемы печати большие порядка сотен тысяч страниц.

    Проблемка в 3-йке (думаю для 4-ки тоже подойдет) обходится мною следующим образом:
    На форму кладется 2 компонента frxReport
    далее в цикле

    for i:=1 to 100 do begin
    frxRep1.prepareReport(true);
    frxRep2.PreviewPages.addFrom(frxRep1)ж
    end;
    FrxRep2.ShowPrepareReport

    Скорость подготовки отчета практически не падает, но все равно
    работает по сравнению с двойкой чудовищно-медленно.
  • отредактировано 20:07
    Сотни тысяч страниц? Если не секрет, что за отчеты такие?
    Попробовал сейчас слегка переделать демку, чтобы по кнопке Design делался PrepareReport(false). Нагенерил в общей сложности 30000 страниц. Скорость формирования отчета если и упала, то незначительно. Возможно, при 100000 страницах тормоза и будут, но терпения не хватило...
  • gpigpi
    отредактировано 20:07
    Также интересно сколько времени и на чём такие отчёты печатаются
  • DenDen
    отредактировано November 2006
    Может быть я изначально не правильно объяснил. Метод PreparedReport(False) вызывается в каждой процедуре вызываемой из основного цикла.
    Вот кусок кода как это выглядет. Соответственно метод PreparedReport(False) вызывается в Proc2, Proc3 и т.д.
    //Происходит при нажатии кнопки
    procedure TFrm1.Button1Click(Sender: TObject);
    begin
      Screen.Cursor := crHourGlass;
      frxReport1.Clear;
      frxReport1.PreviewPages.Clear;
      frxReport1.Preview := nil;
      with StoredProc1 do
      begin
        Close;
        //Передача параметров в процедуру.
        ...
        Open;
      end;
      Screen.Cursor := crDefault;
    end;
    
    //Происходит после открытия StoredProc1
    procedure TFrm1.StoredProc1AfterOpen(DataSet: TDataSet);
    begin
      Screen.Cursor := crHourGlass;
      DataSet.DisableControls;
      DataSet.First;
      while not DataSet.Eof do
      begin
        Application.ProcessMessages;
        if CheckBox1.Checked = True then
          Proc1;
        if CheckBox2.Checked = True then
          Proc2;
        if (CheckBox4.Checked = True) and (DataSet.FieldByName('Total').AsFloat > 0) then
          Proc3;
        if CheckBox5.Checked = True then
          Proc4;
        DataSet.Next;
      end;
      DataSet.EnableControls;
      frxReport1.Preview := frxPreview1;
      frxReport1.ShowPreparedReport;
      frxPreview1.SetFocus;
      Screen.Cursor := crDefault;
    end;
    
    //Proc1
    procedure TFrm1.Proc1;
    begin
      with frxReport1 do
      begin
        LoadFromFile('1.fr3');
        with StoredProc2 do
        begin
          Close;
          //Передача параметров в процедуру.
          ...
          Open;
        end;
        PrepareReport(False);
      end;
    end;
    
  • gpigpi
    отредактировано 20:07
    Может быть проблема в том, что каждый раз в цикле вызывается frxReport1.LoadFromFile? А если в шаблонах есть ещё и графические логотипы, то и формирование будет продолжительным за счёт многочисленной загрузки шаблонов. Воспользуйтесь советом Chaosbringer и один раз загрузите шаблоны в frxReport1..4, а результат добавляйте в frxReport0
  • DenDen
    отредактировано November 2006
    Попробовал способ Chaosbringer и на строке
    frxRep0.PreviewPages.AddFrom(frxRep1)
    
    выдает Access violation...
    Ну, а если быть совсем точным, то Access violation... возникает в модуле frxPreviewPages.pas в процедуре TfrxPreviewPages.AddFrom(Report: TfrxReport).
     xs := TfrxXMLSerializer.Create(nil);
      for i := 0 to Report.PreviewPages.Count - 1 do
      begin
        Page := Report.PreviewPages.Page[i];
        xi := TfrxXMLItem.Create;
        xi.Name := FPagesItem[Count - 1].Name; (Это вызывает Access violation...)
        xs.WriteRootComponent(Page, True, xi);
        xi.Unloadable := False;
        FPagesItem.AddItem(xi);
      end;
      xs.Free;
      ClearPageCache;
    
    Может быть разработчики допустили ошибку. Если нет, то скажите, что я нет так делаю.
  • gpigpi
    отредактировано 20:07
    Покажите фрагмент Вашего кода
  • DenDen
    отредактировано November 2006
    Пожалуйста, смотрите, но от предыдущего фрагмента он мало чем отличается.
    //Происходит при нажатии кнопки
    procedure TFrm1.Button1Click(Sender: TObject);
    begin
      Screen.Cursor := crHourGlass;
      frxReport2.LoadFromFile('1.fr3');
      frxReport1.Clear;
      frxReport1.PreviewPages.Clear;
      frxReport1.Preview := nil;
      with StoredProc1 do
      begin
        Close;
        //Передача параметров в процедуру.
        ...
        Open;
      end;
      Screen.Cursor := crDefault;
    end;
    
    //Происходит после открытия StoredProc1
    procedure TFrm1.StoredProc1AfterOpen(DataSet: TDataSet);
    begin
      Screen.Cursor := crHourGlass;
      DataSet.DisableControls;
      DataSet.First;
      while not DataSet.Eof do
      begin
        Application.ProcessMessages;
        if CheckBox1.Checked = True then
          Proc1;
        if CheckBox2.Checked = True then
          Proc2;
        if (CheckBox4.Checked = True) and (DataSet.FieldByName('Total').AsFloat > 0) then
          Proc3;
        if CheckBox5.Checked = True then
          Proc4;
        DataSet.Next;
      end;
      DataSet.EnableControls;
      frxReport1.Preview := frxPreview1;
      frxReport1.ShowPreparedReport;
      frxPreview1.SetFocus;
      Screen.Cursor := crDefault;
    end;
    
    //Proc1
    procedure TFrm1.Proc1;
    begin
      with StoredProc2 do
      begin
        Close;
        //Передача параметров в процедуру.
        ...
        Open;
      end;
      frxReport2.PrepareReport(True);
      frxReport1.PreviewPages.AddFrom(frxReport2);
    end;
    
    У меня даже не работает, вот такая самая простая процедура. Валит Access violation... и все тут.
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      frxReport1.LoadFromFile('c:\1.fr3');
      frxReport1.PrepareReport(True);
      frxReport0.PreviewPages.AddFrom(frxReport1);
      frxReport0.ShowPreparedReport;
    end;
    
  • gpigpi
    отредактировано 20:07
    Попробуйте так:
    procedure TForm1.Button1Click(Sender: TObject);
    begin
     frxReport1.LoadFromFile('c:\1.fr3');
     frxReport1.PrepareReport(True);
     frxReport0.PrepareReport; //frxReport0 должен содержать одну пустую страницу
     frxReport0.PreviewPages.AddFrom(frxReport1);
     frxReport0.PreviewPages.DeletePage(0);
     frxReport0.ShowPreparedReport;
    end;
    
  • DenDen
    отредактировано 20:07
    Разобрался, все заработало и достаточно быстро. Большое спасибо всем тем, кто откликнулся и помог разобраться мне в этом.
  • отредактировано 20:07
    Не совсем отчет печать счетов на оплату жилищно-коммунальных услуг формат A4 , в отчете нет почти никакой логики, все идет через массивы переменных. принтеры HP 9000, 50 страниц в минуту, распараллелено задание на 15 принтеров, получается весьма шустро.
  • отредактировано 20:07
    to AlexTZ может у вас в демке отчет маленький, в моем случае порядка 600-1000 мемок может в этом все дело?
  • отредактировано 20:07
    Да, скорее всего, в этом. Пара рекомендаций: мемки на страницу не класть - лучше положить их на ReportTitle. Если растягивание и сдвиг (StretchMode, ShiftMode) не нужно - отключите тоже.
  • отредактировано 20:07
    В последнем билде обнаружил ошибку в frxEngine.pas:

    procedure TfrxEngine.PrepareShiftTree(Band: TfrxBand);
    begin
    // add
    if Band.FShiftChildren.Count <> 0 then
    Exit;
    //
    ...

    из-за этого тоже падение производительности.
  • gpigpi
    отредактировано 20:07
    написал:
    Не совсем отчет печать счетов на оплату жилищно-коммунальных услуг формат A4 , в отчете нет почти никакой логики, все идет через массивы переменных.
    Если представление данных построчное, то можно попытаться массивы переменных выводить через frxUserDataset
  • отредактировано 20:07
    to gpi Спасибо но построчно не получается процентов 30 имеют свободное расположение
    to AlexTZ :спасибо за совет, обязательно попробую

Оставить комментарий

Многофункциональный текстовый редактор. Чтобы отредактировать стиль параграфа, нажмите TAB, чтобы перейти к меню абзаца. Там вы можете выбрать стиль. По умолчанию не выбран ни один стиль. Когда вы выберете текст, появится встроенное меню форматирования. Нажмите TAB, чтобы войти в него. Некоторые элементы, такие как многофункциональные вставки ссылок, картинок, индикаторов загрузки и сообщений об ошибок могут быть вставлены в редактор. Вы можете перемещаться по ним, используя стрелки внутри редактора и удалять с помощью клавиш delete или backspace.