If you aren't using Crystal Reports (which you probably should look into if you're doing database reporting and want a form-like invoice) then you have two basic choices:
1) "Simple printing", as described in the 101 VB .NET samples "VB.NET - Windows Forms - Simple Printing". This allows you to print in one font and one fontstyle of that font, in a single print area per printdocument. There may be a way to get more than one print area on a single page but I wasn't able to discover how (doesn't look to me like this is possible, certainly isn't easy). This was too limited for me so I did a little more digging.
2) If you want mixed fonts and mixed fontstyles, or if you want multiple columns, you can extend the RichTextBox control to interact with the EM_FORMATRANGE Windows API function. A guy named Martin Müller did this initially to allow the mixed fonts/fontstyles, and I extended his control a little further to support multiple print columns. Attached is a small project that you are free to use if you think it may help.
An example of how to use this control is below, in a form that has a PrintDocument control, a PrintDialog control, and a pair of richtextboxex2 controls, to print two columns:
Code:
'declared form-wide
Private PrintPageSettings As New PageSettings()
Private iMainFirstCharLeft, iMainFirstCharRight As Integer
'(... some code to stick text into rtxtLeft and rtxtRight controls ...)
'(... menu option/button to call DoPrintMainSheet ...)
Private Sub DoPrintMainSheet()
Try
PrintDocument1.DefaultPageSettings = PrintPageSettings
dlgPrint.Document = PrintDocument1
Dim result As DialogResult = dlgPrint.ShowDialog()
If result = DialogResult.OK Then
PrintDocument1.Print()
End If
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Exclamation, "Printing error!")
End Try
End Sub
Private Sub PrintDocument1_PrintPage(ByVal sender As System.Object, _
ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
'Call the RenderFormatRange function added to
'RichTextBoxEx2, which calls the API EM_FORMATRANGE
'Calling it this way results in two columns with a 20/100ths
'of an inch gutter between the two columns
iMainFirstCharLeft = rtxLeft.RenderFormatRange(False, e, iMainFirstCharLeft, rtxLeft.TextLength, _
e.MarginBounds.Left, (e.PageBounds.Right / 2) - 10)
iMainFirstCharRight = rtxRight.RenderFormatRange(False, e, iMainFirstCharRight, rtxRight.TextLength, _
(e.PageBounds.Right / 2) + 10, e.MarginBounds.Right)
'are we finished printing?
If (iMainFirstCharLeft < rtxLeft.TextLength) Or (iMainFirstCharRight < rtxRight.TextLength) Then
e.HasMorePages = True
Else
e.HasMorePages = False
End If
End Sub
Private Sub PrintDocument1_BeginPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles PrintDocument1.BeginPrint
iMainFirstCharLeft = 0
iMainFirstCharRight = 0
End Sub
Private Sub PrintDocument1_EndPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles PrintDocument1.EndPrint
rtxLeft.FormatRangeDone()
rtxRight.FormatRangeDone()
End Sub