1. 程式人生 > >FastReport 使用技巧篇

FastReport 使用技巧篇

per for gis isa disabled 麻煩 一起 單獨 其中

使用技巧篇

1.FastReport中如果訪問報表中的對象? 可以使用FindObject方法。 TfrxMemoView(frxReport1.FindObject(‘memo1‘)).Text:=‘FastReport‘; 2.FastReport中如何使用上下標? 設置frxmemoview.AllowHTMLTags:= True;在Text輸入如下 上標:mm<sup>2</sup> 下表:k<sub>6</sub> 舉一反三,你還可以使用其他HTML標記。 3.FastReport中如何打印總頁數? 設置兩次報表後加入引號內內容 "第[Page#]頁共[TotalPages#]頁" 4.FastReport中如何動態加入變量及變量組? 建立變量組名 frxreport1.Variables.Add .Name:=‘ ‘+變量組名; 建立變量名 frxreport1.Variables.AddVariable(‘組名,如果為不存的組或空,則為默認組,這裏不需要 空格‘,變量名,變量初始值); 例如要建立變量組Yuan,二個變量Yuan1,Yuan2,則為 frxreport1.Variables.Add .Name:=‘ Yuan‘註意前面是空格 frxreport1.Variables.AddVariable(‘Yuan‘,Yuan1,初始值) frxreport1.Variables.AddVariable(‘Yuan‘,Yuan2,初始值) 5.FastReport中如何加入自定義函數? Fastreport可以自己加入需要的函數,來實現特定的功能。過程就是: 1)添加函數到報表中。 frxreport1.AddFunction(‘完整的函數聲明‘); 如有一個自定義函數,為GetName(Old:String):String;這個函數通過數據集的一個字段,得到另一個返回值。 則語句為:frxreport1.AddFunction(‘Function GetName(Old:String):String;‘); 2)腳本中使用函數。 在腳本中或報表中使用自定義函數,就像使用其它Fastreport內置函數一樣。 3)程序中處理函數。 使用函數是通過frxreport1的OnUserFunction函數來實現的。 OnUserFunction的聲明如下:Function(constMethodName: String;var Params: Variant): Variant; 比如上面的函數,首先要有一個函數,這個函數是GetName的實現部分。如有一個在程序中實現的函數。 function RealGetName(Old:String):String;這個函數名是無所謂的,也可以是GetName。 在OnUserFunction的事件處理中有如下代碼即可完成自定義函數在報表中的使用。 if CompareText(MethodName,‘GetName‘)=0 thenResult:=RealGetName(VarToStr(Params[0])); 我一般都是使用CompareText來比較函數名,因為我發現二個版本的Fastreport,一個是 MethodName全部自動變成了小寫,一個是全部自動變成了大寫,所以幹脆用CompareText來比較, 肯定不會出錯。 如果有多個參數,則依次傳遞Params[0],Params[1]即可,要保持順序一致。 這裏要註意一點,如果參數為指針,則不能直接使用Pointer(Integer(Params[0]))。因為實際傳 遞過來的是指針的整數值,可以使用Pointer(StrToInt(VarToStr(Params[0])))。 6.FastReport中如何共用TFrxreport及TfrxDBDataSet? 一個程序中,不管多麽大的程序,只要打印或預覽時是模式的,則完全可以共用一個TFrxreport 變量及幾個TfrxDBDataSet。只不過,要註意完成一個報表程序的步驟,主要是下面幾步 1)清除報表,得到一個全新的報表內容。 Frxreport1.clear。 2)設置要使用的TfrxDBDataSet的別名,如果不需要可以省略這一步,但一般最好不同的報表用不 同的別名。 註意這一步要在加載報表文件之前,因為一般設計報表文件時已經包含了別名信息。 frxDBDataSet1.UserName:=別名; 3)加載報表或動態建立一個TfrxReportPage。 Frxreport1.LoadFromFile(報表文件的完整文件名); 4)關聯TfrxDBDataSet與TDataset,並設置要使用哪些TfrxDBDataSet。 Frxreport1.DataSets.Clear;//先清除原來的數據集 frxDBDataSet1.DataSet:=dataset1;//關聯Fastreport的組件與TDataset數據集。 Frxreport1.DataSets.Add(frxDBDataSet1);//加載關聯好的TfrxDBDataSet到報表中。 經過這幾步後,就可以像單獨使用一個Tfrxreport一樣使用共用的報表組件了 7.FastReport中如何使用腳本,腳本中使用變量? 很多時候,我們希望把對報表的控制放到報表的腳本中,通常我這樣做有二個原因: 1)能夠根據字段內容的變化而使用不同的設置,因為如果想在程序中實現這樣功能,就不得不用 自定義函數,函數的實現要放到程序中,函數可能需要傳遞很多參數,效率低下。 2)把不同報表的控制放到腳本中,可以實現報表的模塊化,程序只是簡單的設置數據集的關系, 並加載硬盤上的報表文件,不同報表的不同實現方式,顯示方式,均放到報表文件中,程序簡潔 ,易維護,易升級。 當然,這樣的缺點就是程序中加載報表時的數據集別名必須與設計報表時的別名一致。 腳本的使用與通常程序的使用並沒有太多的區別,就是像正常的程序那樣引用控件的名稱即可。 但註意對變量的使用,需要把變量名或表達式用<>括起來。 實現打印分組的頁數。基本的原理就是: 1)必須使用二遍報表,因為FS算總頁數就是需要二遍報表的。 2)在第一遍報表中,在GroupBand打印前,動態的建立整數型數組變量,用以保存上一個分組的 總頁數。 3)在最後一遍報表時,需要顯示分組頁數的Tfrxmemoview取得數組中的數據,但最後一個分組 不會有總數,可以通過總頁數減去GroupBand事件中保存的頁數來取得。 4)代碼中處理了一頁多組,及一組多頁打印分組頭的情況。可以看到這些特殊處理的代碼說明 。 5)我特意在分組尾及頁腳都用了Tfrxmemoview來顯示這些數據,說明在不同情況下的顯示。 8.FastReport中如何在腳本中根據字段名改變Tfrxmemoview的內容? 假設有數據表“用戶”,字段ID為用戶標識,Name為用戶名,打印時要求,如果用戶名為空,則 打印“無用戶名”,否則打印出“用戶名:實際的用戶”,則可以在ID的Tfrxmemoview控件的 OnAfterData事件中寫如下腳本。 if<frxDBDataSet1."Name">=‘‘ then Memo2.Text:=‘無用戶名‘ else Memo2.Text:=‘用戶名:[frxDBDataSet1."Name"]‘ Memo2是放置用戶名稱數據的Tfrxmemoview控件。 這裏註意,要在腳本中訪問變量需要把變量用<>包括起來。 9.FastReport中如何動態調整高度? 我經常使用下面的幾個函數來實現Band及Tfrxmemoview高度的動態調整,需要註意的是:下面的 函數只能調整一個Band中多行的最後一行,如果只有一行(多數情況下應該是這樣)就無所謂了 ,而且這是在寬度已經固定的前提下。在想要調整高度的Band的OnBeforePrint事件中寫 SetMemo(Sender);,代碼如下,粘貼到代碼頁中就可以使用。 下面的代碼也可以演變一些,實現動態寬度等。我多處都判斷了Tag是否為7635,因為我經常需要 單獨調用其中的某個函數。 //7635為保留數字,表示不作任何調整,通常用在多行的最上方 function Biger(Old:Extended):Integer; begin Result:=Trunc(Old); if Frac(Old)>0 then Result:=Result+1; end; procedure JustHeight(Sender:TfrxComponent); var RealHeight:Integer; begin RealHeight:=Biger(TFrxMemoView(Sender).CalcHeight+TFrxMemoView(Sender).Top); ifBiger(TfrxBand(Sender.Parent).Height)<RealHeight then begin //若MEMO的高度小於BAND但計算高度大於BAND,則在調整BAND的函數中就會被調整 TfrxBand(Sender.Parent).Height:=Biger(RealHeight); JustBandHeight(Sender.Parent); end else TfrxMemoView(Sender).Height:=TfrxBand(Sender.Parent).Height -TfrxMemoView(Sender).Top; end; procedureJustBandHeight(Sender:TfrxComponent); var I:Integer; begin for I:=0 to Sender.Objects.Count-1 do if TObject(Sender.Objects.Items[I]) isTFrxMemoView then ifTFrxMemoView(Sender.Objects.Items[I]).Tag=7635 then Continue else //如果小才改變,如果大則不能改變 ifBiger(TfrxMemoView(Sender.Objects.Items[I]).Height+ TfrxMemoView(Sender.Objects.Items[I]).Top)<>Biger(TfrxBand(Sender).Height)then TfrxMemoView(Sender.Objects.Items[I]).Height:= Biger(TfrxBand(Sender).Height-TfrxMemoView(Sender.Objects.Items[I]).Top); end; procedure JustMemo(Sender:TfrxComponent); begin if not Engine.FinalPass then Exit; if Sender.Tag<>7635 then JustHeight(Sender); end; procedure SetMemo(Sender:TfrxComponent); var I:Integer; begin for I:=0 to Sender.Objects.Count-1 do if TObject(Sender.Objects.Items[I]) isTFrxMemoView then ifTfrxMemoView(Sender.Objects.Items[I]).Tag<>7635 then TfrxMemoView(Sender.Objects.Items[I]).OnAfterData:=‘JustMemo‘; end; 10.FastReport中如何實現套打? 紙張是連續的帶鋸齒的已經印刷好的,類似於通信公司發票這裏設計的是客戶銷售記錄。 客戶有兩個要求: 1、因為打印紙張是印刷的,明細記錄只有8行,所以,如果明細記錄如果不到8行,就將公司名稱 、銷售記錄打印在上面,下一個公司的信息打印在下一頁,而不能接在該頁上(呵呵,是啊,如 果接在一起,那印刷單就失去意義了) 2、如果銷售記錄超過8行,則從第9行開始的銷售記錄打印在下一頁(所謂下一頁,其實就是鋸齒 分割的下一*,稱呼“下一份”比較妥切?),並且擡頭(也就是公司名稱)也要打上(如果不打 印擡頭,撕下了後,可能弄混淆了,不知道這一頁是哪個公司的) 問題描述標準說法是不是應該叫“打印固定行”、“強制換頁”? 回答:每頁打印擡頭的問題,就是把包含公司名稱的Band每頁重復打印即可。屬性中有一個的。 勾選就行了。 至於固定行,實際上設計套打時,頁面大小都是固定的,每一行的高度也都是固定的,頁眉與頁 腳也是固定的,這樣設計出來的報表可打印的行數自然就是你要求的 8行了。根本不需要什麽強 制換頁。因為根據紙張會自動換頁的。你要做的就是設計好紙張尺寸、頁面布局,就得了,套打 是一種最簡單的打印,不用想的太復雜。 11.FastReport中如何實現連續打印? 很多人認為Fr不能實現連續打印,以為只能通過自己寫函數調用打印函數來實現連續打印,實際 上,Fr可以輕易的實現連續打印,同時,實現時又是非常簡單,你甚至可以在你的程序的打印設 置中簡單的讓客戶選擇是否連續打印,其它都可以保持不變。 function PelsTomm(Pels:Extended):Extended; begin Result:=Pels/Screen.PixelsPerInch*25.4; end; procedurePrintSerial(Frx:TFrxReport;SequencePage:Byte=0); var P:TfrxReportPage; R,R1:Extended; begin {必須是二遍報表,否則無法計算總頁數。 下面的方法只適用於沒有頁腳的情況,因為如果有頁腳的話 FreeSpace就始終為0了。可以用報表腳來代替。 因為是連續打印,也可以看作只有一頁,報表腳也就相當於頁腳了} if not Frx.Engine.DoublePass then Exit; //SequencePage指要連續打印的頁面,普通報表就是0 P:=TfrxReportPage(Frx.Pages[SequencePage]); R1:=P.TopMargin+P.BottomMargin; while Frx.PrepareReport do begin if (Frx.Engine.TotalPages<=1) thenBreak; R:=Pelstomm(Frx.Engine.TotalPages*Frx.Engine.PageHeight- Frx.Engine.FreeSpace)+R1; P.PaperHeight:=R; end; {必須用上面的循環代碼來得到準確的空白區域 不能用通過計算總頁數減去各頁的頁邊距的方法來獲得空白區域 因為如果碰到一條記錄過寬的情況導致換頁,就不準確了。} R:=Pelstomm(Frx.Engine.TotalPages*Frx.Engine.PageHeight- Frx.Engine.FreeSpace)+R1; P.PaperHeight:=R; end; 在預覽或打印前先調用PrintSerial即可。 12.如何在程序中指定打印機名稱? frxReport1.Report.PrintOptions.Printer := ‘打印機名稱‘; 13.如何使用打印機直接打印? implementation uses Printers; {$R *.dfm} procedure TForm1.Button1Click(Sender:TObject); begin Printer.PrinterIndex := 0;{網絡打印機也是要安裝在你本地的操作系統中的,直接使用順序 試試吧} Printers.Printer.SetPrinter(‘HP1020‘,‘HP1020‘,‘LPT1‘,0);{打印機名字,驅動,端口等, 自查,我是用虛擬打印機測試的} Printers.Printer.BeginDoc; Printers.Printer.Canvas.TextOut(10,10,‘打印這一行字‘); Printers.Printer.EndDoc; end; 14.如何打印空白處? 在打印報表的Band處的OnBeforePrint事件中添加代碼: while FreeSpace > 20 do ShowBand(Child1) 15.如何打印指定行數後換頁? 在master band中OnBeforePrint事件中寫代碼: var vLineCount: integer; begin vLineCount := vLineCount + 1; if vLineCount = 10 then begin vLineCount := 0; NewPage; end; end; 16.fastreport中如何把數據顯示為百分比 DisplayFormat屬性,其中的Kind你設置成fkNumeric,FormatStr [<frxDBDataset1."sjl">*100#n%2.2f]%”。 17.FastReport如何打印表格式的空行? var PageLine: integer; //在頁列印到第幾行 PageMaxRow: integer=15; //設定每頁列數 procedure MasterData1OnBeforePrint(Sender:TfrxComponent); begin PageLine := <Line> mod PageMaxRow; if(PageLine = 1) and (<line> > 1) then Engine.newpage; child1.visible := False; end; //Footer1高度設為0 procedure Footer1OnBeforePrint(Sender:TfrxComponent); var i:integer; begin i:= iif(PageLine=0, PageMaxRow, PageLine); child1.visible := True; while i < PageMaxRow do begin i:= i + 1; Engine.ShowBand(Child1); //印空白表格 end; child1.visible := False; end; begin end. ======================================================================== 早期版本 ---------------- 使用自定義函數---------------------------------------- Q: 我怎樣添加我的自定義函數? A: 使用TfrReport.OnUserFunction 事件. 這裏有一個簡單的例子: procedureTForm1.frReport1UserFunction(const Name: String; p1, p2, p3: Variant; var val: Variant); begin if AnsiCompareText(‘SUMTOSTR‘, Name) = 0 then val :=My_Convertion_Routine(frParser.Calc(p1)); end; 然後,你就可以在報表(任何表達式或腳本)的任何地方使用 SumToStr 函數了。 Q: 但是它僅僅能工作在一個TfrReport組件中。可我想在任何地方(在所有的TfrReport組件中) 使用的我的自定義函數? A: 使 OnUserFunctionevent 句柄作為所有組件的公用句柄。如果你不能做到這一點,你需要創 建函數庫: type TMyFunctionLibrary =class(TfrFunctionLibrary) public constructor Create; override; procedure DoFunction(Fno: Integer; p1, p2,p3: Variant; var val: Variant); override; end; constructor TMyFunctionLibrary.Create; begin inherited Create; with List do begin Add(‘DATETOSTR‘); Add(‘SUMTOSTR‘); end; end; procedureTMyFunctionLibrary.DoFunction(Fno: Integer; p1, p2, p3: Variant; var val: Variant); begin val := 0; case Fno of 0: val :=My_DateConvertion_Routine(frParser.Calc(p1)); 1: val := My_SumConvertion_Routine(frParser.Calc(p1)); end; end; 要註冊函數庫,調用 frRegisterFunctionLibrary(TMyFunctionLibrary); 要卸載函數庫,調用 frUnRegisterFunctionLibrary(TMyFunctionLibrary); Q: 我怎樣將我的函數添加到函數列表中 (用表達式生成器)? A: 使用 frAddFunctionDesc 過程 (在FR_Class 單元中): frAddFunctionDesc(FuncLib, ‘SUMTOSTR‘, ‘Myfunctions‘, ‘SUMTOSTR(<Number>)/Converts number toits verbal presentation.‘); 註意: "/" 符號是必須的! 它從它的描述中分隔函數語法。 FuncLib 被聲明為你自己的函數庫 (如果你不使用函數庫可以將其設置為nil). 當函數庫未註冊 時,所有它的函數將自動從函數列表中刪除。 ---------------- 使用變量------------------------------------- Q: 我怎樣編程實現填充變量列表(在數據詞典中)? A:數據詞典中的所有變量及分類都被存儲在TfrReport.Dictionary.Variables 中. with frReport1.Dictionary do begin // 創建分類(名稱用空白) Variables[‘ New category‘] := ‘ ‘; // 創建變量 Variables[‘New Variable‘] := ‘CustomerData.Customers."CustNo"‘; Variables[‘Another Variable‘] := ‘Page#‘; end; Q: 我定義了字符串變量: with frReport1.Dictionary do Variables[‘Month‘] := ‘March‘; 但是當我運行報表是,出現了錯誤,為什麽? A: 因為 FastReport 假定數據詞典中的字符串變量值是一個表達式,它需要分析、計算它。 可以使用其它的方法: with frReport1.Dictionary do Variables[‘Month‘] := ‘‘‘‘ +‘March‘ + ‘‘‘‘; 或者, 使用 frVariables 來傳輸固定數據到報表。 Q: 我不想在數據詞典中顯示某些數據集? A: 使用TfrReport.Dictionary.DisabledDatasets: with frReport1.Dictionary do begin // 關閉該數據集 DisabledDatasets.Add(‘CustomerData.Bio‘); // 或者, 關閉整個數據模塊/窗體 DisabledDatasets.Add(‘CustomerData*‘); end; Q: 我怎樣將數據傳送到報表? A: 有幾個方法可以實現它. 第一是使用全局對象frVariables (在 FR_Class 單元中被定義): frVariables[‘My variable‘] := 10; 這段代碼創建了一個名稱為“My variable”,值為 10 的變量。這是最好的傳輸固定數據的報表 的方法。 第二種方法是使用 TfrReport.OnGetValue 事件. 這可以使用這個方法來傳送動態數據、記錄等 。 procedure TForm1.frReport1GetValue(ParName:String; var ParValue: Variant); begin if ParName = ‘MyField‘ then ParValue := Table1MyField.Value; end; 最後, 第三種方法是通過編程在數據詞典中定義變量(可以參考以前的問題): with frReport1.Dictionary do begin Variables[‘MyVariable‘] :=‘CustomerData.Customers."CustNo"‘; Variables[‘Another Variable‘] := ’10’; end; Q: 我能在報表和程序間傳送數據嗎? A: 使用 frVariables 對象. 如果你在報表的任何對象的腳本中寫入以下代碼: MyVariable := 10 那麽,在你的程序中,你可以使用以下代碼來獲取 MyVariable 的值: v := frVariables[‘MyVariable‘]; ----------------腳本(FastReport Pascal) --------------------------------- Q: Band 中是否可以使用腳本? A: 當然. 選擇 band ,然後按Ctrl+Enter 或在對象瀏覽器中選擇 "OnBeforePrint" 屬性。 Q: 報表頁中是否可以使用腳本? A: 當然. 選擇頁 (在空白處單擊) ,然後在對象瀏覽器中選擇"OnBeforePrint" 屬性。如果該 頁是一個對話框窗體,那麽這個屬性就是 "OnActivate". Q: 我有兩個對象: Memo1 和 Memo2. 我能否在 Memo1 的腳本中調用 Memo2 的屬性和方法? A: 當然, 例如,你可以這樣做: 對象名.屬性名. Q: 在腳本中,我可以使用對象的哪些屬性? A: 幾乎所有你能在對象瀏覽器中看到的屬性。例如,可以使用 Font .Name, Font.Size等來存取 字體屬性。 ---------------- 其它問題-------------------------------------------- Q: 怎樣改變多頁報表中某一頁的順序? A: 拖動頁標簽到目的位置。 Q: 我想查看所有的字段及變量,我想在報表中使用列表來實現它? A: 設置TfrReport.MixVariablesAndDBFields := True.所有的數據字段及變量可在“插 入數據字段”對話框中可存取了。 Q: 我不想顯示導入選項對話框? A: 在導入組件(比如,TfrTextExport)中設置所有必需的選項,然後通過設置ShowDialog屬性為 False來關閉此對話框。 Q: 為什麽 TotalPages變量不起作用? 它總是返回 0. A: 在你的報表中設置 Two-pass 選項. 要設置它,你需要在報表設計器的“文件”菜單中,打開 “報表選項”對話框。 Q: 我用BLOB字段來存儲我的報表。當我運行報表設計器時,它顯示我的報表未命名? A: 在運行報表設計器前,這樣做: frReport1.FileName := ‘Name of my report‘; Q: 我想在重新定義報表設計器中的“打開”及“保存”按鈕的功能? A: 查看 TfrDesigner 組件. 它有幾個必需的事件:OnLoadReport 和 OnSaveReport. 這裏有一小段代碼例子: procedureTForm1.frDesigner1LoadReport(Report: TfrReport; var ReportName: String; var Opened:Boolean); begin with MyOpenDialog do begin Opened := ShowModal = mrOk; if Opened then begin Report.LoadFromBlobField(…); ReportName := …; end; end; end; procedureTForm1.frDesigner1SaveReport(Report: TfrReport; var ReportName: String; SaveAs: Boolean;var Saved: Boolean); begin if SaveAs then with MySaveDialog do begin Saved := ShowModal = mrOk; if Saved then begin Report.SaveToBlobField(…); ReportName := …; end; end else Report.SaveToBlobField(…); end; Q: 在 QR 中, 我可以寫這樣的代碼:QRLabel1.Caption := ’Some text’. 我可以用FR這樣做 嗎? A: FR 對象並不是一個組件 (這並不像 QR, RB).但使用 TfrReport.FindObject 方法可以通過 對象名稱找到該對象。 var t: TfrMemoView; begin t :=TfrMemoView(frReport1.FindObject(’Memo1’)); if t <> nil then t.Memo.Text := ’FastReport’; end; Q: 我想在用戶預覽(TfrPreview組件)中自定義熱鍵? A: 這個組件有個窗口: Tform 屬性. 將自定義句柄指定到Window.OnKeyDown 屬性. Q: Fast Report 2.4 不能裝載FreeReport 2.21 文件? A: 這僅需要使用16進制數改變報表文件的第一字節,然後在源代碼中修改下面的部分。在這些修 改之後,裝載報表並保存它. 最後,返回到源代碼處. FR_Class: function ReadString(Stream: Tstream):String; begin { if frVersion >= 23 then} Result := frReadString(Stream) {else Result := frReadString22(Stream);} end; procedure ReadMemo(Stream: Tstream; Memo:Tstrings); begin { if frVersion >= 23 then} frReadMemo(Stream, Memo){ else frReadMemo22(Stream, Memo);} end; FR_Utils: procedure frReadMemo(Stream: Tstream; l:Tstrings); var s: String; b: Byte; n: Word; begin l.Clear; l.Text := frReadString(Stream); exit; Stream.Read(n, 2); if n > 0 then repeat Stream.Read(n, 2); SetLength(s, n); Stream.Read(s[1], n); l.Add(s); Stream.Read(b, 1); until b = 0 else Stream.Read(b, 1); end; function frReadString(Stream: Tstream):String; var s: String; n: Integer; b: Byte; begin Stream.Read(n, 4); SetLength(s, n); Stream.Read(s[1], n); if (n > 0) and (s[n] = #$0A) then SetLength(s, n - 2); // Stream.Read(b, 1); Result := s; end; Q: 怎樣不在打印預覽中打印報表? A: 這裏有一段代碼: frReport1.PrepareReport; frReport1.PrintPreparedReport(‘‘, 1, True,frAll); 或 frReport1.PrintPreparedReportDlg; Q: 我想在報表中旋轉圖片。問題是這張圖片是由我的應用程序生成的。是否有方法可以在打印前 將這幅圖片裝載到報表中? A: 使用TfrReport.OnBeforePrint 事件: if View .Name = ‘Picture1‘ then TfrPictureView(View).Picture.LoadFromFile(…) 或 .Assign 或 .你所想要做的任何事情 FastReport套打全攻略 //以設計套打行為6行為例進行說明 一、定義變量 TaoDa 0 是套打1 不套打 cPage系統變量頁# caPage系統變量總頁數 二、TfrPage.OnBeforePrint事件中寫 { ifTaoDa = ‘0‘ then begin title.visible:=false; //不用打印的設置Visible為False; danweiv.frametyp := 0; //只打印數據的不需要打印邊框的設置 frametyp 為 0; ... end; i :=0 ; //定義一個變量並進行初始化。 } 二、主項數據.OnBeforePrint事件中寫 { ifTaoDa = ‘0‘ then begin i:= i + 1; bm.memo := i; if(i > 5 ) then if ((i-1) mod 6 ) = 0 then newpage; end; } 三、主項腳.OnBeforePrint事件中寫 { j :=i mod 6; if j<> 0 then begin for k := j to 5 do begin ShowBand(Child1); //Child1是子的名稱 顯示空白行 end; end; } 四、欄目腳.OnBeforePrint事件中寫 { ifcpage <> capage then begin shi.memo := ‘‘; //十 bai.memo := ‘‘; //百 qian.memo := ‘‘; //千 wan.memeo := ‘‘; //萬 end else begin shi.memo := v1; bai.memo := v2; qian.memo := v3; wan.memo := v4; end; } 這段代碼是用來控制在有多頁情況下,在最後一頁上顯示總金額。 其中:v1,v2,v3,v4 是自定義變量。 報表結構組成: 欄目頭 //畫報表的標頭 主項數據 //顯示的數據,會與數據源進行綁定 主項腳 //什麽也不用放,只用來控制 visible := false; 子 //畫出空白行顯示的組件 欄目腳 //顯示總的金額、數量 頁腳//顯示頁數 調用方法: frReportA.LoadFromFile(s); s 是文件 frReportA.Dictionary.Variables[‘taoda‘]:=‘1‘; 進行查詢 打印: frReportA.PrepareReport; frreportA.PrintPreparedReport(‘‘,1,true,frall); 預覽: frReportA.ShowReport; FastReport打印CxGrid數據 用慣了FastReport,就不願意再使用其他的Print Component。用FastReport打印CxGrid Filter後的數據,網上一直沒有很好的辦法和例程。看到有將CxGrid的Fileter Text取出後再賦給DataSet的說明,沒有具體去試驗,太麻煩。如此著名的Component肯定有解決此問題的方法。於是今天到Dev Express英文站點去瀏覽了一番,在該站上搜索了一下,居然出來N多此問題的提問者,看了幾個這類的問題後,終於解決了。 解決此問題可以使用以下方法: 1、將View的datacontroller.filter.autodatasetfilter屬性設為True。 此方法需要DataSet支持才能設置。 2、是在FastReport的frDBDataSet的CheckEofEvent裏寫如下代碼: EOF := frUserDataset1.RecNo >=Grid.ViewData.RecordCount; 在frReport的GetValue Event裏寫代碼: if ParName=‘Field1‘ then ParValue :=Grid.ViewData.Records[frDataset1.RecNo].Values[2]); 此代碼也可這樣寫: ParValue:=Grid.ViewData.Records[frDataset1.RecNo].Values[View.GetColumnByFieldName(ParName).Index]); ReportMachine 1.如何使用代碼指定打印機? RMReport1.LoadFromFile(‘Untitled.rmf‘); rmreport1.PrinterName:=‘\\192.168.10.1\HP LaserJet 1022‘;

FastReport 使用技巧篇