2014-10-03 5 views
0

Я использую Embarcadero RAD Studio XE7, C++ Builder с FastReport 5. Я создаю очень простой FastReport, который добавляет некоторые значения в таблицу и выводит итог. Я не могу получить синтаксис формулы суммы правильно, и в результате он продолжает бросать ошибку нарушения прав доступа.FastReport (RAD Studio XE7 C++ Builder) - Как вы создаете формулу суммы?

Чтобы воспроизвести эту проблему в RAD Studio XE7:

  1. Open RAD Studio XE7 и перейдите в меню Файл -> New -> VCL Forms Application - C++ Builder
  2. Перетащите компонент TClientDataSet по имени ClientDataSet1 на форма. Перетащите компонент TfrxReport с именем frxReport1 в форму. Перетащите TfrxDBDataset с именем frxDBDataset1 в форму.
  3. Перетащите TButton с именем Button1 в форму и дважды щелкните его, чтобы создать обработчик события OnClick.
  4. Добавьте следующие строки в обработчик события Button1Click:

    // Create a simple dataset. 
    
    ClientDataSet1->FieldDefs->Clear(); 
    ClientDataSet1->FieldDefs->Add("ID", ftInteger, 0, false); 
    ClientDataSet1->FieldDefs->Add("Status", ftString, 10, false); 
    ClientDataSet1->FieldDefs->Add("Created", ftDate, 0, false); 
    ClientDataSet1->FieldDefs->Add("Volume", ftInteger, 0, false); 
    
    try 
    { 
        ClientDataSet1->CreateDataSet(); 
    } 
    catch(Exception& e) 
    { 
        ShowMessage("ERROR: '" + e.Message + "'"); 
        return; 
    } 
    
    ClientDataSet1->Open(); 
    for (int i = 0; i < 10; ++i) 
    { 
        ClientDataSet1->Append(); 
        ClientDataSet1->FieldByName("ID")->AsInteger = i; 
        ClientDataSet1->FieldByName("Status")->AsString = "Code" + String(i); 
        ClientDataSet1->FieldByName("Created")->AsDateTime = Now(); 
        ClientDataSet1->FieldByName("Volume")->AsInteger = Random(1000); 
    
        try 
        { 
        ClientDataSet1->Post(); 
        } 
        catch(Exception& e) 
        { 
        ShowMessage("ERROR: '" + e.Message + "'"); 
        ClientDataSet1->Close(); 
        return; 
        } 
    } 
    
    // Dataset created successfully, now create Fast Report that outputs that dataset 
    
    frxReport1->Clear(); 
    frxDBDataset1->DataSet = (TDataSet*)ClientDataSet1; 
    
    frxReport1->DataSets->Add(frxDBDataset1); 
    
    TfrxDataPage* DataPage = new TfrxDataPage(frxReport1); 
    DataPage->CreateUniqueName(); 
    
    TfrxReportPage* Page = new TfrxReportPage(frxReport1); 
    Page->CreateUniqueName(); 
    
    // set sizes of fields, paper and orientation to defaults 
    Page->SetDefaults(); 
    Page->Orientation = poPortrait; 
    
    TfrxReportTitle* HeaderBand = new TfrxReportTitle(Page); 
    HeaderBand->CreateUniqueName(); 
    HeaderBand->Top = 0; 
    HeaderBand->Height = 20; 
    
    TfrxMemoView* Memo = new TfrxMemoView(HeaderBand); 
    Memo->CreateUniqueName(); 
    Memo->Text = "Generic Report"; 
    Memo->SetBounds(0, 0, 200, 20); 
    
    TfrxHeader* ColumnHeaderBand; 
    ColumnHeaderBand = new TfrxHeader(Page); 
    ColumnHeaderBand->CreateUniqueName(); 
    ColumnHeaderBand->Top = HeaderBand->Top + HeaderBand->Height; 
    ColumnHeaderBand->Height = 20; 
    
    TfrxMasterData* DataBand = new TfrxMasterData(Page); 
    DataBand->Name = "DataBand"; 
    DataBand->DataSet = frxDBDataset1; 
    DataBand->Top = ColumnHeaderBand->Top + ColumnHeaderBand->Height; 
    DataBand->Height = 20; 
    
    TfrxMemoView* mField; 
    for (int i = 0; i < DataBand->DataSet->FieldsCount(); ++i) 
    { 
        const String fieldname = ClientDataSet1->Fields->Fields[i]->FieldName; 
    
        mField = new TfrxMemoView(ColumnHeaderBand); 
        mField->CreateUniqueName(); 
        mField->SetBounds(i * 100, 0, 100, 20); 
        mField->Text = fieldname; 
        mField->HAlign = haCenter; 
    
        // Now do the actual data 
        mField = new TfrxMemoView(DataBand); 
        mField->CreateUniqueName(); 
        mField->DataSet = DataBand->DataSet; 
        mField->DataField = fieldname; 
        mField->SetBounds(i * 100, 0, 100, 20); 
        mField->HAlign = haRight; 
    } 
    
    // Now do footer band. This will hold the total 
    TfrxBand* FooterBand = new TfrxFooter(Page); 
    FooterBand->CreateUniqueName(); 
    FooterBand->Top = DataBand->Top + DataBand->Height; 
    FooterBand->Height = HeaderBand->Height; 
    
    TfrxMemoView* totals = new TfrxMemoView(FooterBand); 
    totals->Top = 0; 
    totals->Left = 0; 
    totals->Height = 20; 
    totals->Align = baWidth; 
    
    bool is_error = false; 
    try 
    { 
        // ALL OF THESE LINES CAUSE THE ACCESS VIOLATION 
    
        // Create a summation function that displays the volume total 
        totals->Text = "Totals: [Sum(<ClientDataSet1.Volume>, MyDataBand, 1)]"; 
        //totals->Text = "Totals: [Sum(<ClientDataSet1.'volume'>,MyDataBand,1)]"; 
        //totals->Text = "Totals: [Sum(<ClientDataSet1.\"volume\">,MyDataBand,1)]"; 
        //totals->Text = "Totals: [Sum(<ClientDataSet1.""volume"">,MyDataBand,1)]"; 
        //totals->Text = "Totals: [Sum(<ClientDataSet1.''volume''>,MyDataBand,1)]"; 
        //totals->Text = "Totals: [Sum(<ClientDataSet1.\'volume\'>,MyDataBand,1)]"; 
    } 
    catch(Exception& e) 
    { 
        ShowMessage("ERROR: '" + e.Message + "'"); 
        is_error = true; 
    } 
    
    if (!is_error) 
    { 
        frxReport1->ShowReport(true); 
    } 
    
    ClientDataSet1->Close(); 
    
    ShowMessage("Program complete!"); 
    
  5. скомпилировать и запустить программу. Код в блоке try приведет к нарушению доступа. Почему это происходит? Каков правильный синтаксис для создания формулы суммы?

