Mahlzeit.
So langsam muss ich auch die Drucken-Thematik in meinem Programm mal angehen. Ich dachte mir, ich bastel'
was, womit man jedes beliebige DGV ausdrucken kann. (Ja, extra DGV-Inhalt und nicht DataTable - ich erweitere das später
um eine Vorabauswahl für Spalten und Rows)
Ich muss zugeben, das ganze Gedöns mit dem Drucken (alles muss "gemalt" werden, neue Seite erstellen etc.) ist für mich komplexer als die ganze
Datenverarbeitungs-Sachen die ich inzwischen betreibe..
Die Druckvorschau sieht soweit schon ganz ordentlich aus, allerdings:
- schießen manche "Zellinhalte" (
- ich hab's hinbekommen, dass wenn die Header erstellt werden, er weitere Seiten erstellt und die restlichen Header dahin verteilt. Außerdem
erstelle ich für jeden Header direkt die entsprechenden Zellinhalte mit.
Was passiert jetzt aber, wenn die Zeilen mehr werden, als es die Seite zu lässt? Hier müsste wieder eine neue Seite erstellt werden und die Header von der 1.
wieder mit angedruckt werden.
- ich will mir nen eigenen
2 Radiobuttons erstellt für die Einstellung Hochformat/Querformat. Dazu ein entsprechendes Handling geschrieben:
Da tut sich allerdings nix, wenn ich die Radiobuttons anklicke (also die Ansicht ändert sich im PrintPreview nicht).
Ich hätte gedacht, dass sich dort die Ansicht ändert und auch die Seiten "neu erstellt" werden. Denn im Querformat hätte man ja z.B. mehr Platz für die Header.
Könnt ihr mir sagen, wie ich das am besten anstelle?
Anbei mein bisheriger Print-Code (erstmal nur Druckvorschau, Rest kommt später wenn das alles passt):
Spoiler anzeigen
PS: Ich hab mich ein bisschen an dem Code von diesem Thread bedient, allerdings muss es bei mir flexibel sein, da sich die Spalten ja auch je nach DGV ändern
: vb-paradise.de/index.php/Threa…ostID=1173341#post1173341
So langsam muss ich auch die Drucken-Thematik in meinem Programm mal angehen. Ich dachte mir, ich bastel'
was, womit man jedes beliebige DGV ausdrucken kann. (Ja, extra DGV-Inhalt und nicht DataTable - ich erweitere das später
um eine Vorabauswahl für Spalten und Rows)
Ich muss zugeben, das ganze Gedöns mit dem Drucken (alles muss "gemalt" werden, neue Seite erstellen etc.) ist für mich komplexer als die ganze
Datenverarbeitungs-Sachen die ich inzwischen betreibe..

Die Druckvorschau sieht soweit schon ganz ordentlich aus, allerdings:
- schießen manche "Zellinhalte" (
FormattedValue.ToString
) über die Rectangles hinaus, obwohl ich die per MeasureString
ausgemessen habe- ich hab's hinbekommen, dass wenn die Header erstellt werden, er weitere Seiten erstellt und die restlichen Header dahin verteilt. Außerdem
erstelle ich für jeden Header direkt die entsprechenden Zellinhalte mit.
Was passiert jetzt aber, wenn die Zeilen mehr werden, als es die Seite zu lässt? Hier müsste wieder eine neue Seite erstellt werden und die Header von der 1.
wieder mit angedruckt werden.
- ich will mir nen eigenen
PrintPreview-Dialog
bauen, dazu hab ich erstmal nen einfachen Dialog, da das PrintPreviewControl
drauf gezogen und2 Radiobuttons erstellt für die Einstellung Hochformat/Querformat. Dazu ein entsprechendes Handling geschrieben:
VB.NET-Quellcode
- Private Sub rbtn_CheckedChanged(sender As Object, e As EventArgs) Handles rbtnHochformat.CheckedChanged,
- rbtnQuerformat.CheckedChanged
- If rbtnHochformat.Checked Then
- Me.PrintPreviewControl1.Document.DefaultPageSettings.Landscape = False
- Else
- Me.PrintPreviewControl1.Document.DefaultPageSettings.Landscape = True
- End If
- End Sub
Da tut sich allerdings nix, wenn ich die Radiobuttons anklicke (also die Ansicht ändert sich im PrintPreview nicht).
Ich hätte gedacht, dass sich dort die Ansicht ändert und auch die Seiten "neu erstellt" werden. Denn im Querformat hätte man ja z.B. mehr Platz für die Header.
Könnt ihr mir sagen, wie ich das am besten anstelle?
Anbei mein bisheriger Print-Code (erstmal nur Druckvorschau, Rest kommt später wenn das alles passt):
VB.NET-Quellcode
- Imports System.Drawing, System.Drawing.Printing
- Public Module Print
- Private WithEvents _PrintDoc As PrintDocument
- Private _dgv As DataGridView
- Private _myfont As Font = New Font("Arial", 11, FontStyle.Regular)
- Private _activeColIndex As Integer
- Private _totalWidth As Integer
- Private _penGray As New Pen(Brushes.LightGray, 0.5)
- 'TODO: Abfangen, wenn Headertext im DGV mehrzeilig angezeigt wird (ist dann soll er auch mehrzeilig gedruckt werden
- Public Sub PrintDgv(DocumentName As String, dgv As DataGridView)
- _PrintDoc = New PrintDocument With {.DocumentName = DocumentName}
- _dgv = dgv
- _activeColIndex = 0
- _totalWidth = 0
- Using dlgPreview As New dlgPrintPreview
- 'dlgPreview.WindowState = FormWindowState.Maximized
- dlgPreview.PrintPreviewControl1.Document = _PrintDoc
- dlgPreview.ShowDialog()
- End Using
- End Sub
- Private Sub PrintDoc_PrintPage(sender As Object, e As PrintPageEventArgs) Handles _PrintDoc.PrintPage
- Dim g = e.Graphics
- Dim margin = _PrintDoc.DefaultPageSettings.Margins
- Dim X = margin.Left
- Dim Y = margin.Top
- Dim drawText As Action(Of String, Integer, Integer) = Sub(s, dx, dy) g.DrawString(s, _myfont, Brushes.Black, X + dx, Y + dy)
- drawText(_PrintDoc.DocumentName, 0, 0) 'Titel
- Y += 30
- Dim kvpOfColsAndMaxWidth = GetVisibleColAndMaxWidth(g)
- Dim maxPrintWidth = _PrintDoc.DefaultPageSettings.PaperSize.Width - _PrintDoc.DefaultPageSettings.Margins.Right 'die maximale Breite nach rechts
- For Each colAndMaxWidth In kvpOfColsAndMaxWidth
- If colAndMaxWidth.Key.Index < _activeColIndex Then Continue For
- If _totalWidth + colAndMaxWidth.Value > maxPrintWidth Then 'wenn die Breite überschritten würde, dann hier abbrechen und nach return mit der Col weitermachen
- If Not e.HasMorePages Then e.HasMorePages = True
- _activeColIndex = colAndMaxWidth.Key.Index
- _totalWidth = 0 'totalWidth muss für eine neue Seite natürlich zurückgesetzt werden
- Return
- End If
- DrawHeader(g, X, Y, _totalWidth, colAndMaxWidth)
- DrawFormattedValue(g, X, Y, _totalWidth, colAndMaxWidth)
- _totalWidth += colAndMaxWidth.Value
- Next
- If e.HasMorePages Then e.HasMorePages = False
- End Sub
- ''' <summary>Speichert alle sichtbaren DGV-Columns, sowie die maximale Schriftbreite der Spalte (oder HeaderCell-Breite, falls größer) in einem Dictionary</summary>
- Private Function GetVisibleColAndMaxWidth(g As Graphics) As Dictionary(Of DataGridViewColumn, Integer)
- Dim dic As New Dictionary(Of DataGridViewColumn, Integer)
- For i = 0 To _dgv.ColumnsX.Where(Function(col) col.Visible).Count - 1
- Dim colIndex = i
- 'Dim maxCellWidth = _dgv.RowsX.Select(Function(rw) rw.Cells(colIndex).Size.Width).Max
- Dim maxCellContentWidth = g.MeasureString(_dgv.RowsX.Select(Function(rw) rw.Cells(colIndex).FormattedValue.ToString).Max, _myfont) 'TODO: klappt noch nicht zu 100%
- Dim colWidth = _dgv.Columns(i).Width
- If colWidth > maxCellContentWidth.Width Then
- dic.Add(_dgv.Columns(colIndex), colWidth)
- Else
- dic.Add(_dgv.Columns(colIndex), CInt(maxCellContentWidth.Width))
- End If
- Next
- Return dic
- End Function
- Private Sub DrawHeader(g As Graphics, x As Integer, y As Integer, totalWidth As Integer, colAndMaxWidth As KeyValuePair(Of DataGridViewColumn, Integer))
- Dim drawHeaderText As Action(Of String, Integer) = Sub(s, dx) g.DrawString(s, _myfont, Brushes.Black, x + dx, y + 5)
- g.FillRectangle(Brushes.LightGray, x + totalWidth, y, colAndMaxWidth.Value, 30)
- drawHeaderText(colAndMaxWidth.Key.HeaderText, totalWidth)
- End Sub
- Private Sub DrawFormattedValue(g As Graphics, x As Integer, y As Integer, totalWidth As Integer, colAndMaxWidth As KeyValuePair(Of DataGridViewColumn, Integer))
- Dim drawRowText As Action(Of String, Integer, Integer) = Sub(s, dx, dy) g.DrawString(s, _myfont, Brushes.Black, x + dx, y + dy)
- Dim rowPos = 35
- For Each rw In _dgv.RowsX
- Dim formattedValue = rw.Cells(colAndMaxWidth.Key.Index).FormattedValue.ToString
- If formattedValue = "True" Then formattedValue = "Ja"
- If formattedValue = "False" Then formattedValue = "Nein"
- drawRowText(formattedValue, totalWidth, rowPos)
- g.DrawRectangle(_penGray, x + totalWidth, y + rowPos, colAndMaxWidth.Value, 30) 'x,x + rowPos - 5, totalWidth + colAndMaxWidth.Value, x + rowPos - 5) 'zu weit rechts, teilweise unterschiedlich lang
- rowPos += 30
- Next
- End Sub
- End Module
PS: Ich hab mich ein bisschen an dem Code von diesem Thread bedient, allerdings muss es bei mir flexibel sein, da sich die Spalten ja auch je nach DGV ändern

"Na, wie ist das Wetter bei dir?"
"Caps Lock."
"Hä?"
"Shift ohne Ende!"
"Caps Lock."
"Hä?"
"Shift ohne Ende!"
