前言
本人很不喜欢QuickReport,因为其有太多问题,也太不灵活。但在开发过程中,还是无法避免接触到这种问题,特别是历史遗留下来的控件,几乎是不可能把那么多的报表去换成其他报表控件的。我把自己在改造一个项目中使用QuickReport的经验写出来,当然,有部分是从别的地方摘抄的,就一起整合了。
1.使用delphi自带控件。
Delphi 7中仍然存在Quick Report,只是因为Delphi 7默认的报表工具为Rave,所以在工具条上找不到。你可以使用Components|Install Packages,然后点击Add,找到delphi7安装目录/bin目录并添加dclqrt70.bpl。
然而,自带控件是没有源码的,只要有一点不满足要求,就得每个报表进行改动,项目根本无法进行下去。所以,源码太重要了。
2.使用QuickReport 4.0 professionalfor Delphi7. www.playicq.com上有一个带源码的版本,先去下载下来,安装。默认在Delphi安装目录的quickrpt子目录下面。
别急着使用!因为有太多问题。让我们来逐一解决下面的问题:
(1)QRDBText中文折行问题
QRDBText中有一个属性WordWrap,本来以为这个属性一设置为True,就万事大吉了,可事与愿违,全乱了!
查了半天资料,据说3.06版曾经解决了这个问题,后来的版本却又走了回头路!我晕,但有什么办法。千辛万苦,终于在大富翁上找到一个解决办法
原文见:http://www.delphibbs.com/delphibbs/dispq.asp?lid=620364
第一步:
在.../Delphi7/lib目录下,找到qrctrls.dcu,删除之或改名,将.../Delphi7/quickrpt
目录下的qrctrls.pas和qrdefs.inc两个文件copy到.../Delphi7/lib目录下,然后将
qrdefs.inc中的
//{$DEFINE VER100}
一句改为
{$DEFINE VER100}
第二步:
然后在qrctrls.pas中找到TQRCustomLabel.FormatLines过程,将其修改如下:
procedure TQRCustomLabel.FormatLines;
var
I, J : integer;
NewLine : string;
LineFinished : boolean;
HasParent : boolean;
MaxLineWidth : integer;
AAlignment: TAlignment;
function aLineWidth(Line : string) : integer;
begin
if HasParent then
result := Muldiv(Longint(ParentReport.TextWidth(Font, Line)),Zoom,100)
else
Result := Canvas.TextWidth(Line);
end;
procedure FlushLine;
begin
FFormattedLines.Add(NewLine);
NewLine := '';
end;
procedure AddWord(aWord : string);
//{$ifdef ver100}
var
S: string;
//{$endif}
begin
if aLineWidth(NewLine + aWord) > Width then
begin
if NewLine = '' then
begin
//{$ifdef ver100}
if SysLocale.FarEast then
begin
while true do
begin
if (aWord[1] in LeadBytes) and (Length(aWord) > 1) then
S := copy(aWord, 1, 2)
else
S := copy(aWord, 1, 1);
if aLineWidth(NewLine + S) < Width then
begin
NewLine := NewLine + S;
Delete(aWord, 1, Length(S));
end
else
Break;
end;
end
else
while aLineWidth(NewLine + copy(aWord, 1, 1)) < Width do
begin
NewLine := NewLine + copy(aWord, 1, 1);
Delete(aWord, 1, 1);
end;
//{$else}
// while aLineWidth(NewLine + copy(aWord, 1, 1)) < Width do
// begin
// NewLine := NewLine + copy(aWord, 1, 1);
// Delete(aWord, 1, 1);
// end;
//{$endif}
aWord := '';
end;
FlushLine;
if aLineWidth(aWord) > Width then
begin
if NewLine = '' then
begin
if Width = 0 then
aWord := ''
else
while aLineWidth(aWord) > Width do
//{$ifdef ver100}
if ByteType(aWord, Length(aWord)) = mbTrailByte then
Delete(aWord, Length(aWord)-1, 2)
else
//{$endif}
Delete(aWord, Length(aWord), 1);
end;
NewLine := aWord;
FlushLine;
aWord := '';
end;
if not WordWrap then
begin
aWord := '';
LineFinished := true;
end;
end;
NewLine := NewLine + aWord;
end;
procedure AddLine(Line : string);
var
aPos : integer;
begin
while pos(#10, Line) > 0 do
Delete(Line, Pos(#10, Line), 1);
aPos := pos(#13, Line);
if aPos > 0 then
begin
repeat
AddLine(copy(Line, 1, aPos - 1));
Delete(Line, 1 , aPos);
aPos := pos(#13, Line);
until aPos = 0;
AddLine(Line);
end else
begin
J := 0;
NewLine := '';
LineFinished := false;
if AutoSize then
begin
NewLine := Line;
FlushLine;
LineFinished := True;
end else
begin
while (J < Length(Line)) and (Length(Line) > 0) do
begin
repeat
//{$ifdef ver100}
begin
inc(J);
if Line[J] in LeadBytes then
begin
inc(J);
break;
end;
end;
//{$else}
// inc(J)
//{$endif}
until (Line[J] in BreakChars) or (J >= Length(Line));
AddWord(copy(Line, 1, J));
Delete(Line, 1, J);
J := 0;
end;
if not LineFinished then
FlushLine;
end;
end;
end;
procedure FormatFromCaption;
begin
AddLine(FPrintCaption);
if not UpdatingBounds and HasParent then
begin
UpdatingBounds := true;
if Height < (longint(ParentReport.TextHeight(Font, 'W') * Zoom div 100) + 1) then
Height := (longint(ParentReport.TextHeight(Font, 'W')) * Zoom div 100) + 1;
UpdatingBounds := false;
end
end;
procedure FormatFromStringList;
var
J : integer;
begin
if (FLines.Count <> 0) then
begin
if AutoSize then
FFormattedLines.Assign(FLines)
else
for J := 0 to FLines.Count - 1 do
AddLine(FLines[J]);
end else
if csDesigning in ComponentState then
begin
FCaption := Name;
FormatFromCaption;
FCaption := '';
end;
end;
begin
if Parent <> nil then
begin
if assigned(FFormattedLines) then
FFormattedLines.Clear
else
FFormattedLines := TStringList.Create;
HasParent := ParentReport <> nil;
LineFinished := false;
if CaptionBased then
FormatFromCaption
else
FormatFromStringList;
if AutoSize and (not UpdatingBounds) and HasParent then
begin
MaxLineWidth := 0;
for I := 0 to FFormattedLines.Count - 1 do
if aLineWidth(FFormattedLines[I]) > MaxLineWidth then
MaxLineWidth := aLineWidth(FFormattedLines[I]);
if Frame.DrawLeft then
MaxLineWidth := MaxLineWidth + Frame.Width;
if Frame.DrawRight then
MaxLineWidth := MaxLineWidth + Frame.Width;
UpdatingBounds := true;
AAlignment := Alignment;
// {$ifdef ver110}
if UseRightToLeftAlignment then
ChangeBiDiModeAlignment(AAlignment);
// {$endif}
case AAlignment of
taCenter : Left := Left + ((Width - MaxLineWidth) div 2);
taRightJustify : Left := Left + Width - MaxLineWidth;
end;
Width := MaxLineWidth;
if (FFormattedLines.Count = 0) and (csDesigning in ComponentState) then
Height := (longint(ParentReport.TextHeight(Font, 'W')) * Zoom div 100) + 1;
if (Height < (longint(ParentReport.TextHeight(Font, 'W') * Zoom div 100) + 1)) then
Height := (longint(ParentReport.TextHeight(Font, 'W')) * Zoom div 100) + 1;
UpdatingBounds := false;
end;
end;
DoneFormat := true;
end;
(2)汉化问题
QuickReport的预览框一向是很丑的,而且还是英文,安装了4.0之后一看,噢?打印预览界面变了,增加了缩略图和搜索文字的功能。如下图(这个界面是我汉化后的效果)
找到文件qrprev.dfm,想怎么汉化,就怎么汉化吧;另外QR4Const中有一些常量需要汉化
(3)给QuickRpt增加输出文件类型,以rtf为例:
这样,在预览的时候,点击保存按钮,就可以选择保存为rtf文件了。
本人很不喜欢QuickReport,因为其有太多问题,也太不灵活。但在开发过程中,还是无法避免接触到这种问题,特别是历史遗留下来的控件,几乎是不可能把那么多的报表去换成其他报表控件的。我把自己在改造一个项目中使用QuickReport的经验写出来,当然,有部分是从别的地方摘抄的,就一起整合了。
1.使用delphi自带控件。
Delphi 7中仍然存在Quick Report,只是因为Delphi 7默认的报表工具为Rave,所以在工具条上找不到。你可以使用Components|Install Packages,然后点击Add,找到delphi7安装目录/bin目录并添加dclqrt70.bpl。
然而,自带控件是没有源码的,只要有一点不满足要求,就得每个报表进行改动,项目根本无法进行下去。所以,源码太重要了。
2.使用QuickReport 4.0 professionalfor Delphi7. www.playicq.com上有一个带源码的版本,先去下载下来,安装。默认在Delphi安装目录的quickrpt子目录下面。
别急着使用!因为有太多问题。让我们来逐一解决下面的问题:
(1)QRDBText中文折行问题
QRDBText中有一个属性WordWrap,本来以为这个属性一设置为True,就万事大吉了,可事与愿违,全乱了!
查了半天资料,据说3.06版曾经解决了这个问题,后来的版本却又走了回头路!我晕,但有什么办法。千辛万苦,终于在大富翁上找到一个解决办法
原文见:http://www.delphibbs.com/delphibbs/dispq.asp?lid=620364
第一步:
在.../Delphi7/lib目录下,找到qrctrls.dcu,删除之或改名,将.../Delphi7/quickrpt
目录下的qrctrls.pas和qrdefs.inc两个文件copy到.../Delphi7/lib目录下,然后将
qrdefs.inc中的
//{$DEFINE VER100}
一句改为
{$DEFINE VER100}
第二步:
然后在qrctrls.pas中找到TQRCustomLabel.FormatLines过程,将其修改如下:
procedure TQRCustomLabel.FormatLines;
var
I, J : integer;
NewLine : string;
LineFinished : boolean;
HasParent : boolean;
MaxLineWidth : integer;
AAlignment: TAlignment;
function aLineWidth(Line : string) : integer;
begin
if HasParent then
result := Muldiv(Longint(ParentReport.TextWidth(Font, Line)),Zoom,100)
else
Result := Canvas.TextWidth(Line);
end;
procedure FlushLine;
begin
FFormattedLines.Add(NewLine);
NewLine := '';
end;
procedure AddWord(aWord : string);
//{$ifdef ver100}
var
S: string;
//{$endif}
begin
if aLineWidth(NewLine + aWord) > Width then
begin
if NewLine = '' then
begin
//{$ifdef ver100}
if SysLocale.FarEast then
begin
while true do
begin
if (aWord[1] in LeadBytes) and (Length(aWord) > 1) then
S := copy(aWord, 1, 2)
else
S := copy(aWord, 1, 1);
if aLineWidth(NewLine + S) < Width then
begin
NewLine := NewLine + S;
Delete(aWord, 1, Length(S));
end
else
Break;
end;
end
else
while aLineWidth(NewLine + copy(aWord, 1, 1)) < Width do
begin
NewLine := NewLine + copy(aWord, 1, 1);
Delete(aWord, 1, 1);
end;
//{$else}
// while aLineWidth(NewLine + copy(aWord, 1, 1)) < Width do
// begin
// NewLine := NewLine + copy(aWord, 1, 1);
// Delete(aWord, 1, 1);
// end;
//{$endif}
aWord := '';
end;
FlushLine;
if aLineWidth(aWord) > Width then
begin
if NewLine = '' then
begin
if Width = 0 then
aWord := ''
else
while aLineWidth(aWord) > Width do
//{$ifdef ver100}
if ByteType(aWord, Length(aWord)) = mbTrailByte then
Delete(aWord, Length(aWord)-1, 2)
else
//{$endif}
Delete(aWord, Length(aWord), 1);
end;
NewLine := aWord;
FlushLine;
aWord := '';
end;
if not WordWrap then
begin
aWord := '';
LineFinished := true;
end;
end;
NewLine := NewLine + aWord;
end;
procedure AddLine(Line : string);
var
aPos : integer;
begin
while pos(#10, Line) > 0 do
Delete(Line, Pos(#10, Line), 1);
aPos := pos(#13, Line);
if aPos > 0 then
begin
repeat
AddLine(copy(Line, 1, aPos - 1));
Delete(Line, 1 , aPos);
aPos := pos(#13, Line);
until aPos = 0;
AddLine(Line);
end else
begin
J := 0;
NewLine := '';
LineFinished := false;
if AutoSize then
begin
NewLine := Line;
FlushLine;
LineFinished := True;
end else
begin
while (J < Length(Line)) and (Length(Line) > 0) do
begin
repeat
//{$ifdef ver100}
begin
inc(J);
if Line[J] in LeadBytes then
begin
inc(J);
break;
end;
end;
//{$else}
// inc(J)
//{$endif}
until (Line[J] in BreakChars) or (J >= Length(Line));
AddWord(copy(Line, 1, J));
Delete(Line, 1, J);
J := 0;
end;
if not LineFinished then
FlushLine;
end;
end;
end;
procedure FormatFromCaption;
begin
AddLine(FPrintCaption);
if not UpdatingBounds and HasParent then
begin
UpdatingBounds := true;
if Height < (longint(ParentReport.TextHeight(Font, 'W') * Zoom div 100) + 1) then
Height := (longint(ParentReport.TextHeight(Font, 'W')) * Zoom div 100) + 1;
UpdatingBounds := false;
end
end;
procedure FormatFromStringList;
var
J : integer;
begin
if (FLines.Count <> 0) then
begin
if AutoSize then
FFormattedLines.Assign(FLines)
else
for J := 0 to FLines.Count - 1 do
AddLine(FLines[J]);
end else
if csDesigning in ComponentState then
begin
FCaption := Name;
FormatFromCaption;
FCaption := '';
end;
end;
begin
if Parent <> nil then
begin
if assigned(FFormattedLines) then
FFormattedLines.Clear
else
FFormattedLines := TStringList.Create;
HasParent := ParentReport <> nil;
LineFinished := false;
if CaptionBased then
FormatFromCaption
else
FormatFromStringList;
if AutoSize and (not UpdatingBounds) and HasParent then
begin
MaxLineWidth := 0;
for I := 0 to FFormattedLines.Count - 1 do
if aLineWidth(FFormattedLines[I]) > MaxLineWidth then
MaxLineWidth := aLineWidth(FFormattedLines[I]);
if Frame.DrawLeft then
MaxLineWidth := MaxLineWidth + Frame.Width;
if Frame.DrawRight then
MaxLineWidth := MaxLineWidth + Frame.Width;
UpdatingBounds := true;
AAlignment := Alignment;
// {$ifdef ver110}
if UseRightToLeftAlignment then
ChangeBiDiModeAlignment(AAlignment);
// {$endif}
case AAlignment of
taCenter : Left := Left + ((Width - MaxLineWidth) div 2);
taRightJustify : Left := Left + Width - MaxLineWidth;
end;
Width := MaxLineWidth;
if (FFormattedLines.Count = 0) and (csDesigning in ComponentState) then
Height := (longint(ParentReport.TextHeight(Font, 'W')) * Zoom div 100) + 1;
if (Height < (longint(ParentReport.TextHeight(Font, 'W') * Zoom div 100) + 1)) then
Height := (longint(ParentReport.TextHeight(Font, 'W')) * Zoom div 100) + 1;
UpdatingBounds := false;
end;
end;
DoneFormat := true;
end;
(2)汉化问题
QuickReport的预览框一向是很丑的,而且还是英文,安装了4.0之后一看,噢?打印预览界面变了,增加了缩略图和搜索文字的功能。如下图(这个界面是我汉化后的效果)
找到文件qrprev.dfm,想怎么汉化,就怎么汉化吧;另外QR4Const中有一些常量需要汉化
(3)给QuickRpt增加输出文件类型,以rtf为例:
constructor TQuickRep.CreateNew(AOwner : TComponent; Dummy: Integer);
var
aaa :TQRRTFFilter;//added
begin
inherited CreateNew(AOwner);
Controller := TQRController.Create(self);
Controller.ParentReport := Self;
Controller.SelfCheck := Self;
aaa := TQRRTFFilter.Create(Self);//added by sss
end;这样,在预览的时候,点击保存按钮,就可以选择保存为rtf文件了。