Print to PDF weird behavior

I put this question in the OS X channel because I do not tested it in Windows 8.1 (I even think that I do not installed a virtual printer there, yet).

The code below is a stripped down version (no header, no Footer, other things have been removed) for a code presentation here - as clean as possible - so you can understand what he does / how it prints / where the bug here.

  1. The code is in a MenuItem for speed up / less stuff to remove once the bug will be squashed.

  2. The data is stored in a ListBox located in the window where the MenuItem (MenuHandler) resides.

  3. I used Copy (14 lines of text, the first one is for the Heading, but the code to print the heading was removed) / Paste to place some text to print.

  4. The bug: if the ListBox have 5 lines (5 Rows), the last background color (either yellow or blue) is used to print 5 empty Rows below the last Row with text.

a. The code prints a blue or yellow background alternatively (Odd / Even), then print the text in black.
b. The last printed line with text is followed by n background lines where n is the number of previously printed lines.
I hope this is clear.

To test the code below:

a. create a new project,
b. Add one ListBox and name it LB
c. Add an Open Event and fill it with a loop that add - say 5 lines with 5 columns into the ListBox
d. Add a MenuItem in the File Menu
e. Add a New Handler to Window1
f. Copy / Paste the code below

Run,

Fire the MenuItem,
Press the PDF PopupMenu and choose Open the PDF Document in Preview (something like that).

Then, a PDF document is prepared, sent to Preview who display it.
You will see your lines: alternate background colors with black strings, followed by the same number of printed lines, without text and here is the bug.

BTW: I nearly forgot ! Search the kColor_ prefixed variables in the code below, dim one line for each and set a light color to them (I used light yellow and light cyan).

This will take far less than 5 minutes to do; you may take more time to try to understand why there is colored background (unified colors for many lines) WITHOUT any text printed: there is no text to print there.

I want to be clear, so I will not give details on what I’ve done during the last six hours trying to squash the bug, in vain. I have this bug since summer of 2014.

Thank you.

[code]Function FileTestColorPrint() As Boolean
// ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
//
// Test the Color Printing…
// [2016-01-17] This code is stripped down from the real routine and display the same bug
// I create it before asking for help in the Forum.
// The code do not print header nor footer for clarity
// I removed some other parts of the original code still for clarity
// Clarity: the code still generate the same error, so I was right
// in removing parts before submission to the forum.
//
// ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
//
Dim g As Graphics
Dim p As New PrinterSetup

// Set the Printer Default Properties
p.Landscape = False // True was my default, but I tested with False
// How do I change the Print Size % ?
// p.Size% = 70 // Does not exists, yet…

If p.PageSetupDialog Then
g = OpenPrinterDialog§
If g = Nil Then
// Issue an alert to the user
MsgBox “An error occured” + EndOfLine + EndOfLine + “Unable to print the data.”

  // Stops here
  Return True
End If

Else
// Issue an alert to the user
MsgBox “An error occured” + EndOfLine + EndOfLine + “Unable to print the data.”

// Stops here
Return True

End If

// ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- Printing Process Part
// Dim the needed variables
Dim Row_Height As Integer // height of each Row
Dim Row_Count As Integer // Number of Rows to print
Dim LoopIdx As Integer // Loop Indice variable
Dim Line_Pos As Integer // Y Position of the current Line
Dim Page_Height As Integer // Physical Height of the Page
Dim Page_Width As Integer // Physical Width of the Page
Dim Line_Max As Integer // Max number of lines per page
Dim Line_Number As Integer // Number of the current line
Dim Col_Count As Integer // Number of Columns to print… (in the ListBox)
Dim Col_Idx As Integer // Loop indice to print all Columns of a Row
Dim X As Integer // Position of the first Tab (30)
Dim Y As Integer // Position of the first Line (30)

//[2016-01-17] Added to get a correct print of columns
// Auto compute and set the ListBox Columns widths…
Columns_Auto_Widths()

// Fill some variables
Row_Height = LB.RowHeight // Get the Row height (in pixels)
Row_Count = LB.ListCount - 1 // Store the number of Rows to print [0-based]
Col_Count = LB.ColumnCount - 1 // Get the number of Columns to print [0-based]

// Compute MY Height and Width
Page_Height = p.PageHeight - (10 * 2) // Margins are 10 pixels
Page_Width = p.PageWidth - (10 * 2) // Margins are 10 pixels

