AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein DBGrid, ausdrucken über mehrere Seitenbreite hinaus
Thema durchsuchen
Ansicht
Themen-Optionen

DBGrid, ausdrucken über mehrere Seitenbreite hinaus

Ein Thema von waldforest · begonnen am 30. Sep 2016 · letzter Beitrag vom 1. Okt 2016
Antwort Antwort
waldforest

Registriert seit: 8. Mai 2005
366 Beiträge
 
Delphi XE3 Enterprise
 
#1

DBGrid, ausdrucken über mehrere Seitenbreite hinaus

  Alt 30. Sep 2016, 16: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
  Mit Zitat antworten Zitat
Benutzerbild von haentschman
haentschman

Registriert seit: 24. Okt 2006
Ort: Seifhennersdorf / Sachsen
5.289 Beiträge
 
Delphi 12 Athens
 
#2

AW: DBGrid, ausdrucken über mehrere Seitenbreite hinaus

  Alt 30. Sep 2016, 17:19
Hallöle...
Zitat:
ohne Reportgenerator
...da wirst du nicht glücklich. Wenn du am Design deines Ausdrucks schraubst mußt du am Code schrauben. Wenn du mal die Komponenten austauschst da funktioniert nichts mehr.

Nutze die Zeit um dich in einen Reportgererator einzuarbeiten. (imho ist bei XE3 Fastreport dabei)
  Mit Zitat antworten Zitat
waldforest

Registriert seit: 8. Mai 2005
366 Beiträge
 
Delphi XE3 Enterprise
 
#3

AW: DBGrid, ausdrucken über mehrere Seitenbreite hinaus

  Alt 30. Sep 2016, 19:17
Hallo,

danke für die Empfehlung, möchte dennoch die Logik verstehen.
Aber dennoch habe ich mir dies einmal mit Quickreport angesehen, wie kann man denn hier über die Seitenbreite hinaus die Liste erstellen ?
mfg wf
  Mit Zitat antworten Zitat
Benutzerbild von haentschman
haentschman

Registriert seit: 24. Okt 2006
Ort: Seifhennersdorf / Sachsen
5.289 Beiträge
 
Delphi 12 Athens
 
#4

AW: DBGrid, ausdrucken über mehrere Seitenbreite hinaus

  Alt 1. Okt 2016, 06:01
Moin...

Ist nicht bei deiner Delphi Version Fastreport dabei?
Zitat:
möchte dennoch die Logik verstehen
...ich möchte die Logik eines Reportgenerators nicht verstehen. Der druckt das das was ich möchte das die Stelle wo ich es hinhaben will. Da bleibt mehr Zeit für die creativen Seiten...
Zitat:
wie kann man denn hier über die Seitenbreite hinaus die Liste erstellen
Mit Quickreport habe ich keine Erfahrungen. Aber alle Reportgeneratoren arbeiten nach dem gleichen Prinzip. Die Daten kommen aus einer Liste (DataSet in deinem Falle, welches am Grid hängt). Die Daten kommen niemals aus den visuellen Controls. Der Report ist dann quasi die Vorlage. Der Report stellt die Daten dann visuell, je nach Menge, zusammen... mit den Seitenvorschüben die du brauchst.

Nachtrag:
Zitat:
FastReport has been present in Delphi and C++Builder since XE2 and it’s part of XE3
...dann gibt es keine Frage für den Generator. Tutorials Teil 1-4: https://www.youtube.com/watch?v=VDTSGf4oIFA

Ungeübt tippe ich darauf das der (einfache) Report in 1 Stunde (ohne Tutorial) fertig ist.

Einschränkungen zum Tutorial:
* In der Embarcardero Edition gibt es den ReportDesiger, welcher aus dem Code aufrufbar ist, nicht.

Geändert von haentschman ( 1. Okt 2016 um 07:48 Uhr)
  Mit Zitat antworten Zitat
waldforest

Registriert seit: 8. Mai 2005
366 Beiträge
 
Delphi XE3 Enterprise
 
#5

AW: DBGrid, ausdrucken über mehrere Seitenbreite hinaus

  Alt 1. Okt 2016, 14:16
Hallo,
ich habe es einmal mit Fastreport nachgebaut. Auch hier sehe ich keine Möglichkeit in der Breite über den normalen Bereich (sprich auf neuer Seite) zu drucken.

page.EndlessWidth hat keinen Einfluss.


Delphi-Quellcode:
procedure GridPreview(Grid: TDBGrid);
var
  page: TfrxReportPage;
  band: TfrxBand;
  memo: TfrxMemoView;
// cross: TfrxCrossView;
  masterBand: TfrxMasterData;
  i, x: Integer;
  CurrentLeft, CurrentTop : integer;
  BMark: TBookmark;

