顯示具有 QuickReport 標籤的文章。 顯示所有文章
顯示具有 QuickReport 標籤的文章。 顯示所有文章

2026年2月25日 星期三

修正 Quick Report 預覽/列印的顯示比例

 當調整了電腦螢幕的縮放比例後,操作程式裡的報表QuickReport,發現報表預覽的資料內容沒有隨著顯示縮放比跟著做調整,但不影響實際列印輸出的結果。



參考網上的作法,修正 QuickReport 需 QRPrntr.pas 排除縮放比的問題。

我採用網友提供的方法1來處理。

File Name : QRPrntr.pas

Procedure Name : CreateMetafileCanvas


QRPrntr.pas 修正後,重新編譯QR506RunDXE10.bpl,

預覽結果就會以符合系統縮放比做調整了。


【參考連結】

老森常譚 IT Help 《Delphi》修正 Quick Report 預覽列印的比例問題


2025年12月25日 星期四

QuickReport - 載入 Qrp 報表文件時,會預先使用預設印表機的紙張格式套用在文件上,與設計的報表格式不符...

 var 
  repReport:TQuickRep;
  iPageHeightPixel, iPageWidthPixel:Integer;
  Meta: TMetafile;
begin
  inherited;
  repReport := TQuickRep.Create(nil);
  repReport.PrevInitialZoom := qrZoomToWidth;   //頁寬
  repReport.PrevShowThumbs := False;            //不顯示簡視欄
  repReport.PrevShowSearch := False;            //不顯示搜尋欄
  repReport.PreviewInitialState := wsMaximized; //最大化
  repReport.ShowProgress := True;
  repReport.PreviewDefaultSaveType := stQRP;

  repReport.Prepare;
  repReport.QRPrinter.Load('Report.qrp');    //載入檔案

  Meta := repReport.QRPrinter.GetPage(1);
  iPageWidthPixel := Meta.Width;    //取得文件記錄中的尺寸 Pixel
  iPageHeightPixel := Meta.Height;  //取得文件記錄中的尺寸 Pixel

  repReport.Page.Orientation := repReport.QRPrinter.Orientation; //報表直/橫向
  repReport.Page.PaperSize := TQRPaperSize.Custom; //報表紙張格式
  repReport.Units := TQRUnit.Pixels;
  repReport.Page.Length := iPageHeightPixel; //設定報表長度
  repReport.Page.Width := iPageWidthPixel;   //設定報表寬度

  repReport.PrinterSettings.PaperSize := TQRPaperSize.Custom;  //報表紙張格式
  repReport.PrinterSettings.PrinterIndex := 1;      //指定印表機
  repReport.PrinterSettings.ApplySettings(repReport.QRPrinter);

  repReport.QRPrinter.PrinterIndex := 1;            //指定印表機
  repReport.QRPrinter.aPrinterSettings.ApplySettings;
  repReport.QRPrinter.PreviewModal;      //預覽文件
end;

2025年6月11日 星期三

QuickReport 調整 QRShape 配合 DetailBand 展延

 


procedure TForm1.DetailBand1BeforePrint(Sender: TQRCustomBand; var PrintBand: Boolean);
var h:extended;
begin
  DetailBand1.ExpandedHeight(h);
  QRShape1.Size.Height := h - QRShape1.Size.Top - 1;
end;



2023年11月28日 星期二

在表單底下空白處,使用LoopBand填滿表格

報表情境1 (未使用GroupBand)


procedure TForm1.DetailBand1AfterPrint(Sender: TQRCustomBand;  BandPrinted: Boolean);
var iCurrencyY, iPaperLength, iPrintY, iCount, iLoopBandHeight, iBottomMargin,
  iPageFooterBand, iQRGroupFooter:Integer;
begin
  //檢查最後一筆
  if ADOQuery1.RecNo=ADOQuery1.RecordCount then
  begin
    iPaperLength := QuickRep1.QRPrinter.PaperLength;  //報表高度
    iCurrencyY := QuickRep1.CurrentY;  //目前輸出的高度
    iLoopBandHeight := Ceil(QRLoopBand1.Size.Length);  //LoopBand 的高度
    iPageFooterBand := Ceil(PageFooterBand1.Size.Length);  //PageFooterBand 的高度
    iBottomMargin := Ceil(QuickRep1.Page.BottomMargin);  //報表邊界Bottom的高度
    iPrintY := iPaperLength - iCurrencyY - iPageFooterBand - iBottomMargin; //LoopBand 輸出的高度
    iCount := iPrintY div iLoopBandHeight;
    QRLoopBand1.PrintCount := iCount;
