I would print a listbox

Good evening group
I would like to print the contents of a listbox, this is the code, where am I wrong?

Dim p As New PrinterSetup
Dim g As Graphics
Dim settings As String
Dim Printed_Lines As Integer // Indice LINEE di stampa
Dim Lines_By_Page As Integer // Numbero di linee per pagina
Dim PA_Width As Integer // Area di stampa il larghezza
Dim PA_Height As Integer // Area di stampa in altezza
Dim Row_Cnt As Integer // Numero di righe da stampare
Dim Row_Height As Integer // Row Heught (usato come Y per stampare le righe
Dim LoopIdx As Integer // indice di Loop
Dim Line_Y As Integer //  Valore Y



If p.PageSetupDialog Then
  g = OpenPrinterDialog
End If

PA_Width = p.Width
PA_Height = p.Height
Lines_By_Page = PA_Height / ListBoxPromemoria.RowHeight // Height of the Listbox
Row_Cnt = ListBoxPromemoria.RowCount '-1'
Row_Height = ListBoxPromemoria.RowHeight
Line_Y = Row_Height

For LoopIdx = 0 To Row_Cnt-1
  messagebox LoopIdx.ToString + " di " + Row_Cnt.ToString-1
  g.DrawText(ListBoxPromemoria.CellTextAt(LoopIdx,0), LoopIdx , PA_Width)
  //End of page ?
  If Printed_Lines >= Lines_By_Page Then
    MESSAGEBOX "NEXT page"
    Line_Y = Row_Height
    Printed_Lines = 1
    g.NextPage
  Else
    Line_Y = Line_Y + Row_Height
    Printed_Lines = Printed_Lines + 1
  End If
  
  If UserCancelled Then Exit
  
Next


What makes you say you’re wrong ?
Without me testing this code to see what you think the problem is it’s hard to say

First off, you should be gettng a compile error on this line:

I think you want:

messagebox LoopIdx.ToString + " di " + Integer(Row_Cnt - 1).ToString

Or, leave out all the “-1” adjustments by using ListBoxPromemoria.LastRowIndex instead of RowCount.

The next problem I see is that you’re not placing the output at the correct location on the page. DrawText places the text at the given X & Y coordinates. You’re using the loop counter and graphics width as the X & Y coordinates.

I think you want something like

g.DrawText(ListBoxPromemoria.CellTextAt(LoopIdx,0), 0 , Line_Y)

Also, you probably want to check if g is Nil, as it will be if the user chooses Cancel in the print dialog. Plus, you need to exit from the method if either dialog is cancelled. Currently it still runs, which will lead to a NilObjectExecption. Finally, you display the PageSetupDialog, but then don’t use the (now configured) PrinterSetup in the Print dialog. So I think you want something like this:

If Not p.PageSetupDialog Then Return
g = OpenPrinterDialog(p)
If g = Nil Then Return

I tried to modify the code following the suggestions … I also wrote the messagebox, which shows me line by line, all the fields of the LISTBOX. But when it prints the file, only the first line comes out. The other 9 no … where am I wrong?

Dim p As New PrinterSetup
Dim g As Graphics
Dim settings As String
Dim Printed_Lines As Integer // Indice LINEE di stampa
Dim Lines_By_Page As Integer // Numbero di linee per pagina
Dim PA_Width As Integer // Area di stampa il larghezza
Dim PA_Height As Integer // Area di stampa in altezza
Dim Row_Cnt As Integer // Numero di righe da stampare
Dim Row_Height As Integer // Row Heught (usato come Y per stampare le righe
Dim LoopIdx As Integer // indice di Loop
Dim Line_Y As Integer //  Valore Y



If Not p.PageSetupDialog Then Return
g = OpenPrinterDialog(p)
If g = Nil Then Return

PA_Width = p.Width
PA_Height = p.Height
Lines_By_Page = PA_Height / ListBoxPromemoria.RowHeight // Height of the Listbox
Row_Cnt = ListBoxPromemoria.LastRowIndex
Row_Height = ListBoxPromemoria.RowHeight
Line_Y = Row_Height

