可使用FindObject方法。数组
TfrxMemoView(frxReport1.FindObject('memo1')).Text:='FastReport';网络
设置frxmemoview.AllowHTMLTags:= True;在Text输入以下模块化
上标:mm2函数
下表:k6布局
触类旁通,你还可使用其余HTML标记。测试
设置两次报表后加入引号内内容 "第[Page#]页共[TotalPages#]页"操作系统
创建变量组名设计
frxreport1.Variables.Add .Name:=' '+变量组名;指针
创建变量名orm
frxreport1.Variables.AddVariable('组名,若是为不存的组或空,则为默认组,这里不须要空格',变量名,变量初始值);
例如要创建变量组Yuan,二个变量Yuan1,Yuan2,则为
frxreport1.Variables.Add .Name:=' Yuan'注意前面是空格
frxreport1.Variables.AddVariable('Yuan',Yuan1,初始值)
frxreport1.Variables.AddVariable('Yuan',Yuan2,初始值)
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])))。
一个程序中,无论多么大的程序,只要打印或预览时是模式的,则彻底能够共用一个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同样使用共用的报表组件了
不少时候,咱们但愿把对报表的控制放到报表的脚本中,一般我这样作有二个缘由:
1)可以根据字段内容的变化而使用不一样的设置,由于若是想在程序中实现这样功能,就不得不用自定义函数,函数的实现要放到程序中,函数可能须要传递不少参数,效率低下。
2)把不一样报表的控制放到脚本中,能够实现报表的模块化,程序只是简单的设置数据集的关系,并加载硬盘上的报表文件,不一样报表的不一样实现方式,显示方式,均放到报表文件中,程序简洁
,易维护,易升级。
固然,这样的缺点就是程序中加载报表时的数据集别名必须与设计报表时的别名一致。
脚本的使用与一般程序的使用并无太多的区别,就是像正常的程序那样引用控件的名称便可。
但注意对变量的使用,须要把变量名或表达式用<>括起来。
实现打印分组的页数。基本的原理就是:
1)必须使用二遍报表,由于FS算总页数就是须要二遍报表的。
2)在第一遍报表中,在GroupBand打印前,动态的创建整数型数组变量,用以保存上一个分组的总页数。
3)在最后一遍报表时,须要显示分组页数的Tfrxmemoview取得数组中的数据,但最后一个分组不会有总数,能够经过总页数减去GroupBand事件中保存的页数来取得。
4)代码中处理了一页多组,及一组多页打印分组头的状况。能够看到这些特殊处理的代码说明。
5)我特地在分组尾及页脚都用了Tfrxmemoview来显示这些数据,说明在不一样状况下的显示。
假设有数据表“用户”,字段ID为用户标识,Name为用户名,打印时要求,若是用户名为空,则打印“无用户名”,不然打印出“用户名:实际的用户”,则能够在ID的Tfrxmemoview控件的
OnAfterData事件中写以下脚本。
if<frxDBDataSet1."Name">='' then
Memo2.Text:='无用户名'
else
Memo2.Text:='用户名:[frxDBDataSet1."Name"]'
Memo2是放置用户名称数据的Tfrxmemoview控件。
这里注意,要在脚本中访问变量须要把变量用<>包括起来。
我常用下面的几个函数来实现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;
纸张是连续的带锯齿的已经印刷好的,相似于通讯公司发票这里设计的是客户销售记录。
客户有两个要求:
一、由于打印纸张是印刷的,明细记录只有8行,因此,若是明细记录若是不到8行,就将公司名称、销售记录打印在上面,下一个公司的信息打印在下一页,而不能接在该页上(呵呵,是啊,如
果接在一块儿,那印刷单就失去意义了)
二、若是销售记录超过8行,则从第9行开始的销售记录打印在下一页(所谓下一页,其实就是锯齿分割的下一*,称呼“下一份”比较妥切?),而且抬头(也就是公司名称)也要打上(若是不打印抬头,撕下了后,可能弄混淆了,不知道这一页是哪一个公司的)
问题描述标准说法是否是应该叫“打印固定行”、“强制换页”?
回答:每页打印抬头的问题,就是把包含公司名称的Band每页重复打印便可。属性中有一个的。
勾选就好了。
至于固定行,实际上设计套打时,页面大小都是固定的,每一行的高度也都是固定的,页眉与页脚也是固定的,这样设计出来的报表可打印的行数天然就是你要求的 8行了。根本不须要什么强
制换页。由于根据纸张会自动换页的。你要作的就是设计好纸张尽寸、页面布局,就得了,套打是一种最简单的打印,不用想的太复杂。
不少人认为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:=TfrxReportPage(Frx.Pages[SequencePage]);
P.PaperHeight:=R;
end;
{必须用上面的循环代码来获得准确的空白区域不能用经过计算总页数减去各页的页边距的方法来得到空白区域由于若是碰到一条记录过宽的状况致使换页,就不许确了。}
R:=Pelstomm(Frx.Engine.TotalPages*Frx.Engine.PageHeight-
Frx.Engine.FreeSpace)+R1;
P:=TfrxReportPage(Frx.Pages[SequencePage]);
P.PaperHeight:=R;
end;
在预览或打印前先调用PrintSerial便可。
frxReport1.Report.PrintOptions.Printer := '打印机名称';
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;
在打印报表的Band处的OnBeforePrint事件中添加代码:
while FreeSpace > 20 do
ShowBand(Child1)
在master band中OnBeforePrint事件中写代码:
var
vLineCount: integer;
begin
vLineCount := vLineCount + 1;
if vLineCount = 10 then
begin
vLineCount := 0;
NewPage;
end;
end;
DisplayFormat属性,其中的Kind你设置成fkNumeric,FormatStr [<frxDBDataset1."sjl">*100#n%2.2f]%”。
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.