begin
  // Make sure that report is clean.
  GridRep.Clear;

  // Set dataset range properties
  dataset.RangeEnd:= reCount;
  dataset.RangeEndCount:= grid.DataSource.DataSet.RecordCount;

  // Add dataset to report
  GridRep.DataSets.Add(dataset);

  // Add a page
  page:= TfrxReportPage.Create(GridRep);
  page.CreateUniqueName;
  page.SetDefaults;
  page.EndlessWidth := True;
  page.Orientation:= poLandscape;

  // Add a report title band
  band:= TfrxReportTitle.Create(page);
  band.CreateUniqueName;
  band.Top:= 0;
  band.Height:= Abs(Grid.Font.Height) + 10;

  // Add object to the report title band
  memo:= TfrxMemoView.Create(band);
  memo.CreateUniqueName;
  memo.Text:= 'Test';
  memo.Height:= Abs(Grid.Font.Height) + 10;
  memo.Align := baWidth;

  // Add masterdata band
  masterBand:= TfrxMasterData.Create(page);
  masterBand.CreateUniqueName;
  masterBand.DataSet:= dataset;
  masterBand.Top:= band.Top+band.Height+1;
  masterBand.Height:= (Canvas.TextHeight('A') + 10);

  // Add objects on master data
  x:= 0;
  for I := 0 to Grid.Columns.Count - 1 do
   begin
// ShowMessage(IntToStr(i)+'___'+Grid.Columns.Items[I].Field.FieldName);
     if (Grid.Columns.Items[I].Visible) then
    begin
      memo:= TfrxMemoView.Create(masterBand);
      memo.CreateUniqueName;
      // Connect to data
      memo.DataSet:= dataset;
      memo.DataField:= Grid.Columns.Items[I].FieldName;
      memo.SetBounds(x, 0, Grid.Columns[I].Width, (Canvas.TextHeight('A') + 10));
      x:= x+grid.Columns[I].Width;
      memo.Frame.Typ:= [ftLeft, ftRight, ftTop, ftBottom];
      memo.GapX:= 3;
      memo.GapY:= 2;
    end;
  end;

  GridRep.Showreport; {or Preview if you prefer}


end;
mfg wf
  Mit Zitat antworten Zitat
Benutzerbild von haentschman
haentschman

Registriert seit: 24. Okt 2006
Ort: Seifhennersdorf / Sachsen
5.289 Beiträge
 
Delphi 12 Athens
 
#6

AW: DBGrid, ausdrucken über mehrere Seitenbreite hinaus

  Alt 1. Okt 2016, 15:26
Moin...

Warum benutzt nicht den Designer? Das TfrxReport Objekt auf die Form... Doppelklick drauf und den Report designen. Du machst dir mehr Arbeit als nötig.
Später kann man das optimieren... Reports und Datenbank etc.

PS: Hänge mal ein PDF an wie das Ergebnis ausschauen soll.

Delphi-Quellcode:
// Add objects on master data
  x:= 0;
  for I := 0 to Grid.Columns.Count - 1 do
   begin
// ShowMessage(IntToStr(i)+'___'+Grid.Columns.Items[I].Field.FieldName);
     if (Grid.Columns.Items[I].Visible) then
    begin
      memo:= TfrxMemoView.Create(masterBand);
      memo.CreateUniqueName;
      // Connect to data
      memo.DataSet:= dataset;
      memo.DataField:= Grid.Columns.Items[I].FieldName;
      memo.SetBounds(x, 0, Grid.Columns[I].Width, (Canvas.TextHeight('A') + 10));
      x:= x+grid.Columns[I].Width;
      memo.Frame.Typ:= [ftLeft, ftRight, ftTop, ftBottom];
      memo.GapX:= 3;
      memo.GapY:= 2;
    end;
  end;
Du hast doch das Dataset. Warum vermischt du das mit den Columns? Ich denke das du dich von den visualen Controls nicht lösen kannst.

Geändert von haentschman ( 1. Okt 2016 um 15:40 Uhr)
  Mit Zitat antworten Zitat
waldforest

Registriert seit: 8. Mai 2005
366 Beiträge
 
Delphi XE3 Enterprise
 
#7

AW: DBGrid, ausdrucken über mehrere Seitenbreite hinaus

  Alt 1. Okt 2016, 16:07
Hallo,
ich nutze das Grid, damit ich hier ggf. Spaltenbreite, sowie Spalten ausblenden kann, damit habe ich einen Einfluss auf die auszugebenden Felder.

Das Grid geht über eine Seitenbreite hinaus !!
Rechnungen.pdf
mfg wf
  Mit Zitat antworten Zitat
Benutzerbild von haentschman
haentschman

Registriert seit: 24. Okt 2006
Ort: Seifhennersdorf / Sachsen
5.289 Beiträge
 