For LoopIdx = 0 To Row_Cnt
  messagebox ListBoxPromemoria.CellTextAt(LoopIdx,0)  //TEST
  g.DrawText(ListBoxPromemoria.CellTextAt(LoopIdx,0), 0 , Line_Y)
  
  //End of page ?
  If Printed_Lines >= Lines_By_Page Then
    MESSAGEBOX "NEXT page"
    Line_Y = Row_Height
    Printed_Lines = 1
    g.NextPage
  Else
    Line_Y = Line_Y + Row_Height
    Printed_Lines = Printed_Lines + 1
  End If
  
  If UserCancelled Then Exit
  
Next

It works for me. Don’t understand why it doesn’t for you, especially since you say the messagebox shows you each cell’s value.

Can you try a different printer, or print to PDF?

I have a listbox, with 9 rows. But when I launch the print, it only prints the first line, even if, with Messagebox, I see that it goes through all the lines. I print on a virtual PDF printer.It reads the 9 lines from the listbox, but prints only 1. I don’t understand if because it overwrites all of them on the same line.

LIke I said, it works for me.

Which OS & Version, and which Xojo version are you using?

Windows 7 64bit, Foxit to PDF, Xojo 2022 R1.1

Instead of MessageBox, use:
System.DebugLog

No guys, I can’t print the ListBox well.

hi boys
I solved
or added only one line … and with that I format the print and see the whole listbox well.

You should post your solution. It may be helpful for others that encounter a similar situation.

Certainly with great pleasure.
Although the code can certainly be improved.



Dim p As New PrinterSetup
Dim g As Graphics
Dim settings As String
Dim Printed_Lines As Integer // Indice LINEE di stampa
Dim Lines_By_Page As Integer // Numbero di linee per pagina
Dim PA_Width As Integer // Area di stampa il larghezza
Dim PA_Height As Integer // Area di stampa in altezza
Dim Row_Cnt As Integer // Numero di righe da stampare
Dim Row_Height As Integer // Row Heught (usato come Y per stampare le righe
Dim LoopIdx As Integer // indice di Loop
Dim Line_Y As Integer //  Valore Y
Dim ComponiRigo as string
Dim Colonna3 as string


If Not p.PageSetupDialog Then Return
g = OpenPrinterDialog(p)
If g = Nil Then Return

PA_Width = p.Width
PA_Height = p.Height
Lines_By_Page = PA_Height / ListBoxPromemoria.RowHeight // Height of the Listbox
Row_Cnt = ListBoxPromemoria.LastRowIndex
Row_Height = ListBoxPromemoria.RowHeight
Line_Y = Row_Height
'' Intestazione colonne foglio 
g.DrawText("____________________________  STAMPA PROMEMORIA ____________________________", 0 , 0)
g.DrawText("                                                                             ", 0 , 20)
g.DrawText("ID  **   Oggetto   ** Data **   Messaggio", 0 , 40)
For LoopIdx = 0 To Row_Cnt
  ComponiRigo=""
  colonna3=""
  colonna3=ListBoxPromemoria.CellTextAt(LoopIdx,3)
  Colonna3=replaceall(colonna3,chr(13),".")
  ComponiRigo=ListBoxPromemoria.CellTextAt(LoopIdx,0)+ " ** "+ListBoxPromemoria.CellTextAt(LoopIdx,1) + " ** " + ListBoxPromemoria.CellTextAt(LoopIdx,2)+ " ** "+colonna3 
  g.DrawText(ComponiRigo, 0 , Line_Y)
  G.DrawLine(0,lINE_y+5,200,LINE_Y+5)
  //End of page ?
  If Printed_Lines >= Lines_By_Page Then
    Line_Y = Row_Height
    Printed_Lines = 1
    g.NextPage
  Else
    Line_Y = Line_Y + Row_Height
    Printed_Lines = Printed_Lines + 1
  End If
  
  If UserCancelled Then Exit
  
Next

I don’t see anything that would cause this to work for you when the previous attempt did not. And the first few rows of the listbox should be printing over top of your header.

