SUM в кросс-табе: Stack Overflow :-(

отредактировано February 2004 Раздел: FastReport 2.xx VCL
При попытке просуммировать столбцы frUserDataSet'a в cross-tab отчете,
FastReport выдает StackOverflow.

Для разработчиков:
Ошибка в функции Split.
Дело в том, что я, для удобства пользователей, описания своих таблиц заношу в словарь. Тогда они могут выбирать нужные им данные из окна "Вставка поля из БД".
Для того, чтобы срабатывал метод OnGetValue, в поле "Выражение" словаря данных приходится помещать не значение поля данных, а его название. В результате получается бесконечный цикл, так как в методе split не обрабатываются пользовательские значения (т.е. не вызывается вункция OnUserData).


Вопрос: Как добится корректной работы функции SUM в кросс-табе, или придется писать свою? Или я где-то туплю? Помогите пожалуйста!


P.S. Разговор идет о ручном построении кросс-таб-отчета, я надеюсь, Вы догадались :-)

С Уважением, Владимир.

Комментарии

  • отредактировано February 2004
    Ну чтож...
    Никто мне не ответил в этом форуме, ни посетители, ни авторы...
    Поэтому пришлось разбираться самому. Точнее, почти одному - немого оптимизма внушил мне Женя Пришко

    На самом деле, я в очередной раз столкнулся с недочетом создателей програмного продукта Fast Report, в простонароде называемом bug.

    Описание: Если в словарь переменных заносишь переменную, а в ее значение заносишь её имя (в надежде обработать по вызову OnGetValue впоследствии (особенно в вызове SUM cross-tab отчёта)) то получаешь зацикливание программы и в конце-концов сообщение: Stack Overflow.

    Объясню на примере входящем в стандартные демки FastReport'а PrnGrid:

    1)В дизайнере frReport1 добавляем бэнд Master Footer и на пересечении его с бэндом Cross Data кладём Memo с таким содержимым:
    [SUM([Cell])]
    

    2) Два раза щёлкаем мышью на CrossData чтобы назначить источник данных для MasterFooter:
    MasterFooter1: Master footer   =  ColDataset
    


    Компилируем, запускаем приложение.... Ошибка с сообщением о несоответствии конверсии типа Variant...

    Эта ошибка обходится исправлением функции OnGetValue (привожу её полностью):
    procedure TForm1.frReport1GetValue(const ParName: string;
      var ParValue: Variant);
    begin
      if AnsiCompareText(ParName, 'Cell') = 0 then
        if ColDataset.RecNo >= ColDataset.RangeEndCount
          then ParValue := 0
          else ParValue := StringGrid1.Cells[ColDataset.RecNo, RowDataset.RecNo];
    end;
    

    Запускаем... Сумма считается!!! Почти ура! Но... Пользователю хотелось бы при проектировании формы знать как называются поля данных, чтобы их можно было вставлять в форму с помощью окна выбора "Источники данных БД". Если мы работали бы с источниками BDE, то названия полей сами бы отображались в этом окне, но при работе с frUserDataSet названия полей туда приходится заносить через словарь переменных - у frUserDataSet'а нет свойств с описанием полей (что, кстати, очень бы не мешало вставить в одну из будущих версий FastReport'а).

    Итак,
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      ColDataset.RangeEnd := reCount;
      ColDataset.RangeEndCount := StringGrid1.ColCount;
      RowDataset.RangeEnd := reCount;
      RowDataset.RangeEndCount := StringGrid1.RowCount;
    
      // Следующая строка необходима для того, чтобы пользователь во время редактирования memo мог воспользоваться диалогом "Вставить поле БД", а не помнить и набирать название поля вручную
      frReport1.MixVariablesAndDBFields := True;
    
      frReport1.Dictionary.Variables.Variable[' ColDataset'] := '';
      frReport1.Dictionary.Variables.Variable['Cell'] := 'Cell';
    
      frReport1.ShowReport;
    end;
    

    Запускаем... Stack Overflow!!!! И немая сцена, хотя мы ничего предосудительного с точки зрения FastReport'а не сделали.

    Ошибка, как я говорил, кроется в исходном модуле FastReporta.
    Вот заплатка, возможно не самая лучшая из возможных, но, думаю, разработчики продукта поймут идею и реализуют её более грамотно.
    модуль fr_pars.pas:
    строка 754:
    было:  if FVariables.IndexOf(s1) <> -1 then
    стало:  if (FVariables.IndexOf(s1) <> -1) and (s1 <> FVariables[s1]) then
    
    строка  771:  
    было: else if FVariables.IndexOf(s1) <> -1 then
    стало: else if (FVariables.IndexOf(s1) <> -1) and (s1 <> FVariables[s1]) then
    
    
    Всё.
    Компилируется, запускается, считается.

    Кому что непонятно кидайте сообщения в эту ветку форума.

    P.S.
    Надеюсь, что разработчики продукта, во-первых исправят в следующих версиях эту ошибку, а во-вторых добавят описания полей к объекту frUserDataSet для более удобного пользования их замечательным продуктам.

    С Уважением, Дружинин Владимир.

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

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