end;




 報表情境2 (使用GroupBand)



procedure TForm1.QuickRep2StartPage(Sender: TCustomQuickRep);
begin
  //在報表上放置QRExpr1,借來運算QRGroup.Expression運算後的結果
  QRExpr1.Expression := QRGroup2.Expression;
  QRExpr1.Enabled := False;
end;


procedure TForm1.DetailBand1AfterPrint(Sender: TQRCustomBand; BandPrinted: Boolean);
var iCurrencyY, iPaperLength, iPrintY, iCount, iLoopBandHeight, iBottomMargin,
  iPageFooterBand, iQRGroupFooter:Integer;
  sCurValue, sNextValue:String;
begin
  //取得目前以及下一筆資料的運算結果做比對
  sCurValue := QRExpr1.Value.StringVal;
  adoQuery1.Next;
  sNextValue := sCurValue;
  if not adoQuery1.eof then
  begin
    sNextValue := QRExpr1.Value.StringVal;
    adoquery1.Prior;
  end;

  //如果是最後一筆,或是前後筆資料不吻合,就使用LoopBand填滿
  iCount := 0;
  if (ADOQuery1.RecNo=ADOQuery1.RecordCount) or (sCurValue<>sNextValue) then
  begin
    iPaperLength := QuickRep2.QRPrinter.PaperLength;  //報表高度
    iCurrencyY := QuickRep2.CurrentY;  //目前輸出的高度
    iLoopBandHeight := Ceil(QRLoopBand2.Size.Length);  //LoopBand 的高度
    iQRGroupFooter := Ceil(QRGroupFooter2.Size.Length);  //GroupFooter 的高度
    iPageFooterBand := Ceil(PageFooterBand2.Size.Length);  //PageFooter 的高度
    iBottomMargin := Ceil(QuickRep2.Page.BottomMargin);  //報表邊界Bottom的高度
    iPrintY := iPaperLength - iCurrencyY - iPageFooterBand - iQRGroupFooter - iBottomMargin;
    iCount := iPrintY div iLoopBandHeight;
  end;
  QRLoopBand2.PrintCount := iCount;
end;


2022年11月29日 星期二

Access violation at address xxxxxxxx in module 'rtl70.bpl'. read of address xxxxxxxx

 



程式中使用到QuickReport物件,機器設備上必須先設定有印表機,如果是網路印表機,必須是已連線的狀態。


2022年8月17日 星期三

擴展QuckReport報表內容

報表內容過多過長, Report礙於報表的設計空間,開發階段不容易將報表元件放置到適當的位置。可以在Form上,放置多個QuickRep報表元件,在不同的QuickRep元件中利用ChildBand來設計,再用程式碼控制將ChildBand併到主報表裡做預覽。





uses QRPrntr;

type TQRPrintableExt=class(TQRPrintable);

procedure TForm1.pr_Reset_ParentReport(AChildBand:TQRChildBand; AParentBand:TQRCustomBand);
var i:Integer;
begin
  AChildBand.Parent := AParentBand.ParentReport;
  AChildBand.ParentBand := AParentBand;

  for i := 0 to AChildBand.ControlCount-1 do
    TQRPrintableExt(AChildBand.Controls[i]).ParentReport := AChildBand.ParentReport;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  pr_Reset_ParentReport(ChildBand1, DetailBand1);
  pr_Reset_ParentReport(QRChildBand1, ChildBand1);

  QuickRep1.Preview;
end;

輸出結果:



2022年6月15日 星期三

操作Printers.Printer.PrintIndex 無法變更 QuickReport PrintSetup裡的輸出印表機!?

Uses Printers;
...
Printers.Printer.PrintIndex := 1;  //指定輸出的印表機索引,不會變更預設印表機
...

TPrintDialog會依據PrintIndex的變更指向對應的印表機,
QuickReport PrintSetup沒有因為PrintIndex變更指定輸出的印表機,維持指向預設印表機。


修正QuickReport QRPrnSu.pas文件