What is this line for? It prints nothing.

g.DrawText("                                                                             ", 0 , 20)

My guess is you are thinking of the graphics area like a text editor, where you have to “enter” a blank line if you want to create vertical space before the next line. That’s not how this works. You can “print” anywhere on the page, and in any order. It’s all a coordinate system. The page is then sent to the printer when the method is finished.

Also, you should use the HorizontalResolution and VerticalResolution from the PrinterSetup to properly scale the output. Else you will get different sizes on different printers.

Also, you could probably accomplish what you’re wanting a lot easier with a Report.

You also use:

ListBoxPromemoria.RowHeight

in code, then one line later, you use the defined variable Row_Height.

You have Returns [Chr(13)] in Cell(s) ?

Also, by default, you use the OS Font and size.

At least, the next time show a screen shot (in this case a screen shot of the populated ListBox): you may use Styles in the ListBox, Images, etc.

I haven’t messed with Printing from Xojo for several years since everything I’m doing is Web applications now, but when I did do printing from desktop apps I found that using graphics to draw into a canvas and displaying the Canvas “page” in a window helped a lot in the debugging process for text/graphics placement. If it looked good in the canvas it would look the same on a printed page.

Print to pdf is a better idea: you print at the paper size and can save the result immediately. IMHO.

1 Like
Dim p As New PrinterSetup
Dim g As Graphics
Dim settings As String
Dim Printed_Lines As Integer // Indice LINEE di stampa
Dim Lines_By_Page As Integer // Numbero di linee per pagina
Dim PA_Width As Integer // Area di stampa il larghezza
Dim PA_Height As Integer // Area di stampa in altezza
Dim Row_Cnt As Integer // Numero di righe da stampare
Dim Row_Height As Integer // Row Heught (usato come Y per stampare le righe
Dim LoopIdx As Integer // indice di Loop
Dim Line_Y As Integer //  Valore Y
Dim ComponiRigo as string
Dim Colonna3 as string


If Not p.PageSetupDialog Then Return
g = OpenPrinterDialog(p)
If g = Nil Then Return

PA_Width = p.Width
PA_Height = p.Height
Lines_By_Page = PA_Height / ListBoxPromemoria.RowHeight // Height of the Listbox
Row_Cnt = ListBoxPromemoria.LastRowIndex
Row_Height = ListBoxPromemoria.RowHeight
Line_Y = Row_Height
'' Intestazione colonne foglio 
g.DrawText("____________________________  STAMPA PROMEMORIA ____________________________", 0 , 0)
g.DrawText("                                                                             ", 0 , 20)
g.DrawText("ID  **   Oggetto   ** Data **   Messaggio", 0 , 60)
For LoopIdx = 0 To Row_Cnt
  ComponiRigo=""
  colonna3=""
  colonna3=ListBoxPromemoria.CellTextAt(LoopIdx,3)
  Colonna3=replaceall(colonna3,chr(13),".")
  ComponiRigo=ListBoxPromemoria.CellTextAt(LoopIdx,0)+ " ** "+ListBoxPromemoria.CellTextAt(LoopIdx,1) + " ** " + ListBoxPromemoria.CellTextAt(LoopIdx,2)+ " ** "+colonna3 
  g.DrawText(ComponiRigo, 0 , Line_Y+80)
  G.DrawLine(0,lINE_y+80+5,300,LINE_Y+80+5)
  //End of page ?
  If Printed_Lines >= Lines_By_Page Then
    Line_Y = Row_Height
    Printed_Lines = 1
    g.NextPage
  Else
    Line_Y = Line_Y + Row_Height
    Printed_Lines = Printed_Lines + 1
  End If
  
  If UserCancelled Then Exit
  
Next

Sorry guys, I’ve had a lot to do these days. I have read your comments. Please understand that I am not a professional programmer, so my code is certainly not optimal. But at the moment it works for me. I’ll post the updated code again, with screenshots of the results.


(p.S) Yes, I have chr (13) characters in return, which I replace with.