CSDN博客

img fbysss

QuickReport Delphi7完全解决方案

发表于2004/10/28 16:34:00  6606人阅读

分类: delphi

前言
      本人很不喜欢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文件了。

阅读全文
0 0

相关文章推荐

img
取 消
img