Problem beim drucken multipler Seiten mit fortlaufendem Text

  • VB.NET

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

    silverbob76GE schrieb:

    ein Textbaustein
    ist der Text in einem XML-Knoten, wo in der Tabelle 10, 20, 30 usw. davor steht.
    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!

    silverbob76GE schrieb:

    Dann wird genau 1 DataRow gedruckt.
    Das ist doch nicht Sinn der Sache.
    Lagere alles in die Prozedur aus, und die wird zwei Mal aufgerufen.
    Für Seite 1 und die anderen Seiten.
    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!
    Also For-Schleife wieder rein. Aktuell sieht der Code nicht vor, das ich zwischen den Seiten unterscheide, also sprich:

    VB.NET-Quellcode

    1. If pagenb = 0 then
    2. End
    3. If pagenb > 0 then
    4. End if


    ist nicht mehr enthalten. Ich fange oben an, durchlaufe die Schleife, wenn die Seite nicht ausreicht, wird eine neue gedruckt.
    Das klappt jetzt aber nur bis Ende Seite 1, siehe Bild. Auf Seite 2 ist nichts mehr gedruckt.
    Bilder
    • Screenshot1.png

      57,22 kB, 1.372×931, 47 mal angesehen
    Ich habs jetzt hinbekommen, das die Seiten gedruckt werden. Allerdiongs wird der Druck der DataRow nicht an der Stelle fortgeführt, an der aufgehört wurde.
    Aber es wird erkannt wo das Seitenende ist und auf der nächsten Seite weiter gedruckt.

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub PrintDocument1_PrintPage(sender As Object, e As Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
    2. 'Druckprozedur
    3. Dim margin = PrintDocument1.DefaultPageSettings.Margins
    4. Dim g = e.Graphics
    5. Dim brush As New SolidBrush(Color.LightGray)
    6. Dim brush1 As New SolidBrush(Color.Black)
    7. Dim pen1 As New Pen(Brushes.LightGray, 0.5)
    8. Dim pen2 As New Pen(Brushes.DarkGray, 0.5)
    9. Dim pen3 As New Pen(Brushes.White, 0.5)
    10. Dim LineHeight As Single = Me.myfont.GetHeight
    11. margin.Left = 30
    12. margin.Right = 30
    13. margin.Top = 30
    14. margin.Bottom = 30
    15. leftMargin = margin.Left
    16. rightMargin = margin.Right
    17. topMargin = margin.Top
    18. bottomMargin = margin.Bottom
    19. 'Druckbereich
    20. Dim rc = e.Graphics.VisibleClipBounds
    21. rc.Offset(margin.Left + 30, margin.Top + 30) ' obere linke Ecke
    22. rc.Width -= (margin.Left + 20 + margin.Right - 20) ' neue Breite
    23. rc.Height -= (margin.Top + margin.Bottom) ' neue Höhe
    24. X = leftMargin
    25. Y = topMargin
    26. Dim strformat As New StringFormat(StringFormat.GenericTypographic)
    27. Dim charactersfitted As Integer
    28. Dim linesfilled As Integer
    29. If pagenb = 0 Then ' Druck der ersten Seite
    30. DrawHeader(g) ' Kopfzeile auf erster Seite
    31. DrawRectangle(g, brush) ' Tabellenkopfzeile als farbiges Rechteck
    32. 'DataTable enthält Rechnungspositionen. Damit alle DataRows der DataTable gedruckt werden, Iteration mit For-Schleife durch
    33. 'Bindingsource.
    34. For i = index To FKAuftragsübersichtAuftragsdetailBindingSource.Count - 1
    35. Dim row1 = DirectCast(DirectCast(FKAuftragsübersichtAuftragsdetailBindingSource.Current, DataRowView).Row, DtsAufträge.AuftragsdetailRow)
    36. Dim B = 380
    37. Dim area As New SizeF(380, e.MarginBounds.Height - Y)
    38. indextext = 0
    39. 'Prüfung der Länge des Strings in der DataRow
    40. Dim S As SizeF = e.Graphics.MeasureString(row1.Leistung.Substring(indextext), myfont, area, strformat, charactersfitted, linesfilled)
    41. Dim fläche As New Rectangle(X + 60, Y + 35, 380, e.MarginBounds.Height - Y)
    42. 'bestimmt die Höhe der zu druckenden Zeile
    43. Dim Hoch As Double = Ausgabenhöhe(S, B)
    44. DrawRow1Info(g, pen3, strformat, row1, fläche, Hoch, B, charactersfitted)
    45. 'DataRow in Tabellenform gedruckt
    46. 'Zeichnung der Tabellenzellen
    47. DrawHoch(g, pen1, Hoch) '
    48. g.DrawString(String.Format(" - Seite {0} -", pagenb + 1), myfont, brush, 380, 1130)
    49. index += 1
    50. FKAuftragsübersichtAuftragsdetailBindingSource.MoveNext()
    51. indextext += charactersfitted
    52. If indextext < row1.Leistung.Length Then
    53. e.HasMorePages = True
    54. pagenb += 1
    55. Return
    56. End If 'keine weiteren Seiten für Druck vorhanden
    57. Next
    58. End If
    59. If pagenb >= 1 Then ' Druck der ersten Seite
    60. indextext = charactersfitted
    61. Y += 80
    62. DrawRectangle(g, brush) ' Tabellenkopfzeile als farbiges Rechteck
    63. 'DataTable enthält Rechnungspositionen. Damit alle DataRows der DataTable gedruckt werden, Iteration mit For-Schleife durch
    64. 'Bindingsource.
    65. For i = index To FKAuftragsübersichtAuftragsdetailBindingSource.Count - 1
    66. Dim row1 = DirectCast(DirectCast(FKAuftragsübersichtAuftragsdetailBindingSource.Current, DataRowView).Row, DtsAufträge.AuftragsdetailRow)
    67. Dim B = 380
    68. Dim area As New SizeF(380, e.MarginBounds.Height - Y)
    69. 'indextext = charactersfitted
    70. indextext = 0
    71. 'Prüfung der Länge des Strings in der DataRow
    72. Dim S As SizeF = e.Graphics.MeasureString(row1.Leistung.Substring(indextext), myfont, area, strformat, charactersfitted, linesfilled)
    73. Dim druckfläche As New Rectangle(X + 60, Y + 35, 380, e.MarginBounds.Height - Y)
    74. 'e.Graphics.DrawString(row1.Leistung.Substring(indextext, charactersfitted), myfont, brush, fläche, strformat)
    75. 'bestimmt die Höhe der zu druckenden Zeile
    76. Dim Hoch As Double = Ausgabenhöhe(S, B)
    77. 'DataRow in Tabellenform gedruckt
    78. DrawRow1Info(g, pen3, strformat, row1, druckfläche, Hoch, B, charactersfitted)
    79. 'Zeichnung der Tabellenzellen
    80. DrawHoch(g, pen1, Hoch) '
    81. 'Zähler für die Position in der BindingSource
    82. index += 1
    83. g.DrawString(String.Format(" - Seite {0} -", pagenb + 1), myfont, brush, 380, 1130)
    84. FKAuftragsübersichtAuftragsdetailBindingSource.MoveNext()
    85. indextext += charactersfitted
    86. If indextext < row1.Leistung.Length Then
    87. e.HasMorePages = True
    88. pagenb += 1
    89. Exit Sub
    90. End If
    91. Next
    92. End If
    93. End Sub


    Wie schaffe ich es nun, das der Druck an richtiger Stelle fortgeführt wird? Wenn ich die Variable Indextext (stellt die Position des Textes dar) nicht Null setze, bekomme ich die Fehlermeldung:
    "startindex cannot be larger then length of string". Wenn ich den Indextext nulle, kann ich den Text nicht auf nächster Seite fortführen, oder?

    silverbob76GE schrieb:

    Wie schaffe ich es nun, das der Druck an richtiger Stelle fortgeführt wird?
    Du musst jeden Textbaustein in sich allein behandeln.
    Wisse, in welche Zeile Du jetzt druckst und wisse, wie viele Zeilen noch auf das Papier passen und wisse, welchen Textbaustein Du gerade bearbeitest.
    Dein Aufruf sollte also so aussehen:

    Quellcode

    1. Dim Flag = DruckeTextBaustein(Nummer, ...)
    2. If Flag Then
    3. ' speichere eine Reihe von Variablen in der Klasse
    4. e.HasMorePages = True
    5. pagenb += 1
    6. Return
    7. End If
    Wobei Flag aussagt, ob der Textbaustein vollständig gedruckt wurde.
    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

    also mit der for schleife durchlaufe ich das dataset. Soll ich nun die Flag dort einarbeiten und dabei prüfen ob die zu druckende zeile auf die seite passt? Bin gerade total überfragt und komme auch nicht mehr weiter.

    wie soll das aussehen?

    Dim Flag = DruckeTextBaustein(row1.leistung, row1.pos, row1. menge, etc…)

    If Flag(row1.leistung.length) > indextext then?

    End if

    weiss nicht wirklich was ich da machen soll. Kann auch die Anzahl Zeilen abfragen und wenn die maximale Zeilenanzahl je Seite überschritten wird abbrechen. Aber dann wird doch der text auch abgebrochen.
    @silverbob76GE Über welche Programmiererfahrung verfügst Du?
    Welcher Datentyp wird in meinem Snippet für Flag impliziert?
    Welcher Datentyp wird in Deinem Snippet für Flag impliziert?
    Das Ergebnis des Aufrufs meiner Funktion DruckeTextBaustein(...) ist, ob der Textbaustein vollständig gedruckt wurde oder nicht.
    Wenn ja, geht es weiter mit dem nächsten Textbaustein.
    Wenn nein, muss noch der Rest desselben Textbausteins gedruckt werden, deswegen musst Du einige Werte abspeichern, z.B. die Position, ab der der aktuelle Baustein weiter gedruckt wird.
    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!
    Hallo @RodFromGermany

    1. ich würde behaupten, das ich Anfänger bin, mehr nicht. Flag ist für mich komplett neu und habe ich vorher auch noch nie gehört, daher bin ich auch gerade etwas überfordert.
    Habe mir das Wissen über Jahre angeeignet, hier aus dem Forum mit eurer Hilfe und Tutorials, viel auch über Google.
    2. Denke, das dein Datentyp ein Boolean ist. Also wahr oder falsch, daher die IF Abfrage danach.
    3. Meiin Snippet ergibt dann natürlich keinen Sinn.

    Ich könnte über die Zeilenhöhe abfragen, wann die aktuelle Zeile gleich der Maxzeile ist und dann den Seitenwechsel ausprobieren, richtig?
    Auf der nächsten Seite muss es dann an der abgerochenen Stelle weitergehen.

    Ich weiß nicht, was in das Flag rein muss. Daher hatte ich angenommen, das da die Werte aus der DataRow rein müssen.

    silverbob76GE schrieb:

    Daher hatte ich angenommen, das da die Werte aus der DataRow rein müssen.
    In einen Wert vom Type Boolean?
    Flag ist ein grundlegend elementarer Basis-Begriff der Programmierung und kommt in allen Programmiersprachen vor.
    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!
    Ich war ne Weile AFK, bitte nicht im Dreieck springen, wenn ich was verpasst habe.
    Ich werf mal was anderes in den Raum: Du zeichnest die DataRow-Bestandteile, die auf jeden Fall noch Platz finden. Dann rufst Du eine Methode auf, die Dir den Teil des Textes der DataRow zurückgibt, der noch auf die Seite passt. Wenn alles draufpasst, setzt Du ein Zeichen, dass noch weitere DataRows auf die Seite passen. Ansonsten merkst Du Dir, wieviel vom aktuellen Text schon aufgedruckt wurde und somit was noch fehlt und beim nächsten Mal (nächste Seite) draufmuss. Bei letzterem darf eben der Rest der DataRow-Daten nicht nochmal gedruckt werden.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    @VaporiZed, den gleichen Gedanken hatte ich auch.

    Ich hab mir gedacht, das ich den restlichen platz berechne und schaue, ob mein String da rein passt. Wenn nicht, den Text splitten und auf nächster Seite drucken.
    Muss nun noch klären, wie ich das angehe.

    silverbob76GE schrieb:

    Muss nun noch klären, wie ich das angehe.
    Bist Du beratungsresistent?
    Ich habe Dir in Post #19 dieses Deines Threads ein in sich geschlossenes Beispiel gegeben, was exakt das tut.
    Darf ich davon ausgehen, dass Du Dir es noch nicht mal angesehen hast?
    Noch eine solche kontraproduktive Antwort und ich bin raus hier. X(
    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!
    Du brauchst einmal eine String-Variable, die Teile des großen Textes aufnimmt. Zu Beginn einer neuen DataRow ist sie leer. Dann misst Du aus, wieviel Platz auf der Seite noch ist. Du übergibst DataRow, Stringvariable, Scriftart und verfügbaren Platz (Rectangle) an eine Methode und diese ermittelt, ob der Text in das Rectangle reinpasst. Wenn der Text mit MeasureString so hoch ist wie das Rectangle, wird der Text wohl nicht reinpassen und die Methode muss den Text Wort für Wort kürzen, bis es passt. Vielleicht ist es sogar besser, das Rectangle etwas größer zu machen. Wenn MeasureString die Höhe des zu großen Rectangles wiedergibt, ist der Text definitiv zuviel. Erst, wenn der Text nicht mehr so hoch ist, passt der Text noch auf die Seite. Sobald der Text soweit gekürzt ist, dass er draufpasst, wird dieser Text in der Stringvariable gespeichert und eine Markierung (Flag) gesetzt, dass die aktuelle DataRow inhaltlich noch nicht vollständig gedruckt wurde.
    Danach wird geschaut, ob die aktuelle DataRow vollständig gedruckt wurde. Falls ja, geht es mit der nächsten DataRow weiter. Falls nein, wird der Text der aktuellen DataRow um den schon gedruckten Inhalt gekürzt, der restliche Text gedruckt, die anderen Bestandteile nicht nochmal.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    @RodFromGermany, wenn du meine Posts gelesen hättest, wüsstest du das ich versuche, das umzusetzen was du geschrieben hast.
    Leider scheiterts daran, das mir das Wissen dazu fehlt, was du mir empfiehlst. Also nicht gleich sauer sein, aber einiges was du emfpiehlst sprengt meinen aktuellen Wissensstand.

    Ich bin immer noch dabei, die Posts nachzuarbeiten und leider auch ein wenig genervt und versuche meinerseits wege zu finden, die ich verstehen und nachvollziehen kann. Leider dauert das alles sehr lange.
    Ist ja nicht so, das der Code den du in Post 19 geposted hast, für mich sofort vollständig nachvollziehbar ist. Da muss ich erst mal ein wenig nacharbeiten. Aber glaub mir, hab bis Dato alles gelesen was du in dem Thread posted, verstanden noch nicht.
    Wenn du helfen magst, sehr gerne, und Danke dafür. Mag bei dir vielleicht so ankommen, als würde man dir nicht zuhören. Aber ich glaube, da deutest du etwas komplett falsch.
    Wenn hier einer Hilfe sucht, dann weil er nicht weiterkommt und vermutlich schon sehr viel probiert hat. Wenn dann jemand antwortet, ist man dankbar und voller Hoffnung, das man vorankommt und das Ziel
    vielleicht bald erreicht. Da machts keinen Spaß sich noch was vorwerfen zu lassen. Das ich kein Profi bin weiß ich selber, daran muss mich keiner erinnern. Ich bin ein Newb, aber bemüht.

    @VaporiZed, sowas ähnliches hatte ich mir in Gedanken schon ausgemalt. Wie ich das in Code packe, weiß ich noch nicht. Aber wie @RodFromGermany geschrieben hat, hatte er mir einen WInk mit dem Zaunpfahl in Post 19 gegeben.
    Wenn ich den verstanden habe, bin ich ein ganzes Stück weiter.

    Auch wenn wir Newbs manchmal dämliche Fragen stellen oder nicht sofort auf eure schritt für schritt Anleitungen richtig antworten oder reagieren können, oder eure zielführenden Tips nicht sofort umsetzen können heißt das nicht, das wir nicht für jede Hilfe dankbar sind. Habt bitte etwas Geduld.

    Danke für jede weitere Antwort.

    silverbob76GE schrieb:

    aber einiges was du emfpiehlst sprengt meinen aktuellen Wissensstand.
    Dann stell ganz konkrete Fragen zu jedem Detail einzeln.
    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!
    also Tabellen drucken ist immer ein lausiges Geschäft.
    Mir fehlt in diesem Thread überhaupt eine Art Masterplan.
    Wieviele Spalten gibt es, und wie wird deren Breite festgelegt?
    Womöglich wird eine SeitenVorschau nötig, nach der der User die Breiten neu festlegen möchte.

    Jdfs erst nach Festlegung der Spaltenbreiten kann man die Tabelle durchgehen, und muss nun Spalte für Spalte vermessen.
    Dabei kann sich Mehrzeiligkeit in verschiedenen Spalten ergeben: Diejenige Spalte mit der höchsten Anzahl Zeilumbrüche ist massgeblich.
    Danach entscheidet sich, ob Seitenwechsel, oder obs noch passt.

    Man braucht auch mehrere TeilDruckRoutinen:

    Quellcode

    1. je Seite:
    2. Seiten-Kopf
    3. Seiten-Fuss
    4. RechnungsKopf
    5. Geht die Tabelle über mehrere Seiten, braucht man auch dieses je Seite:
    6. Tabellen-Header
    7. Tabellen-Inhalte
    8. RechnungsFuss

    An Infrastruktur wird wohl eine Routine zum Rahmen-Malen angezeigt sein, und eine für den Zell-Inhalt.
    Und eine Routine für Fliesstext (Rech-Kopf/Fuss) - vielleicht kann man die auch für Seiten-Kopf/Fuss mitverwenden, sonst dafür nochma extra.

    (Also ich finde, mit post#19 allein wird man diese Bretter noch lange nicht gebohrt kriegen)

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „ErfinderDesRades“ ()

    @RodFromGermany

    habe meinen Demo-Code gemäß Post 19 mal angepasst.

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub PrintDocument1_PrintPage(sender As Object, e As Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
    2. 'Druckprozedur
    3. Dim margin = PrintDocument1.DefaultPageSettings.Margins
    4. Dim g = e.Graphics
    5. Dim brush As New SolidBrush(Color.LightGray)
    6. Dim brush1 As New SolidBrush(Color.Black)
    7. Dim pen1 As New Pen(Brushes.LightGray, 0.5)
    8. Dim pen2 As New Pen(Brushes.DarkGray, 0.5)
    9. Dim pen3 As New Pen(Brushes.White, 0.5)
    10. 'Dim LineHeight As Single = Me.myfont.GetHeight
    11. margin.Left = 30
    12. margin.Right = 30
    13. margin.Top = 30
    14. margin.Bottom = 30
    15. leftMargin = margin.Left
    16. rightMargin = margin.Right
    17. topMargin = margin.Top
    18. bottomMargin = margin.Bottom
    19. 'Druckbereich
    20. Dim rc = e.Graphics.VisibleClipBounds
    21. rc.Offset(margin.Left + 30, margin.Top + 30) ' obere linke Ecke
    22. rc.Width -= (margin.Left + 20 + margin.Right - 20) ' neue Breite
    23. rc.Height -= (margin.Top + margin.Bottom) ' neue Höhe
    24. X = leftMargin
    25. Y = topMargin
    26. DrawHeader(g)
    27. DrawRectangle(g, brush)
    28. Dim row1 = DirectCast(DirectCast(FKAuftragsübersichtAuftragsdetailBindingSource.Current, DataRowView).Row, DtsAufträge.AuftragsdetailRow)
    29. Dim sb As New System.Text.StringBuilder(row1.Leistung.Substring(indextext))
    30. Dim charactersfitted As Integer
    31. Dim linesfilled As Integer
    32. maxrows = 60
    33. Using sf As New StringFormat()
    34. ' nur vollständige Zeilen drucken
    35. sf.FormatFlags = StringFormatFlags.LineLimit
    36. ' die noch zu druckenden Zeichen holen
    37. Dim S As SizeF = New SizeF(380, myfont.GetHeight * linesfilled)
    38. Dim rec As New RectangleF(X + 60, Y + 35, 380, myfont.GetHeight * linesfilled)
    39. ' die Anzahl der druckbaren Zeichen bestimmen
    40. g.MeasureString(sb.ToString(), myfont, S, sf, charactersfitted, linesfilled)
    41. DrawHoch(g, pen1, Hoch:=CInt(myfont.GetHeight * linesfilled + 20))
    42. ' der eigentliche Druck
    43. g.DrawString(sb.ToString(0, charactersfitted), myfont, Brushes.Black, rec, sf)
    44. indextext += charactersfitted
    45. e.HasMorePages = indextext < row1.Leistung.Length
    46. End Using
    47. End if


    Es wird genau ein Textbaustein gedruckt. Aber wie komme ich nun weiter? Kann das alles in eine For-Schleife einbinden, die bindingsoruce durchlaufen. Muss aber die Variable Indextext (Zähöer der gedruckten Buchstaben) auf Null setzen, da ich sonst eine Fehlermeldung bekomme
    "startindex cannot be longer then length of string".

    @ErfinderDesRades

    Die Tabelle die ich drucke, baut auf einer typisierten DataTable auf. Die zu druckenden Daten hole ich aus der BindingSource.
    Es werden 6 Spalten gedruckt:

    - Position (String), Leistung (String), Menge (Double), Einheit (String), Einzelpreis (Dec), Gesamtpreis (Dec)

    Die maßgebende Spalte ist "Leistung", da hier der Text zu den ausgeführten Leistungen gescrhieben wird. Die Textlänge kann variieren, alle anderen Spalten erfodern keinen Zeileumbruch, da die Zeichenanzahl innerhalb des zur Verfügung stehenden Bereichs gedruckt werden kann.
    Die Spaltenbreiten sind also festgelegt.

    Der Ausdruck beinhaltet einen

    - Seitenkopf mit Bauvorhaben, Rechnungs und Auftragsnummer, etc.
    - Ansprechpartner mit Kontaktdaten
    - Seitenfuss (Firmendaten, Bankverbindung, etc)
    - Rechnungspositionen in Tabellenform, auch über mehrere Seiten.

    Der einfache Ausdruck einer Tabelle mit einzeiligen Zeilen ist kein Problem, funzt auch so weit. Rahmenzellen etc. soweit vorhanden.
    Mein Problem ist, das es bei mehrzeiligem text dazu kommt, das dieser nicht bei Seitenende abgebrochen und auf der nächsten Seite fortgeführt wird. Post 19 bezieht sich eher darauf zu verstehen, wann das Seitenende erreicht und eine neue Seite angefangen werden muss. Den Code für die aktuelle Anwendung schreibe ich seit mehreren Monaten, die komplette Anwendung ist viel umfangreicher. Dies ist nur ein Anwendungsmodul des ganzen. Vor dem Druckvorgang habe ich mich lange gedrückt, wollte das aber nun endlich angehen Wie sich herausstellt, viel komplexer als ich angenommen hatte.
    Bilder
    • Screenshot 2 Seiten.png

      112,69 kB, 1.297×906, 38 mal angesehen
    Dateien
    • test.pdf

      (74,8 kB, 37 mal heruntergeladen, zuletzt: )

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

    @silverbob76GE Du hast das mit der BindingSource doch schon gelöst gehabt.
    Ich hab Dir doch geschrieben, wie es weiter geht.
    In der Prozedur misst Du den verbleibenden Platz aus. Ist genug Platz da, druckst Du und machst mit dem nächsten Text weiter.
    Ist nicht genug Platz da, druckst Du so viel wie hin passt, speicherst die letzte gedruckte bzw. die erste nicht gedruckte Position ab und sagst der aufrufenden Prozedur Bescheid (Returnwert), weiter mit der nächsten Seite und demselben Text ab der gespeicherten Position.
    ==============
    Diese Brushes und Pens usw. gehören nicht in die Prozedur, sondern in die Klasse:

    VB.NET-Quellcode

    1. Dim brush As New SolidBrush(Color.LightGray)
    2. Dim brush1 As New SolidBrush(Color.Black)
    3. Dim pen1 As New Pen(Brushes.LightGray, 0.5)
    4. Dim pen2 As New Pen(Brushes.DarkGray, 0.5)
    5. Dim pen3 As New Pen(Brushes.White, 0.5)
    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!