UPDATE:

Я изменил код, явно устанавливая имя frxDBDataSet1:

frxReport1->Clear(); 
    frxDBDataset1->DataSet = (TDataSet*)ClientDataSet1; 
    frxDBDataset1->Name = "frxDBDataset1"; // line added 
    frxReport1->DataSets->Add(frxDBDataset1); 

Я также изменил формулу линию следующее:

totals->Text = "Totals: [Sum(<frxDBDataset1.\"Volume\">, DataBand, 1)]"; 

Я все еще получаю нарушение прав доступа.

+0

Две вещи: 1) Текст для Totals упоминает «MyDataBand», но ваша группа данных на самом деле называется «DataBand». 2) Он не показывает в вашем коде, что имя для набора данных. Это свойство frxDBDataset1. Он не обязательно должен иметь то же имя, что и фактический набор данных. - Синтаксис, по крайней мере тот, который у меня есть и работает, выглядит примерно так: [SUM (, BandName, 1)] –

+0

После внесения этих изменений я все еще получаю ошибку «Нарушение прав доступа». См. Обновление выше. – MrSnrub

+0

Какая версия FR вы используете? Мне удалось запустить программу с несколькими изменениями (все они являются тем, что мы обсуждали ранее) без каких-либо проблем. Я запускаю XE5 с FR 4.15.5. –

ответ

0

Перейти к Project -> Настройки -> Пакеты -> Runtime Packages. Установите «Ссылка с пакетами времени выполнения» на False.

Значение по умолчанию для этой опции: True для C++ Builder, False для Delphi. Это объясняет, почему эквивалентный код работал в Delphi, но не работал в C++ Builder.

0

Мне удалось запустить без проблем следующий связанный пример, который включает изменения, которые мы прокомментировали ранее.

https://www.dropbox.com/s/6grmajvoy9ijxfh/SO_test1.7z?dl=0

+0

У меня нет RAD Studio XE5, так что проект давал несколько недостающих ошибок библиотеки, когда я пытался их скомпилировать.Но я скопировал код обработчика Button OnClick и вставил его в свой собственный образец кода проекта. Он все еще выдавал ошибку нарушения доступа. – MrSnrub

+0

@MrSnrub Я склонен думать, что это ошибка с FR 5, но я не имею ее сейчас, чтобы протестировать. Вы пробовали связаться со службой поддержки FR? Код, как я уже сказал, отлично работает с XE5 и FR 4, я думаю, что он должен отлично работать с FR 5 - если они несколько не изменили поддержку построенных отчетов во время выполнения, но этот особый код не должен заставить FR давать AV , Кстати, перед изменением имени набора данных и имени группы у меня появились некоторые ошибки, но они четко заявили, в чем проблема: не удалось найти набор данных X и неизвестную полосу Y. –