不用控件如何做按页打印(打印某页到某页的内容)(70分)

  • 主题发起人 主题发起人 恍然大晤
  • 开始时间 开始时间

恍然大晤

Unregistered / Unconfirmed
GUEST, unregistred user!
[red]我用PRINTER类做了一个打印程序,网格、打印方向设置都实现了,唯按页打印(即打印某页到某页的内容)不知如何编写,请各位大虾指教(请讲详细些,最好附代码),江湖救急!多谢,多谢!!!........[/red]
 
和你一样,我也想知道,帮你顶
 
不说清楚,没法子帮啊,如果是打印数据,在数据里先进行选择就可以了啊
 
比如TDBgrid中的数据全部有两页,我想打印第2页,该怎么做
 
首先生成第一页和第二页两个临时文件(或临时数据库)(文件名按页序号),在打印时按页码读取相应的临时文件(或临时数据库)再打印(或预览)应可以了。
我的如下程序实现了此功能:http://www.onlinedown.net/soft/25472.htm
 
不过这种方法也太原始和太麻烦了(和用API做差不多),我的上述程序的打印代码有5000行左右,我这样说可能你不相信吧,就说页面设置的代码量都有1000多行的,我整个软件的程序才15000多行,打印(含预览代码)就占了1/3。
如果程序的模块少的话,可以使用TPrint类这样做,如果模块多的话,这样做,不累死你才怪,还是用报表控件吧。不过这样做的话你可以学习很多东西,不管是做多么复杂的打印,都是小菜一碟。
 
用这种方法做完一个打印程序以后,看王寒松的eReport,也不过如此(我闪,谁扔我西瓜!!!)。
 
哥们,你的方法有点不科学吧,如果有100页的数据,还要生成100个临时文件呀
 
我把打印模块作成共享了,不能累死
 
一、其实生成100个临时文件没有什么,每个文件几个k至多几十个k,没有什么。
二、如果模块多的话,这种办法不是很科学,我不是说过:“如果程序的模块少的话,可以使用TPrinter类这样做,如果模块多的话,这样做,不累死你才怪,还是用报表控件吧。”。以后,如果不用打印控件的话,我会考虑用类继承、重载的方法来进行打印编程的。
三、就算你把打印模块共享,代码量也少不了多少的(其实,我的软件中,我已经将共用的代码使用函数进行共享了,但代码量还是这么多),用控件可以减少代码量,但缺少点灵活性(如果用些技巧的话,使用打印控件代码,还是可以作得很灵活,这样的话,和我的方法也没有多大区别。事实上,只要用代码来进行灵活的控制,不管使不使用控件,都是很麻烦的)。
 
生成的临时文件要在退出程序后删除。
 
你也可以生成内存文件的方式进行打印,这样可加快打印或预览的反应速度,但如果有几k页话,我建议还是采取磁盘临时文件的方式进行打印。
我印象中原来的王寒松的eReport是采用内存文件的方式进行打印的,但为了有更好的兼容性,改成了磁盘临时文件的方式(因为如果报表有几k页的话,需要很多的内存,如果内存不足,很容易出现问题)。
 
方式二是生成一个打印临时数据库,数据里保存分页的标志(比如第2页从几行开始,到几行结束)和打印数据及打印参数。但这种方式仅适用于打印有规则的表格,对于文档、表格混排的打印情况不适合,文档、表格混排的打印最好还是生成自定义格式的临时文件再打印,此临时文件可包括打印的数据、打印配置等。
 
[red]你说的临时文件是个什么样的文件,我不懂,能解释一下,它如何生成,多谢指教!!![/red]
 
