Drucken des Inhalts eines Datagridview / Dataset über mehrere Seiten in VB Net

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 63 Antworten in diesem Thema. Der letzte Beitrag () ist von silverbob76GE.

    Wenn ich später Zuhause bin Versuche ich dir Mal ein Snippet zu basteln. Bin allerdings noch arbeiten.

    Woran machst du denn fest wann auf Seite 2 gedrückt werden soll? Hast du dazu ein Maximum an Zeilen?
    Rechtschreibfehler betonen den künstlerischen Charakter des Autors.

    silverbob76GE schrieb:

    Dieser wird nun auch auf Seite 2 gedruckt.
    Das PrintDocument-Event wird für jede Seite einzeln aufgerufen.
    Also setze einen Zähler, damit Du weißt, welche Seite Du gerade druckst.
    Dieser Zähler wird im BeginPrint-Event genullt.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @Akanel

    Bin auch noch arbeiten. Werd mich gleich da reinhängen wenns noch geht.

    Das maximum an Zeilen richtet sich nach den Positionen, die im DataTable vorhanden sind.
    Ich schrebe ins Datatable über verschiedene Controls. Daruch werden die Zeilen (entsprechend die zugehörigen Spalten) gefüllt und im DatagridView angezeigt.
    Jede Zeile im DataTable entspricht einer Position im Angebot. Wenn es nun mehrere Artikel gibt, die der kunde haben möchte, sind mehrere Zeilen vorhanden.

    Die PDF teilt sich in 3 Bereiche auf.

    Bereich 1: Briefkopf. ca. 15 Zeilen, statisch. SOll nicht wiederholt werden
    Bereich 2: Artikelpositionen (Anzahl der Zeilen aus dem DataTable). Dieser Teil ist variabel und kann mehrere Seiten erfordern, je nach Artikelanzahl.
    Bereich 3: Text hinter den Artikelpositionen, auch statisch. Wird nur hinter die Positionen gesetzt.

    ich habe mir überlegt, das ich drei separate Sub's schreibe, die alle im PrintDocument-Printpage Event angerufen werden.
    So würde die For-Schleife auch nur im Bereich 2 wiederholt werden..

    Dazu muss ich aber festelegen, wo Bereich zwei anfängt. Auf Seite 1 wäre das z.B. Zeile 17, auf Seite 2 aber dann Zeile 1.

    Hoffe du verstehst was ich meine.

    @RodFromGermany:

    Das PrintDocument-Event wird für jede Seite erneut aufgerufen, ok. Nur wenn ich den kompletten Aufbau der Seite (Briefkopf, Positionen, Endtext) hier drin stehen habe, wird ann nicht alles immer wieder auf jeder Seite neu gedruckt? Wie kann ich es hinbekommen, das Bereich 1 und Bereich 3 nicht wiederholt gedruckt werden, wenn das Event aufgerufen wird.

    Im BeginPrint event habe ich einen Zähler hinzugefügt:

    VB.NET-Quellcode

    1. me.pageNB = 0


    Der Wert pageNB muss ja dann mit steigender Seitenzahl auch erhöht werden um 1. Das müsste doch immer dann passieren wenn e.hasmorepages = true erzielt wird, richtig?

    mfg, Silver

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „silverbob76GE“ ()

    silverbob76GE schrieb:

    Wie kann ich es hinbekommen, das Bereich 1 und Bereich 3 nicht wiederholt gedruckt werden, wenn das Event aufgerufen wird.
    So:

    VB.NET-Quellcode

    1. If me.pageNB = 0 Then
    2. ' Seite 1
    3. Else If me.pageNB = 1 Then
    4. ' Seite 2
    5. Else
    6. ' alle anderen Seiten
    7. End If
    8. me.pageNB += 1
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @RodFromGermany

    Danke, hab viel zu kompliziert gedacht gerade. Da hätt ich bestimmt noch 3 tage probiert es hinzubekommen. :)

    Edit:
    also 3 Seitem bekomme ich nun auch gedruckt. Der Tip von @RodFromGermany war Gold Wert, danke nochmal.

    Jetzt muss ich es nur noch hinebekommen, das der Druck da weiterläuft, wo er auf der vorherigen Seite aufgehört hat. Sprich, die letzte Zeile die im DataTable in der For-Schleife aufgerufen wurde, muss nun auf der Folgeseite fortgefürht werden mit der nächsten Zeile.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „silverbob76GE“ ()

    Ok. Also da di erste Seite eh statisch ist, durchlaufe ich mit der For-Schleife nur bis Bindingsource.count -2. Dann passt alles auf die erste Seite. In der If Abfrage für Seite 2 muss ich also ab Zeile 3 bis bindingsource.count -1 durchlaufen, richtig?

    silverbob76GE schrieb:

    richtig?
    Kann ich jetzt nicht nachvollziehen.
    Du solltest beim Drucken immer vom aktuellen Start bis zum seitenende drucken und Dir merken, wo das Seitenende ist. Da geht es bei der nächsten seite weiter.
    Parallel dazu zählst Du die Seiten.
    Ggf, ist es sinnvoll, bei geschlossenen Blöcken, die nicht getrennt werden sollen, einen "Druck ins Leere" zu machen, damit Du weißt, ob der Druck auf die Seite passt oder nicht,
    dass Du also innerhalb eines Aufrufs des PrintPage-Events zwei Durchläufe machst, trocken und scharf.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hi @RodFromGermany

    habe jetzt festgelegt, das nur bis Y = 900 gedruckt werden soll. Wenn 900 erreicht, dann soll eine neue Seite erzeugt werden.
    Aber statt ne neue Seite zu erzeugen, wird der Text einfach auf Seite 1 wieder oben neu gedruckt.
    pageNB habe ich im BeginPrint-Event auf 0 stehen.

    Hab aber noch ein anderes Problem, und zwar mit dem DirectCast und der Bindingsource. Die Bindingsource bezieht sich nur auf die erste Zeile im Datatable, habe aber mehrere Zeilen die gedruckt werden sollen. Aktuell wird immer die erste Zeile gedruckt, bis die Zeilenanzahl im Datatable erreicht ist.
    Der DIrectcast bezieht sich nur auf die erste Zeile, nicht auf die gesamte Datatable

    VB.NET-Quellcode

    1. Dim currentpositionrow = DirectCast(DirectCast(EinzelangebotBindingSource.Current, DataRowView).Row, Kundenangebot.EinzelangebotRow)
    2. Y = 510
    3. For i = 0 To EinzelangebotBindingSource.Count - 1
    4. '.............
    5. Y = Y + 160
    6. g.DrawLine(pen1, X, Y - 10, X + 730, Y - 10)
    7. g.DrawString(String.Format(" - Seite {0} -", pageNB + 1), fntText, Brushes.Black, 380, 1120)
    8. If Y >= 900 Then
    9. pageNB += 1
    10. e.HasMorePages = True
    11. Y = 50
    12. Else
    13. e.HasMorePages = False
    14. End If
    15. Next

    silverbob76GE schrieb:

    oben neu gedruckt.
    Wenn die Sewite voll ist, musst Du die For-Schleife verlassen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Wenn die Sewite voll ist, musst Du die For-Schleife verlassen.


    Wenn ich die For-Schleife verlasse, dann wird immer wieder die gleiche Seite gedruckt. Die For-Schleife brauche ich, um die Bindingsource zu durchlaufen.

    VB.NET-Quellcode

    1. If Y > 900 Then
    2. e.HasMorePages = True
    3. pageNB += 1
    4. Exit For
    5. Y = 50
    6. Else
    7. e.HasMorePages = False
    8. 'pageNB = 1
    9. End If
    @silverbob76GE Du MUSST die For-Schleife verlassen, um auf die nächste Seite zu kommen.
    Ich schlage vor, Du arbeitest zunächst das Tut mal durch und verstehst es (nicht nur anschauen): Drucken mehrseitiger Dokumente
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @RodFromGermany
    Um ehrlich zu sein. Ich blicks nicht. Hab mir das Tut so oft durchgelesen, selbst geschrieben um zu sehen was passiert.
    Bei mir klappts einfach nicht, weil ich es nicht auf mein Modell anwenden kann. Hab halt keinen Fließtext wie in einer RichTextBox.

    - Ich schreib den Briefkopf
    - ich erzeuge eine Schleife zum durchlaufen des DataSets. Diese soll fortlaufen, bis die letzte Zeile im Dataset geschrieben wurde. Die Zeilenanzahl im DataSet kann von 1 bis 100 gehen, ganz egal.
    - ich schreibe einen Schlußtext

    Es soll eine neue Seite eingefügt werden, wenn die Y-Koordinate > 900.

    Alles was ich erreich ist aber, das die erste Seite erzeugt wird und die DataSetzeilen auf der ersten Seite erneut gedruckt werden sowie der Schlußtext. Alle weiteren Seiten werden unendlich gedruckt und der Inhalt sieht dann so aus wie auf Seite 1, allerdings ohne das überdruckt wird.

    Bin echt verzweifelt, weil ich es nicht raffe. Bin jetzt seit fast zwei Wochen an dem Problem und komm nicht weiter.
    @silverbob76GE Die wichtigste Erkenntnis ist wohl die, dass für jede Seite das PrintPage-Event genau ein Mal aufgerufen wird. 8o
    Wenn Du das verinnerlicht hast, sollte schon mal einiges besser laufen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @RodFromGermany - das habe ich ja verstanden. Weiß nur nicht wie ich es umsetzen kann.

    Der Druck der ersten Seite funzt ja. Dann sag ich bei Y > 900 bitte neue Seite.
    Im BeginPrint steht pageNB = 0. Im PrintPage-Event wird pageNB inkrementiert, wenn Y > 900 erreicht wird.

    Es wird alles immer und immer wieder gedruckt. Das PrintPage-Event ist dafür verantwortlich, ist mir klar.
    Das Event wird so oft aufgerufen, bis alles was gedruckt werden muss, auch gedruckt wurde. ich weiß nicht, wie ich das Printpage-Event im zweiten und n-ten Durchlauf an der Stelle durchlaufe, wo ich beim vorherigen mal aufgehört habe zu drucken. Weiß nicht, wie ich das anstellen soll.
    Dachte, das wenn Y > 900 => e.hasmorepages = true dazu führt, das eine neue seite generiert wird, und der Druck an der Stelle weitergeht. Aber da spassiert halt nicht.
    @silverbob76GE Dann musst Du Dir die Position merken, in diesem Falle 900 und bis 1800 auf die zweite Seite drucken.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ok. Daran hatte ich ja auch schon gedacht. Aber dann bin ich immer von der Seitenzahl abhängig. Also quasi:

    Könnte ich das so lösen:
    Y = pageNB x 900

    Select case 0 (seite 1)
    for i = 0 to y

    ......
    Next

    select case 1 (seite 2)
    y = 900 x pageNB

    For i =( pageNB -1)x 900 to pageNB x 900
    ......

    next

    ?
    @silverbob76GE Sieht ganz gut aus.
    Das solltest Du doch durch Probiren ganz fox herausbekommen.
    Sieh Dir das ganze im PrintPreviewDialog an, im Ernstfall kannst Du auch in ein PDF drucken.
    Das geht alles ohne ein Blatt Papier. ;)
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hi @RodFromGermany

    das mit dem Druck der zweiten Siete klappt mittlerweile. Hab jetzt auch mit Select Case den Druckinhalt der einzelnen Seiten konfigurieren können.

    Allerdings haperts immer noch mit der Tabelle. Hab ja ein typisiertes DataSet und auch eine Bindingsource. Und mit dem DirectCast kann ich die Spalten über die Bindignsource ansprechen.
    Ich muss aber zeilenweise durch das DataSet durchlaufen, um unterschiedliche Zelleninhalte zu drucken.

    Mit dem DirectCast wird immer nur die gleiche Zeile angesprochen. Irgend ne Idee wie ich mit dem DirectCast durch das ganze DataSet durchlaufen kann?

    VB.NET-Quellcode

    1. Dim currentpositionrow = DirectCast(DirectCast(EinzelangebotBindingSource.Current, DataRowView).Row, Kundenangebot.EinzelangebotRow)
    2. Y = 500
    3. recordsperpage = 3
    4. For i = index To EinzelangebotBindingSource.Count - 1
    5. netto = currentpositionrow.Netto
    6. mwst = currentpositionrow.MwSt
    7. brutto = currentpositionrow.Brutto
    8. Dim j As Integer
    9. j = 10 + (currentrecord * 10)
    10. element = currentpositionrow.Element
    11. dicke = currentpositionrow.Kerndicke
    12. länge = currentpositionrow.Länge
    13. ep = currentpositionrow._Preis__inkl__Fracht_


    Die Schleife bleibt immer in der gleichen Zeile und durchläuft nicht das DataSet. Dadurch werden immer die gleichen Zeilen gedruckt, was ja nicht richtig ist.

    Wenn ich einen untypisierten Zugriff auf das DataSet einstelle, kann ich das DataSet durchlaufen

    VB.NET-Quellcode

    1. netto = CDbl(Kundenangebot.Einzelangebot.Rows(i).Item("Netto").ToString)


    Wie bekomme ich das beim typisierten Zugriff hin?

    lg, silver

    silverbob76GE schrieb:

    Irgend ne Idee wie ich mit dem DirectCast durch das ganze DataSet durchlaufen kann?
    Du musst einfach die aktuelle Zeile durchiterieren,
    im BindingContext ist das die Property Position.
    social.msdn.microsoft.com/Foru…rd?forum=adodotnetdataset
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @RodFromGermany

    bedeutet dann:

    VB.NET-Quellcode

    1. For i = index To EinzelangebotBindingSource.Position
    2. '....code
    3. EinzelangebotBindingSource.Position = EinzelangebotBindingSource.Position +1
    4. Next


    Das funzt nicht, mache ich da noch was falsch? Muss ich die For schleife anders starten? Bekomme immer nur die erste Zeile im Druck.