QuickReport Delphi7完全解決方案

前言
      本人很不喜歡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文件了。
發佈了51 篇原創文章 · 獲贊 43 · 訪問量 61萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章