Ver. QuickRep506 
File : QRPrnSu.pas
Proceure : GetPrinter

原內容

{ TQRBasePrintDialog }
// HERE the important changes - see dialogs.pas from delphi vcl - source.
// note the Brackets and type casts! It's tricky :-)

procedure TQRBasePrintDialog.GetPrinter(var DeviceMode, DeviceNames: THandle);
var
  DevNames: PDevNames;
  Offset: PChar;
  size : integer;
begin
  FPrinter.GetPrinter(Device, Driver, Port, DeviceMode);
  if DeviceMode <> 0 then
  begin
    size:=SizeOf(TDevNames) +
          (StrLen(Device) + StrLen(Driver) + StrLen(Port) + 3) *Sizeof(Char);
    //DeviceNames := GlobalAlloc(GHND,SizeOf(TDevNames) +
    //               (StrLen(Device) + StrLen(Driver) + StrLen(Port) + 3) *Sizeof(Char));
    //DevNames := PDevNames(GlobalLock(DeviceNames));
    GetMem(DevNames, Size);
    try
      Offset := PChar(PByte(DevNames) + SizeOf(TDevnames));
      with DevNames^ do
      begin
        wDriverOffset := NativeInt(Offset) - NativeInt(DevNames);
        Offset := StrECopy(Offset, Driver) + 1;
        wDeviceOffset := NativeInt(Offset) - NativeInt(DevNames);
        Offset := StrECopy(Offset, Device) + 1;
        wOutputOffset := NativeInt(Offset) - NativeInt(DevNames);;
        StrCopy(Offset, Port);
      end;
    finally
      //GlobalUnlock(DeviceNames);
      FreeMem(DevNames, Size);
    end;
  end;
end;


參考備註指定的 Dialogs.pas 修正

{ TQRBasePrintDialog }
// HERE the important changes - see dialogs.pas from delphi vcl - source.
// note the Brackets and type casts! It's tricky :-)

procedure TQRBasePrintDialog.GetPrinter(var DeviceMode, DeviceNames: THandle);
var
  DevNames: PDevNames;
  Offset: PChar;
  size : integer;
begin
  FPrinter.GetPrinter(Device, Driver, Port, DeviceMode);
  if DeviceMode <> 0 then
  begin
    //size:=SizeOf(TDevNames) +
    //      (StrLen(Device) + StrLen(Driver) + StrLen(Port) + 3) *Sizeof(Char);
    DeviceNames := GlobalAlloc(GHND, SizeOf(TDevNames) +
                   (StrLen(Device) + StrLen(Driver) + StrLen(Port) + 3) *Sizeof(Char));
    DevNames := PDevNames(GlobalLock(DeviceNames));
    //GetMem(DevNames, Size);
    try
      Offset := PChar(PByte(DevNames) + SizeOf(TDevnames));
      with DevNames^ do
      begin
        wDriverOffset := Offset - PChar(DevNames);
        Offset := StrECopy(Offset, Driver) + 1;
        wDeviceOffset := Offset - PChar(DevNames);
        Offset := StrECopy(Offset, Device) + 1;
        wOutputOffset := Offset - PChar(DevNames);;
        StrCopy(Offset, Port);
      end;
    finally
      GlobalUnlock(DeviceNames);
      //FreeMem(DevNames, Size);
    end;
  end;
end;

QRPrnSu.pas修正後儲存,重新編譯/安裝 QR506DesignDXE10.bpl、QR506RunDXE10.bpl



2020年7月30日 星期四

QuickReportLib.pas 記錄




QuickReport 群組頁數/群組合計頁數 

function PageCount(AReport:TQuickRep):Integer;
function PageNumber(AReport:TQuickRep):Integer;
function GroupCount(AReport:TQuickRep; AExpression:String):Integer;
function GroupNumber(AReport:TQuickRep; AExpression:String):Integer;
function GroupPageCount(AReport:TQuickRep; AExpression:String):Integer;
function GroupPageNumber(AReport:TQuickRep; AExpression:String):Integer;

QuickRep1.Prepare;
QuickRep1.PreviewModule;

2018年7月4日 星期三

SynPDF for Delphi


下載 : https://github.com/synopse/SynPDF



Trying to export a report with unicode text to pdf using SynPDF, results in mixed-up text