// Compute the number of lines per page
Line_Max = (Page_Height - (10 * 2)) / Row_Height

// Use the screen Text Font, Text Size. I have to do that since I use the ListBox column widths…
g.TextFont = LB.TextFont // I think this is useless since the ListBox uses the default values
g.TextSize = LB.TextSize - 5 // same as above comment

// Set the positions (X,Y) of the first Tab / Line
X = 10 // X
Y = 30 // Y

// ---------- ---------- ---------- ---------- Compute the Columns Tab values
//
Dim PosAdd As Double // Computed Tab (used to get a Tab value)
Dim Cur_Col(0) As Double // Arrow: Holds the Tabs
Dim Bkgnd_Color As Color // Used to hold the background color (g.ForeColor)

// Set the Line_Number value (to line 1)
Line_Number = 1

// Set the Line vertical value (Y for line 1)
Line_Pos = Y

// Set some default Tab values
PosAdd = -10
Cur_Col(0) = PosAdd

// Get the ListBox Column Widths and copy them into the Column Width array (Cur_Col)
// Store the new Tab (Add a column width to the previous Tab)
For Col_Idx = 1 To Col_Count
// Compute the ‘Tab’ value and append it in the array
Cur_Col.Append Cur_Col(Col_Idx-1) + CDbl(NthField(LB.ColumnWidths,", ",Col_Idx))
Next

// ---------- ---------- ---------- ---------- Print Operations
//
For LoopIdx = 0 To Row_Count
If Line_Number Mod 2 = 0 Then
Bkgnd_Color = kColor_Cyan
Else
Bkgnd_Color = kColor_Yellow
End If
// I deleted two other colors eventually set using a flag in each Row (this change nothing…

// Set the Forecolor
g.Forecolor = Bkgnd_Color // Used to print a background color rect

// Draw the background color
g.FillRect -25,Line_Pos-12,Page_Width+20,Line_Pos+4

// Set the Forecolor to Black
g.Forecolor = kColor_Black // So the text will be printed in Black…

// ---------- ---------- ---------- ---------- ListBox Row / Columns Print Operations
For Col_Idx = 0 to Col_Count
  // Print the current Row, a Cell at a time, at the current tab (Position)
  g.DrawString LB.Cell(LoopIdx,Col_Idx),Cur_Col(Col_Idx),Line_Pos
Next Col_Idx

// Update the Line_Pos
Line_Pos    = Line_Pos + Row_Height
Line_Number = Line_Number + 1

// To avoid 1, Infinite Loop
If UserCancelled Then Exit

Next LoopIdx

// That’s All Folks !
Return True
End Function[/code]

Without testing it, I suspect that in this line, the value of line_pos gets bigger every time, so every rectangle is taller than the one before, not just lower down.

// Draw the background color g.FillRect -25,Line_Pos-12,Page_Width+20,Line_Pos+4

Should it say

// Draw the background color g.FillRect -25,Line_Pos-12,Page_Width+20,Row_Height+4

I think what you are seeing is
XXX

YYYY
YYYY

ZZZZ
ZZZZ
ZZZZ

and so on.

No.

An example pdf may be interesting to see ?

here

I’d better use only some (less than 10) Rows. But you can see the trouble.
That trouble only appears on the last page, on the previous 91 pages, the printing is OK ;-:):.

The example PDF looks exactly as I would expect it to look if what I said above was happening.

What do you mean by ‘no’?
Have you retested with that change?

Here is your code, stripped down to the bare minimum.
Just create a window, add a button, and put this code in the action event.
It is your code, (but I took out the listbox aspect for the moment.)

The main change here is it ONLY outputs rows 2 and 5

Just look at the sizes of the rows.

[code]
dim g As Graphics
Dim p As New PrinterSetup
p.Landscape = False // True was my default, but I tested with False
If p.PageSetupDialog Then
g = OpenPrinterDialog§
Else
MsgBox “An error occured” + EndOfLine + EndOfLine + “Unable to print the data.”
End If

