Registriert seit: 8. Mai 2005
366 Beiträge
Delphi XE3 Enterprise
|
DBGrid, ausdrucken über mehrere Seitenbreite hinaus
30. Sep 2016, 17:50
Hallo,
ich möchte mich etwas intensiver mit dem Drucken, ohne Reportgenerator beschäftigen.
Mit anliegend auf DBGRID angepasstem Code drucke ich ein DBGrid, welche in der Breite über mehrere Blätter geht, aus.
Soweit klappt alles. Mich stört allerdings, dass die Abarbeitung so lange braucht.
Dies liegt sicher einerseits daran, dass jeder Datensatz durchlaufen wird, was ich erst einmal erforderlich ist, anderseits am Erneuten durchlaufen aller Datensätze für das weiter Blatt in der Breite.
Wie könnte man den Code optimieren, z.B. dass nicht für jede neue Seite, welche über die Seitenbreite hinaus erstellt wird, alle Datensätze noch einmal durchlaufen werden müssen.
Delphi-Quellcode:
procedure GridDruckNeu(Grid:tdbgrid; links, oben: Integer; scal:double; DTitle : string; farbig:boolean);
var
x, y, li, ob, re, un, waag, senk, a, vSpalte, bSpalte, vZeile, bZeile: integer;
fix, grund, schrift: TColor;
r: TRect;
fertig:boolean;
i,breite,waagseiten:integer;
function rech(i,j:integer):integer;
begin
result:=round(((i*j) / 72) * scal);
end;
begin
if dlgPnt1.Execute then
begin
Printer.Copies := dlgPnt1.Copies;
Printer.Orientation := poLandscape;
vZeile := 0;
vSpalte := 0;
bZeile := Grid.DataSource.DataSet.RecordCount;
bSpalte := grid.Columns.Count;
waag := GetDeviceCaps(Printer.Handle, LogPixelSX);
senk := GetDeviceCaps(Printer.Handle, LogPixelSY);
SetWindowOrgEx(printer.Handle, 0, 0, nil);
breite:=0; // breite des Ausdrucks, wird gebraucht um ggfs. viewport zu verschieben
for i := vSpalte to bSpalte-1 do
if (Grid.Columns.Items[i].Visible) then
breite:=breite + rech(Grid.Columns[i].Width+1, waag);
waagseiten:=0;
if (scal > 0) and
(vZeile < Grid.DataSource.DataSet.RecordCount) and
(vSpalte < grid.Columns.Count) then
begin
if farbig then
begin
fix := grid.fixedcolor;
grund := grid.color;
schrift := grid.font.color;
end
else
begin
fix := clsilver;
grund := clwhite;
schrift := clblack;
end;
links := rech(links, waag);
oben := rech(oben, senk);
li := GetDeviceCaps(Printer.Handle, PhysicalOffsetX) + 1 + links;
a := rech(3, waag);
with Printer do
begin
Title := DTitle;
BeginDoc;
Canvas.Pen.Style := psClear;
Canvas.Font := Grid.Font;
Canvas.Font.Color := Schrift;
Canvas.Font.Size := round((Grid.Font.Size / 0.72) * scal);
fertig:=false;
while (not fertig) and (not Printer.Aborted) and Printer.Printing do begin
ob := GetDeviceCaps(Printer.Handle, PhysicalOffsetY) + 1 + oben;
un := ob + round(Printer.Canvas.TextHeight('A')*scal)+15;
for x := 0 to Grid.Columns.Count - 1 do
begin
if (Grid.Columns.Items[x].Visible) then
begin
re := li + rech(Grid.Columns[x].Width + 4, waag);
// Canvas.Rectangle(li, ob, re + 2, un + 2); // zeichnet grauen Rahmen um das Grid
r := rect(li + a, ob + 1, re - a, un - 2);
DrawText(Canvas.Handle, pchar( Grid.Columns.Items[x].Title.Caption), Length(Grid.Columns.Items[x].Title.Caption), r, DT_SINGLELINE or DT_VCENTER);
li := re;
end;
end;
li := GetDeviceCaps(Printer.Handle, PhysicalOffsetX) + 1 + links;
ob := un;
Grid.DataSource.DataSet.first;
while (not Printer.Aborted) and (not Grid.DataSource.DataSet.Eof) and Printer.Printing do
begin
un := ob + round(Printer.Canvas.TextHeight('A')*scal)+15; // aufaddieren des Unterrandes
//neue Seite + Kopf
if (un > Printer.PageHeight) and
(Printing) then
begin
printer.NewPage;
SetWindowOrgEx(printer.Handle,printer.pageWidth*waagseiten, 0, nil);
ob := GetDeviceCaps(Printer.Handle, PhysicalOffsetY) + 1 + oben;
un := ob + round(Printer.Canvas.TextHeight('A')*scal)+15;
for x := 0 to Grid.Columns.Count - 1 do
begin
if (Grid.Columns.Items[x].Visible) then
begin
re := li + rech(Grid.Columns[x].Width + 4, waag);
// Canvas.Rectangle(li, ob, re + 2, un + 2); // zeichnet grauen Rahmen um das Grid
r := rect(li + a, ob + 1, re - a, un - 2);
DrawText(Canvas.Handle, pchar( Grid.Columns.Items[x].Title.Caption), Length(Grid.Columns.Items[x].Title.Caption), r, DT_SINGLELINE or DT_VCENTER);
li := re;
end;
end;
ob := un;
li := GetDeviceCaps(Printer.Handle, PhysicalOffsetX) + 1 + links;
end;
un := ob + round(Printer.Canvas.TextHeight('A')*scal)+15;
for x := 0 to Grid.Columns.Count - 1 do
begin
if (Grid.Columns.Items[x].Visible) then
begin
re := li + rech(Grid.Columns[x].Width + 4, waag);
// Canvas.Rectangle(li, ob, re + 2, un + 2); // zeichnet grauen Rahmen um das Grid
r := rect(li + a, ob + 1, re - a, un - 2);
IF Grid.Columns[x].Alignment = taRightJustify then
DrawText(Canvas.Handle, PWChar( Grid.Columns.Items[x].Field.AsString), Length(Grid.Columns.Items[x].Field.AsString), r, DT_SINGLELINE or DT_RIGHT)
else if Grid.Columns[x].Alignment = taLeftJustify then
DrawText(Canvas.Handle, PWChar( Grid.Columns.Items[x].Field.AsString), Length(Grid.Columns.Items[x].Field.AsString), r, DT_SINGLELINE or DT_LEFT)
else
DrawText(Canvas.Handle, PWChar( Grid.Columns.Items[x].Field.AsString), Length(Grid.Columns.Items[x].Field.AsString), r, DT_SINGLELINE or DT_VCENTER);
// DrawText(Canvas.Handle, PWChar( Grid.Columns.Items[x].Field.AsString), Length(Grid.Columns.Items[x].Field.AsString), r, DT_SINGLELINE or DT_VCENTER);
li := re;
end;
end;
ob := un;
li := GetDeviceCaps(Printer.Handle, PhysicalOffsetX) + 1 + links;
Grid.DataSource.DataSet.Next;
end;
// jetzt Prüfung, ob der Ausdruck zu breit ist und ggfs, neue Serie mit verschobenem Viewport
inc(waagseiten); // anzahl der waagerechten nebeneinanderliegen seiten, die ausgedruckt wurden
if (breite > (Printer.PageWidth*waagseiten)) then fertig:=false else fertig:=true;
if not fertig then begin
printer.NewPage;
SetWindowOrgEx(printer.Handle,printer.pageWidth*waagseiten, 0, nil); // viewport um Seitengröße verschieben
end;
end; // von while not fertig...
if Printing then EndDoc;
end; // von WITH PRINTER
end;
end;
end; //GridDruckNeu
Ist es vielleicht sinnvoller im DBGRID angezeigten Daten einfacher auszudrucken, wenn ja, wie bekomme ich diese schnell in ein Stringlist ?
mfg wf
|