生成表格临时文件:
procedure SaveTabDrawFile(PageNumber: Integer;
TabNumber: Integer);
var
TargetFile: TFileStream;
FileFlag: WORD;
PageFlag: Integer;
iLineHeight: Integer;
iTotalLineCount, iMaxLineCountPerPage, iThisPageLineCount: Integer;
iPageCount: Integer;
Count: Integer;
I, J, K: Integer;
TempPChar: array[0..3000] of char;
FileName: string;
strFileDir: string;
sTempStr: String;
begin
strFileDir := MainDir;
// + '/';
if copy(strfiledir, length(strfiledir), 1) <> '/' then
strFileDir := strFileDir + '/';
if not DirectoryExists(strFileDir + 'Temp') then
MkDir(strFileDir +'Temp');
FileName := strFileDir + 'Temp/' + IntToStr(PageNumber) + '.Tmp';
TargetFile := TFileStream.Create(FileName, fmOpenWrite or fmCreate);
try
with TargetFiledo
begin
FileFlag := $AA55;
Write(FileFlag, SizeOf(FileFlag));
PageFlag:=4;
Write(pageFlag, SizeOf(PageFlag));
//iCellHeadLineCount:=1;
// 行高
iLineHeight:= iCellLineHeight;
Write(iLineHeight, SizeOf(iLineHeight));
//总行数
iTotalLineCount:=iTotalCellTextLineCount;
Write(iTotalLineCount, SizeOf(iTotalLineCount));
//每页最大行数
iMaxLineCountPerPage:=iMaxCellTextLineCountPerPage;
Write(iMaxLineCountPerPage, SizeOf(iMaxLineCountPerPage));
//表格总页数
iPageCount:= iCellPageCount;
Write(iPageCount, SizeOf(iPageCount));
//表格页码
Write(TabNumber, SizeOf(TabNumber));
//页码
Write(PageNumber, SizeOf(PageNumber));
//当前页行数
iThisPageLineCount:=iCellThisPageLineCount;
Write(iThisPageLineCount, SizeOf(iThisPageLineCount));
// 每行的属性
for i:=0 to iThisPageLineCountdo
begin
for J:=0 to 6do
begin
case J of
0:
sTempStr:= (MainForm.ActiveMDIChild as TCostCountForm).Table_CostCount.FieldByName('No').AsString;
1:
sTempStr:= (MainForm.ActiveMDIChild as TCostCountForm).Table_CostCount.FieldByName('ItemName').AsString;
2:
sTempStr:= (MainForm.ActiveMDIChild as TCostCountForm).Table_CostCount.FieldByName('MetricUnit').AsString;
3:
sTempStr:= (MainForm.ActiveMDIChild as TCostCountForm).Table_CostCount.FieldByName('WorkAmount').AsString;
4:
if (MainForm.ActiveMDIChild as TCostCountForm).Table_CostCount.FieldByName('UnitPrice').AsFloat <> 0 then
sTempStr:= (MainForm.ActiveMDIChild as TCostCountForm).Table_CostCount.FieldByName('UnitPrice').AsString
else
sTempStr := '';
5:
if (MainForm.ActiveMDIChild as TCostCountForm).Table_CostCount.FieldByName('Value').AsFloat <> 0 then
sTempStr:= FormatFloat('0.00',(MainForm.ActiveMDIChild as TCostCountForm).Table_CostCount.FieldByName('Value').AsFloat)
else
sTempStr := '';
6:
sTempStr:= (MainForm.ActiveMDIChild as TCostCountForm).Table_CostCount.FieldByName('Remark').AsString;
end;
Count := Length(sTempStr);
Write(Count, SizeOf(Count));
StrPCopy(TempPChar, sTempStr);
for K:= 0 to Count - 1do
Write(TempPChar[K], 1);
end;
if (i< iThisPageLineCount) then
(MainForm.ActiveMDIChild as TCostCountForm).Table_CostCount.Next;
end;
end;
finally
TargetFile.Free;
end;
end;

读已经生成的临时文件:
procedure LoadTabDrawFile(strFileName: string);
var
TargetFile: TFileStream;
FileFlag: WORD;
PageFlag: Integer;
iLineHeight: Integer;
iTotalLineCount, iMaxLineCountPerPage, iThisPageLineCount: Integer;
iPageCount: Integer;
Count: Integer;
I, J, K: Integer;
TempPChar: array[0..3000] of char;
sTempStr: String;
begin
TargetFile := TFileStream.Create(strFileName, fmOpenRead);
try
with TargetFiledo
begin
Read(FileFlag, SizeOf(FileFlag));
if FileFlag <> $AA55 then
begin
TargetFile.Free;
Application.MessageBox('文件格式不对...', szProgramTitle, MB_OK+MB_ICONERROR);
Exit;
end;
Read(PageFlag, SizeOf(PageFlag));
// 行高
Read(iLineHeight, SizeOf(iLineHeight));
iCellLineHeight:= iLineHeight;
//总行数
Read(iTotalLineCount, SizeOf(iTotalLineCount));
iTotalCellTextLineCount:= iTotalLineCount;
//每页最大行数
Read(iMaxLineCountPerPage, SizeOf(iMaxLineCountPerPage));
iMaxCellTextLineCountPerPage:= iMaxLineCountPerPage;

//总页数
Read(iPageCount, SizeOf(iPageCount));
iCellPageCount:= iPageCount;
//表格页码
Read(iCellPageNumber, SizeOf(iCellPageNumber));
//页码
Read(iPageNumber, SizeOf(iPageNumber));
//当前页行数
Read(iThisPageLineCount, SizeOf(iThisPageLineCount));
iCellThisPageLineCount:= iThisPageLineCount;
//Application.MessageBox(PChar(IntToStr(iThisPageLineCount)), szProgramTitle, MB_OK+MB_ICONWARNING);
// 每行的属性
SetLength(TabRecord, iThisPageLineCount);
for i:=0 to iThisPageLineCount-1do
begin
for j:=0 to 6do
begin
Read(Count, SizeOf(Count));
for K:=0 to Count-1do
Read(TempPChar[K], 1);
TempPchar[Count]:=#0;
sTempStr:= StrPas(TempPChar);
//Application.MessageBox(Pchar(sTempStr), szProgramTitle, MB_OK+MB_ICONWARNING);
//Application.MessageBox(TempPChar, szProgramTitle, MB_OK+MB_ICONWARNING);
case j of
0:
TabRecord.No:= sTempStr;
1:
TabRecord.ItemName:= sTempStr;
2:
TabRecord.MetricUnit:= sTempStr;
3:
TabRecord.WorkAmount:= sTempStr;
4:
TabRecord.UnitPrice:= sTempStr;
5:
TabRecord.Value:= sTempStr;
6:
TabRecord.Remark:= sTempStr;
end;
end;
end;
end;
finally
TargetFile.Free;
end;
end;

生成临时数据库不用我说了,宇宙人都会。
 
看见了没有,如果你有100个模块的话,都要如此这般的进行编程,才能进行打印,是不是很麻烦。我建议还是用控件方便。
 
现在那些所谓的erp、crm、his等等的程序,由于模块太多,打印基本上采取报表控件的方式进行打印,很少直接使用TPrinter类编程的。
 
接受答案了.
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
后退
顶部