Dim Row_Height As Integer // height of each Row
Dim Row_Count As Integer // Number of Rows to print
Dim LoopIdx As Integer // Loop Indice variable
Dim Line_Pos As Integer // Y Position of the current Line
Dim Page_Height As Integer // Physical Height of the Page
Dim Page_Width As Integer // Physical Width of the Page
Dim Line_Max As Integer // Max number of lines per page
Dim Line_Number As Integer // Number of the current line
Dim Col_Count As Integer // Number of Columns to print… (in the ListBox)
Dim Col_Idx As Integer // Loop indice to print all Columns of a Row
Dim X As Integer // Position of the first Tab (30)
Dim Y As Integer // Position of the first Line (30)

// Fill some variables with constants because I cant be bothered with a listbox
Row_Height = 30
Row_Count = 10
Col_Count = 6

Page_Height = p.PageHeight - (10 * 2) // Margins are 10 pixels
Page_Width = p.PageWidth - (10 * 2) // Margins are 10 pixels

Line_Max = (Page_Height - (10 * 2)) / Row_Height

X = 10 // X
Y = 30 // Y

Dim PosAdd As Double // Computed Tab (used to get a Tab value)
Dim Cur_Col(0) As Double // Arrow: Holds the Tabs
Dim Bkgnd_Color As Color // Used to hold the background color (g.ForeColor)
Line_Number = 1
Line_Pos = Y
PosAdd = -10
Cur_Col(0) = PosAdd
For LoopIdx = 0 To 10
If Line_Number Mod 2 = 0 Then
Bkgnd_Color = &cFFFF00
Else
Bkgnd_Color = &C00ffff
End If
g.Forecolor = Bkgnd_Color // Used to print a background color rect

//THIS is where I made a real change… just output two rows

if line_number = 2 or line_number = 5 then
  // Draw the background color
  g.FillRect -25,Line_Pos-12,Page_Width+20,Line_Pos+4
end if


Line_Pos    = Line_Pos + Row_Height
Line_Number = Line_Number + 1

// To avoid 1, Infinite Loop
If UserCancelled Then Exit

Next LoopIdx[/code]

g.FillRect -25,Line_Pos-12,Page_Width+20,Line_Pos+4

and

Line_Pos = Line_Pos + Row_Height

results in drawing a rect that is Row_Height*Row_Count tall…
DrawRect takes (x,y,width,height), You’re treating it as (x,y,width,Bottom)
You don’t see this in the lines before the end because the next row draws on top of it. The final row is left exposed.

Change the line to

g.FillRect -25,Line_Pos-12,Page_Width+20,Row_Height+4

and you should get your expected result.

Thats what I told him first.

[quote]
Should it say
// Draw the background color
g.FillRect -25,Line_Pos-12,Page_Width+20,Row_Height+4[/quote]

Ah, I see now. That’s what happens when I read forums on my phone :stuck_out_tongue:

[quote=241791:@Jeff Tullin]The example PDF looks exactly as I would expect it to look if what I said above was happening.

What do you mean by ‘no’?
Have you retested with that change?[/quote]
Hi Jeff,

Thank you for your answers.

the no meant: no height variation with printed lines. If I have a pdf with 96 pages that ends with the page 96 with 10 lines, they will all heve the same background color height (I will test what you tell, I have a suspicion… *), and page 96 will have 10 alternate background lines ending with 10 lines with the same color (in fact, the 11 last lines will have the same color, one of those will have the last line of text).

The last background color can be the one for Odd or Even: the default can be the same.

  • Maybe you wanted to tell me that I see what I want, but in fact it is just because the next background color TOP is printed at the correct Y value, and the program do that until the page bottom, excepted when the page is not full, then I see my error in computing the height of the background color ?
    If so, well spotted (at this time, I do not yet read the other answers. The original code only used one color background (a light grey) so the reader (human) can follow the line and (after a good night), that comes to mind while writing this text. I had this problem at this time. Since I based this code on that code I never suspect thsi can arise (but I believe it can: Murphy’s Law). I will check (removing one color for example).

Hi Jeff,

you were right. (as usual I think), I get an eye on Graphics.FillRect and saw that parameters 3 and 4 (in my case) have to be the same from line 1 to last line (when printing a page).

So, in the g.FillRect page (where you tell me the bug is) , the last parameter (the Rect’s Hight) to 16, print a test page and see some white lines (2 pixels probably) between my yellow and blue background colors and no parasite colored background lines without text after the last text printed line.

Bug squash done.

When back home, I will get a better eye on your modified code.

What a strange idea I had to compute the FillRect Height value for each line.

That really was a BUG (my own bug !)

Thank you everybody !