SynPDF have fixed some unicode issues, but not all of them aparently. The following is a streight forward code for exporting a quickreport to PDF usiny SynPDF:

procedure TForm1.CreatePdf(QuickRep: TCustomQuickRep; const aFileName: TFileName);
var
Pdf: TPdfDocument;
aMeta: TMetaFile;
i: integer;
begin
  Pdf := TPdfDocument.Create;
  Pdf.UseUniscribe := True;
  try
      Pdf.DefaultPaperSize := psA4;
      QuickRep.Prepare;
      for i := 1 to QuickRep.QRPrinter.PageCount do begin
        Pdf.AddPage;
        aMeta := QuickRep.QRPrinter.GetPage(i);
        try
          // draw the page content
          Pdf.Canvas.RenderMetaFile(aMeta,1,0,0);
        finally
          aMeta.Free;
        end;
      end;
      Pdf.SaveToFile(aFileName);
  finally
    Pdf.free;
  end;
end;

轉貼至 https://stackoverflow.com/questions/25910798/trying-to-export-a-report-with-unicode-text-to-pdf-using-synpdf-results-in-mixe

2018年1月14日 星期日

QuickReport 得知Prepare 或 Print狀態

//Preview
QuickRep1.QRPrinter.ShowingPreview

//Printing
QuickRep1.QRPrinter.aPrinterSettings.Printer.Printing

2017年9月7日 星期四

QuickReport報表-列表位置

  QuickRep1.CurrentX;
  QuickRep1.CurrentY;

QuickReport QRImage 掉圖

...
sPath := GetEnvironmentVariable('USERPROFILE'); //Ex :C:\Users\Administrator
sFileName := sPath + '\Report.rpt';
QuickRep1.Prepare;
QuickRep1.QRPrinter.Save(sFileName);  //將結果輸出到檔案
QuickRep1.QRPrinter.Load(sFileName);  //載入檔案
QuickRep1.PrinterSettings.PrinterIndex := iCustPrinter; //指定印表機
QuickRep1.QRPrinter.PrinterIndex := iCustPrinter; //指定印表機
QuickRep1.QRPrinter.PreviewModal;    //預覽文件
QuickRep1.QRPrinter.Cleanup;              //關閉文件
...

QuickReport "Cannot assign a tfont to a tfont" 的錯誤狀況排除

方法一:修正QRPrntr.pas

procedure TQRPrinter.PreviewModal;
begin
  if assigned(FOnPreviewEvent) then
  begin
    try
      FOnPreviewEvent(Self)  //使用QRPreview可以正常操作, 不會出現cannot assign a tfont to a tfont
    finally
    end;
  end
  else
  begin
    with GlobalPreviewInterface.Create(nil) do
    try
      ShowModal(Self) //使用預設的Preview, 會出現 cannot assign a tfont to a tfont
    finally
      Free;
    end;
  end;
end;


QuickRep1.ShowProgress := False;  //QRPrntr.pas 會呼叫 TQRProgressForm, 一樣會出現 cannot assign a tfont to a tfont


QRRunDXE2.dpk 重新編譯, 將產出的bpl dcp檔, 複製到dpk的連結目錄
c:\windows\system32
C:\Program Files (x86)\Embarcadero\RAD Studio\9.0\lib\win32


方法二:
主要是由于在创建Dll的Form时,将外部调用程序的Application、Screen和MainForm都传给了Dll并且将Dll中的这几个对 象都替换掉了的缘故,解决的办法是只需将外部调用程序的Application.Handle及MainForm传给Dll并替换掉Dll中的这两项值就 可以了,我已测试通过,可以试一试。如:
var
p: PLongInt;

{DllApp: TApplication Dll中的Application
 OutApp: TApplication 外部调用程序的Application
}
p:=@(DllApp.MainForm);
DllApp.Handle := OutApp.Handle;
p^:=LongInt(OutApp.MainForm);



轉貼至 http://bbs.csdn.net/topics/50408729

QuickReport 列表資料轉向的問題

Report寬度 > 長度, 印表機會自動將資料靠右橫印,
如果設定Report橫印將資料轉正,
印表機的資料轉向會取至Report的設定將資料靠左橫印

單張送紙
  如果是單張送紙的話, 可以將調整長度大於寬度,
印表機就不會自動將資料轉向

連續送紙
  需調整印表機的資料轉向, 並調整Report的長寬值