|
-
Jan 4th, 2024, 01:42 PM
#1
Thread Starter
Addicted Member
VB.NET Print total items of ListBox
Trying to print the complete list of items from a listbox using this code. When I set 'e.HasMorePages' to True, it will continue to run on forever. Not sure what I am missing here, but the way this is now only gives me a single page of items. Thanks for any assistance on this.
Code:
Private Sub BtnPrint_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnPrint.Click
PrintDocument1.Print()
End Sub
Private Sub PrintDocument1_PrintPage(ByVal sender As System.Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
Dim fnt As New Font("Arial", 10, FontStyle.Regular, GraphicsUnit.Point)
Dim ListBoxItem As String = String.Empty
For Each LBItem As String In ListBox2.Items
ListBoxItem = ListBoxItem & vbCrLf & LBItem
Next
ListBoxItem = ListBoxItem.Substring(vbCrLf.Length)
e.Graphics.DrawString(ListBoxItem, fnt, Brushes.Black, 0, 0)
e.HasMorePages = False
End Sub
-
Jan 4th, 2024, 05:41 PM
#2
Re: VB.NET Print total items of ListBox
Printing is a bit difficult. Basically what you will need to do is draw the String of each item in the ListBox and if the total height of all that has been drawn will exceed the total height of the page then you need to set HasMorePages to true.
Try something like this (untested and modified from ChatGPT):
Code:
Imports System.Drawing.Printing
Public Class MyForm
Private _startIndex As Integer = 0
Private Sub PrintDocument1_PrintPage(sender As Object, e As PrintPageEventArgs) Handles PrintDocument1.PrintPage
Dim printFont = New Font("Arial", 10, FontStyle.Regular, GraphicsUnit.Point)
Dim lineHeight = printFont.GetHeight(e.Graphics)
Dim printArea = New RectangleF(e.MarginBounds.Left, e.MarginBounds.Top, e.MarginBounds.Width, e.MarginBounds.Height)
Dim itemIndex = _startIndex
Dim listboxItemCount = ListBox2.Items.Count
While (itemIndex < listboxItemCount)
Dim itemText = ListBox2.Items(itemIndex).ToString()
Dim textLayout = New StringFormat()
printArea.Y += lineHeight
Dim linesPerPage = Convert.ToInt32(Math.Floor(printArea.Height / lineHeight))
For i = 0 To linesPerPage - 1
If (itemIndex < listboxItemCount) Then
Dim lineRectangle = New RectangleF(printArea.Left, printArea.Y, printArea.Width, lineHeight)
e.Graphics.DrawString(itemText, printFont, Brushes.Black, lineRectangle, textLayout)
printArea.Y += lineHeight
itemIndex += 1
Else
Exit For
End If
Next
If (itemIndex < listboxItemCount) Then
e.HasMorePages = True
_startIndex = itemIndex
Return
End If
End While
_startIndex = 0
e.HasMorePages = False
End Sub
End Class
Update -
Reviewing this code a little bit, it is potentially flawed a little bit based on your situation.
This code assumes that each item in the ListBox only takes up a single line on the printed document. If that's not the case, then you'll need to adjust the lineHeight variable in the For/Next loop to be recalculated the height of the drawn text.
If you don't have any items that span multiple lines though, then this solution should be fine.
Last edited by dday9; Jan 4th, 2024 at 05:56 PM.
-
Jan 5th, 2024, 11:12 AM
#3
Thread Starter
Addicted Member
Re: VB.NET Print total items of ListBox
Thanks dday9... this does produce strange results like you said. My listbox is populated with info after searching multiple files for a part number and returning filename and qty of each part number within. Here is an example of the listbox contents: "PART NUMBER" is what was searched. "-TOP & -BTM" lines are the filenames found containing the part number and then QTY used. The typical print range on this can be 1 to 10 pages.
Code:
PART NUMBER: GR29-028B
_______________________________
2-900-09-TOP
QTY Per = 4
--------------
2-189-02-BTM
QTY Per = 8
--------------
2-3389-01-TOP
QTY Per = 17
--------------
4-988-023-TOP
QTY Per = 12
-
Jan 5th, 2024, 11:27 AM
#4
Re: VB.NET Print total items of ListBox
I'm not fully understanding the issue, could you elaborate a bit more on what happened when you tried the solution I provided?
-
Jan 5th, 2024, 11:34 AM
#5
Thread Starter
Addicted Member
Re: VB.NET Print total items of ListBox
Sorry, I should have posted that as well. Your code now prints like this:
Code:
PART NUMBER: GR29-028B
PART NUMBER: GR29-028B
PART NUMBER: GR29-028B
PART NUMBER: GR29-028B
PART NUMBER: GR29-028B
PART NUMBER: GR29-028B
PART NUMBER: GR29-028B
PART NUMBER: GR29-028B
PART NUMBER: GR29-028B
PART NUMBER: GR29-028B
--------------------------
--------------------------
--------------------------
--------------------------
--------------------------
--------------------------
--------------------------
--------------------------
--------------------------
--------------------------
--------------------------
--------------------------
QTY Per = 5
QTY Per = 5
QTY Per = 5
QTY Per = 5
QTY Per = 5
QTY Per = 5
QTY Per = 5
QTY Per = 5
QTY Per = 5
QTY Per = 5
-
Jan 5th, 2024, 11:39 AM
#6
Re: VB.NET Print total items of ListBox
So this loops over every item in your ListBox. If you setup a debugger at the top of the PrintPage event handler, what is the result of ListBox2.Items?
-
Jan 5th, 2024, 12:38 PM
#7
Re: VB.NET Print total items of ListBox
Looks like your loop is setup wrong. Need to post your current code.
btw - That data really seems to lend itself to being displayed in a DataGridView. Each file would only use one line, not 3. Save a lot of pages.
I believe in the Code Bank there is an example of how to print a datagridview.
-
Jan 5th, 2024, 01:27 PM
#8
Thread Starter
Addicted Member
Re: VB.NET Print total items of ListBox
dday9 - I must be doing this wrong because I cannot get the listbox items to change when I set a breakpoint and step through it.
wes4dbt - I am open to doing a DataGridView rather than a listbox if it makes printing easier. I have it set this way now simply for user readability.
Here is the complete code I am using now to search and populate the listbox. I am certain it lacks efficiency.
Code:
Imports System.Drawing.Printing
Imports System.IO
Imports System.Text.RegularExpressions
Public Class Form1
Dim fpath = Directory.GetCurrentDirectory
Dim filesPath = fpath
Dim thePart As String
Private _startIndex As Integer = 0
Private Sub BtnSearch_Click(sender As System.Object, e As System.EventArgs) Handles BtnSearch.Click
If txtPartNum.Text = "" Then Exit Sub
Me.ListBox2.Items.Clear()
thePart = $"{txtPartNum.Text}" 'match whole word
ListBox2.Font = New Font("Arial", 10, FontStyle.Regular)
Me.ListBox2.Items.Add("PART NUMBER: " & thePart)
Me.ListBox2.Items.Add("________________________________________")
Me.ListBox2.Items.Add("")
Dim startFolder As String = fpath & "\prg"
Dim fileList As IEnumerable(Of FileInfo) = GetFiles(startFolder)
Dim searchTerm As New Regex(thePart)
Dim queryMatchingFiles = From afile In fileList
Where afile.Extension = ".dp"
Let fileText = File.ReadAllText(afile.FullName)
Let matches = searchTerm.Matches(fileText)
Where (matches.Count > 0)
Select Name = afile.Name,
Matches = From match As Match In matches
Group By match.Value Into g = Group
Select New With {Value, g.Count}
Try
Dim folder As String = fpath & "\parts\"
Dim filename As String = System.IO.Path.Combine(folder, thePart & ".jpg")
PictureBox1.Image = Image.FromFile(filename)
Catch ex As Exception
'Leave image blank
End Try
For Each fileMatches In queryMatchingFiles
Dim s = fileMatches.Name
Dim newFile As String = (Path.Combine(Path.GetDirectoryName(s), Path.GetFileNameWithoutExtension(s)))
ListBox2.Items.Add(newFile)
For Each match In fileMatches.Matches
'ListBox2.Items.Add(match.Value + ": " + match.Count.ToString)
ListBox2.Items.Add("QTY Per = " + match.Count.ToString)
Next
ListBox2.Items.Add("------------------------------")
Next
End Sub
Shared Function GetFiles(root As String) As IEnumerable(Of FileInfo)
Return From file In My.Computer.FileSystem.GetFiles(
root, FileIO.SearchOption.SearchAllSubDirectories, "*.*")
Select New FileInfo(file)
End Function
Private Sub txtPartNum_KeyPress(sender As Object, e As KeyPressEventArgs) Handles txtPartNum.KeyPress
If e.KeyChar = Chr(13) Then
BtnSearch.Focus()
BtnSearch.PerformClick()
End If
End Sub
Private Sub BtnPrint_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnPrint.Click
PrintDocument1.Print()
End Sub
'Private Sub PrintDocument1_PrintPage(ByVal sender As System.Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
' Dim fnt As New Font("Arial", 10, FontStyle.Regular, GraphicsUnit.Point)
' Dim ListBoxItem As String = String.Empty
' For Each LBItem As String In ListBox2.Items
' ListBoxItem = ListBoxItem & vbCrLf & LBItem
' ListBoxItem = ListBoxItem.Substring(vbCrLf.Length)
' Next
' ListBoxItem = ListBoxItem.Substring(vbCrLf.Length)
' e.Graphics.DrawString(ListBoxItem, fnt, Brushes.Black, 0, 0)
' e.HasMorePages = False
'End Sub
Private Sub PrintDocument1_PrintPage(sender As Object, e As PrintPageEventArgs) Handles PrintDocument1.PrintPage
Dim printFont = New Font("Arial", 10, FontStyle.Regular, GraphicsUnit.Point)
Dim lineHeight = printFont.GetHeight(e.Graphics)
Dim printArea = New RectangleF(e.MarginBounds.Left, e.MarginBounds.Top, e.MarginBounds.Width, e.MarginBounds.Height)
Dim itemIndex = _startIndex
Dim listboxItemCount = ListBox2.Items.Count
While (itemIndex < listboxItemCount)
Dim itemText = ListBox2.Items(itemIndex).ToString()
Dim textLayout = New StringFormat()
printArea.Y += lineHeight
Dim linesPerPage = Convert.ToInt32(Math.Floor(printArea.Height / lineHeight))
For i = 0 To linesPerPage - 1
If (itemIndex < listboxItemCount) Then
Dim lineRectangle = New RectangleF(printArea.Left, printArea.Y, printArea.Width, lineHeight)
e.Graphics.DrawString(itemText, printFont, Brushes.Black, lineRectangle, textLayout)
printArea.Y += lineHeight
itemIndex += 1
Else
Exit For
End If
Next
If (itemIndex < listboxItemCount) Then
e.HasMorePages = True
_startIndex = itemIndex
Return
End If
End While
_startIndex = 0
e.HasMorePages = False
End Sub
End Class
Last edited by mikeg71; Jan 5th, 2024 at 01:46 PM.
-
Jan 5th, 2024, 06:17 PM
#9
Re: VB.NET Print total items of ListBox
I’m not sure what data you have in your ListBox. If you do decide to switch to a DataGridView, check the DataGridView Printing link in my signature below this post…
- Coding Examples:
- Features:
- Online Games:
- Compiled Games:
-
Jan 5th, 2024, 10:11 PM
#10
Re: VB.NET Print total items of ListBox
Code:
While (itemIndex < listboxItemCount)
Dim itemText = ListBox2.Items(itemIndex).ToString()
Dim textLayout = New StringFormat()
printArea.Y += lineHeight
Dim linesPerPage = Convert.ToInt32(Math.Floor(printArea.Height / lineHeight))
For i = 0 To linesPerPage - 1
If (itemIndex < listboxItemCount) Then
Dim lineRectangle = New RectangleF(printArea.Left, printArea.Y, printArea.Width, lineHeight)
e.Graphics.DrawString(itemText, printFont, Brushes.Black, lineRectangle, textLayout)
printArea.Y += lineHeight
itemIndex += 1
Else
Exit For
End If
Next
If (itemIndex < listboxItemCount) Then
e.HasMorePages = True
_startIndex = itemIndex
Return
End If
End While
There is definitely a problem with you For loop. This line just keep printing the same thing over and over. "e.Graphics.DrawString(itemText, printFont, Brushes.Black, lineRectangle, textLayout)"
My guess is it should be something like,
Code:
e.Graphics.DrawString(ListBox2.Items(itemIndex).ToString, printFont, Brushes.Black, lineRectangle, textLayout)
That's just a guess, I didn't do any testing.
-
Jan 8th, 2024, 09:51 AM
#11
Thread Starter
Addicted Member
Re: VB.NET Print total items of ListBox
@wes4dbt - Your guess was genius, it works . Thanks so much for your help on this. I honestly did not realize how difficult it was to print the contents of a listbox until this came up. Thanks again!
-
Jan 8th, 2024, 09:55 AM
#12
Thread Starter
Addicted Member
Re: VB.NET Print total items of ListBox
 Originally Posted by .paul.
I’m not sure what data you have in your ListBox. If you do decide to switch to a DataGridView, check the DataGridView Printing link in my signature below this post…
@.paul. - I am planning to try out DataGridView as I have never used it for anything. In your experience, is it better than a listbox when just adding smaller amounts of data?
-
Jan 8th, 2024, 11:02 AM
#13
Re: VB.NET Print total items of ListBox
DGVs are great for displaying and or editing tabular data. They have many properties and are fully (well, within reason) customizable. Listboxes are great if you just want to display data. They don’t work well with tabular data, so no columns…
- Coding Examples:
- Features:
- Online Games:
- Compiled Games:
-
Jan 8th, 2024, 12:19 PM
#14
Thread Starter
Addicted Member
Re: VB.NET Print total items of ListBox
Good info to know. I will for sure look at using the DGV, and even possibly converting this project over to it at some point.
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|