Delphi 12 Athens
 
#8

AW: DBGrid, ausdrucken über mehrere Seitenbreite hinaus

  Alt 1. Okt 2016, 17:57
Soo...

2 Varianten als Muster:


1. Header 2 zeilig + Daten 2 zeilig
2. Header 1 zeilig + Daten 1 zeilig + Fortsetzung auf neuer Seite

... ich bitte die Darstellung zu entschuldigen. Ich habe meinen Report ausgedünnt um das zu verdeutlichen. Normalerweise hat man keinen Stress die Datenfelder auszurichten.


PS: Bis auf die Codezeilen für das Laden des Reports, Report.Preview und Füllen des DataSets (bei dir ist das schon fertig) gibt es keinen Code. Wenn die Daten der ersten Seite das Blatt übersteigen, wird auf der nächsten Seite weitergemacht... usw.

Nachtrag:
Wenn du die Spalten dynamisch ausblenden willst, kommst du wahrscheinlich um die Standard Version nicht rum. Da kannst du mit Events für jedes einzelne Control arbeiten. (Größe, Position etc.). Die 199$ war die beste Investion ever... Ob das mit der Embarcadero Version andersweitig geht, habe ich nicht ausprobiert.

Geändert von haentschman ( 1. Okt 2016 um 18:20 Uhr)
  Mit Zitat antworten Zitat
waldforest

Registriert seit: 8. Mai 2005
366 Beiträge
 
Delphi XE3 Enterprise
 
#9

AW: DBGrid, ausdrucken über mehrere Seitenbreite hinaus

  Alt 1. Okt 2016, 19:33
Hallo,
vielen Dank, wenn man weiß wie es geht ist es wirklich ganz einfach.
Delphi-Quellcode:
procedure GridPreview(Grid: TDBGrid);
var
  page_wide : Integer;
  page: TfrxReportPage;
  band: TfrxBand;
  memo: TfrxMemoView;
// cross: TfrxCrossView;
  masterBand: TfrxMasterData;
  i, x: Integer;
  CurrentLeft, CurrentTop : integer;
  BMark: TBookmark;

 Procedure AddPage();
  begin
    // Add a page
    page:= TfrxReportPage.Create(GridRep);
    page.CreateUniqueName;
    page.SetDefaults;
    page.Orientation:= poLandscape;
  
    // Add a report title band
    band:= TfrxReportTitle.Create(page);
    band.CreateUniqueName;
    band.Top:= 0;
    band.Height:= Abs(Grid.Font.Height) + 10;

    // Add object to the report title band
    memo:= TfrxMemoView.Create(band);
    memo.CreateUniqueName;
    memo.Text:= 'Test';
    memo.Height:= Abs(Grid.Font.Height) + 10;
    memo.Align := baWidth;

    // Add masterdata band
    masterBand:= TfrxMasterData.Create(page);
    masterBand.CreateUniqueName;
    masterBand.DataSet:= dataset;
    masterBand.Top:= band.Top+band.Height+1;
    masterBand.Height:= (Canvas.TextHeight('A') + 10);

  end ;


begin
  // Make sure that report is clean.
  GridRep.Clear;

  // Set dataset range properties
  dataset.RangeEnd:= reCount;
  dataset.RangeEndCount:= grid.DataSource.DataSet.RecordCount;

  // Add dataset to report
  GridRep.DataSets.Add(dataset);

  AddPage;


  // Add objects on master data
  x:= 0;
  page_wide :=0;
  for I := 0 to Grid.Columns.Count - 1 do
   begin
// ShowMessage(IntToStr(i)+'___'+Grid.Columns.Items[I].Field.FieldName);
    if (Grid.Columns.Items[I].Visible) then
    begin
      if (page_wide+ Grid.Columns[I].Width+5) > page.Width then
      begin
         AddPage;
         page_wide :=0;
         x:= 0;
      end;

      memo:= TfrxMemoView.Create(masterBand);
      memo.CreateUniqueName;
      // Connect to data
      memo.DataSet:= dataset;
      memo.DataField:= Grid.Columns.Items[I].FieldName;
      memo.SetBounds(x, 0, Grid.Columns[I].Width, (Canvas.TextHeight('A') + 10));
      x:= x+grid.Columns[I].Width;
      memo.Frame.Typ:= [ftLeft, ftRight, ftTop, ftBottom];
      // Aufsummieren der Columsbreiten
      page_wide := page_wide + ROUND(memo.Width);
      memo.GapX:= 3;
      memo.GapY:= 2;
    end;
  end;

  GridRep.Showreport;

end;
@ich fange an, an Fastreport gefallen zu finden.
mfg wf

Geändert von waldforest ( 1. Okt 2016 um 19:40 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:25 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz