简体   繁体   English

FastReport(RAD Studio XE7 C ++ Builder)-如何创建求和公式?

[英]FastReport (RAD Studio XE7 C++ Builder) - How do you create a sum formula?

I am using Embarcadero RAD Studio XE7, C++ Builder with FastReport 5. I create a very simple FastReport that adds up some values in a table and prints out a total. 我正在将Embarcadero RAD Studio XE7和C ++ Builder与FastReport 5一起使用。我创建了一个非常简单的FastReport,它将表中的一些值相加并打印出总计。 I cannot get the syntax for the sum formula correct, and as a result it keeps throwing an access violation error. 我无法正确获得sum公式的语法,因此,它不断抛出访问冲突错误。

To reproduce this problem in RAD Studio XE7: 要在RAD Studio XE7中重现此问题:

  1. Open RAD Studio XE7 and go to File -> New -> VCL Forms Application - C++Builder 打开RAD Studio XE7并转到文件->新建-> VCL表单应用程序-C ++ Builder
  2. Drag a TClientDataSet component named ClientDataSet1 onto the form. 将一个名为ClientDataSet1的TClientDataSet组件拖到窗体上。 Drag a TfrxReport component named frxReport1 onto the form. 将一个名为frxReport1的TfrxReport组件拖到窗体上。 Drag a TfrxDBDataset named frxDBDataset1 onto the form. 将一个名为frxDBDataset1的TfrxDBDataset拖到窗体上。
  3. Drag a TButton named Button1 onto the form, and double-click it to create an OnClick event handler. 将一个名为Button1的TButton拖到窗体上,然后双击以创建OnClick事件处理程序。
  4. Add the following lines to the Button1Click event handler: 将以下行添加到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. Compile and run the program. 编译并运行程序。 The code in the try block will throw an access violation. try块中的代码将引发访问冲突。 Why is this happening? 为什么会这样呢? What is the correct syntax to create the sum formula? 创建求和公式的正确语法是什么?

UPDATE: 更新:

I modified the code by explicitly setting a name for frxDBDataset1: 我通过显式设置frxDBDataset1的名称来修改代码:

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

I also changed the formula line to the following: 我还将公式行更改为以下内容:

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

I am still getting the access violation, though. 但是,我仍然遇到访问冲突。

I was able to run without problems the following linked example, which includes the modifications we commented before. 下面的链接示例能够毫无问题地运行,其中包括我们之前评论的修改。

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

Go to Project --> Options --> Packages --> Runtime Packages. 转到项目->选项->程序包->运行时程序包。 Set "Link with Runtime Packages" to False. 将“与运行时程序包链接”设置为False。

The default for this option is True for C++Builder, False for Delphi. 对于C ++ Builder,此选项的默认值为True,对于Delphi为False。 This explains why the equivalent code worked in Delphi, but didn't work in C++Builder. 这就解释了为什么等效代码在Delphi中有效,而在C ++ Builder中却无效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM