HLP: e.HasMorePages = True (NOT)

  • Thread starter Thread starter Mr. B
  • Start date Start date
M

Mr. B

VB.net (standard)

I'm experiencing some difficulties in printing multiple pages using Print
Preview.

The following is my main parts of my printing subs (excess info deleted for
your viewing pleasure). For a single page, the print preview (and an actual
print) are OK. Getting the .HasMorePages doesn't seem to be working for me
here (unless I'm missing something).

I have a Title Block (separate sub)... print my info 'group' (max 10 per
page)... What the following does (and it's at the bottom where I'm screwing
up) is that 10 or Less items is OK. More than 10 items gives me ONE page with
all the data printed over each other (ie: a Page Break does not occur).

I'd appreciate some help here (have spent many hours trying to figure this one
out):

' ***********************************************************
Private Sub mnuPrinter_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles mnuPrinter.Click

... I set up my PageSettings, Fonts, Column Widths, DefaultPageSettings, etc.
here...

PrintPreviewDialog1.Document = PrintDocument1
PrintPreviewDialog1.ShowDialog()

End Sub

' ***********************************************************
Private Sub PrintDocHeader(ByVal e As
System.Drawing.Printing.PrintPageEventArgs)
.... I set up my Document Header stuff here...
End Sub

' ***********************************************************
Private Sub PrintDocument1_PrintPage(ByVal sender As Object, ByVal e As
System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage

Dim rwCntr As Integer = 0 ' Print Rows Counter (max 16 used)
Dim str As String

' Start Printing Output
For cntrI = 0 To lbWeekItems.Items.Count - 1
rwCntr = rwCntr + 1

' Page Header
If rwCntr = 1 Then PrintDocHeader(e)

.... Now I print my rows (group) of info...
Dim HrTtl As Double
Dim R1 As New RectangleF(X1, Y, W1, 80) ' Col 1 Job
Dim R2 As New RectangleF(X1 + 80, Y, W2, 80) ' Col 2 Job Desc
str = ProjArray(0, cntrI + 1)
e.Graphics.DrawString(str, tableFont, Brushes.Black, R1)
str = ProjArray(1, cntrI + 1)
e.Graphics.DrawString(str, tableFont, Brushes.Black, R2)
..... etc, etc...

.... I Finish off my items with a row (between each group of items)...
Y = Y + 15
' Draw Break Line
With PrintDocument1.DefaultPageSettings
Y = Y + 20
e.Graphics.DrawLine(Pens.Black, X1, Y, .PaperSize.Height - 50, Y)
End With

' HERE IS WHERE I THINK THE PROBLEM IS???
' ========================================
If rwCntr = 10 Then
e.HasMorePages = True
rwCntr = 0
End If

Next ' cntrI

' No More Pages to Print
e.HasMorePages = False

End Sub


Thanks!

Bruce
 
Hi,

The way you wrote your code it always hits e.hasmorepages=
false. Try something like this.

If rwCntr = 10 Then
e.HasMorePages = True
rwCntr = 0
Else
' No More Pages to Print
e.HasMorePages = False
End If

Next ' cntrI


Ken
------------
 
Ken Tucker said:
The way you wrote your code it always hits e.hasmorepages=
false. Try something like this.

If rwCntr = 10 Then
e.HasMorePages = True
rwCntr = 0
Else
' No More Pages to Print
e.HasMorePages = False
End If

Next ' cntrI

Thanks Ken... but believe it or not... Still doesn't work (this is probably
one of the many variations I've tried. Something is VERY strange here.

This is the only place I enter 'e.HasMorePages'. But my PrintPreview still
shows the two pages overlapping each other.

I got most of my code format from a sample app... that worked fine (only they
were using a WHILE statement and I'm using a FOR).

I don't know... I'm pretty tired of this :(

Thanks anyways (this is all rather depressing)

Bruce
 
Mr. B said:
I'd appreciate some help here (have spent many hours trying to figure this one
out):

I think I can solve the problem but if you'll bear with me for a moment I'd
like to offer an "angle" on solving problems. It might have worked in the
particular case but you might be surprised how "simplifying" can lead to the
solution. Reduce the problem down to the fewest number of lines of code...
save the old code of course but eliminate the rectangles, one of the two
drawstring methods, the linebreak and such.

Not specifically because it causes the problem (but it might) but rather
just to get the unrelated things off the table.

Ok... so I think you've misinterpreted how the PrintPage() method works. It
does basically two things... draws the current page and tells the
PrintPreviewDialog if it needs to be called again (for another page.) If
you set .HasMorePages to True it will be called again when the current page
is finished, if you set it to False it will not be called again... even if
there is more data.

You are printing all the data on one page because there is only one call to
PrintPage. It is the repeated calls that will cause the page breaks. The
printing is on top of the previous page simply because you reset the Y
position.

You have to move the following outside of PrintPage...
For cntrI = 0 To lbWeekItems.Items.Count - 1

so it doesn't start the data over each time that PrintPage is called.

Tom
 
Tom Leylan said:
solution. Reduce the problem down to the fewest number of lines of code...
save the old code of course but eliminate the rectangles, one of the two
drawstring methods, the linebreak and such.

Okay... I'll try that. But like I said, it does print out okay (even though
on top of each other). And I took the code from an example CD that works
fine!
Ok... so I think you've misinterpreted how the PrintPage() method works. It
does basically two things... draws the current page and tells the

No kidding (: My first try at VB.net printing !!! (gimme VB6 said:
PrintPreviewDialog if it needs to be called again (for another page.) If
you set .HasMorePages to True it will be called again when the current page
is finished, if you set it to False it will not be called again... even if

Hmmm... if you compare my original post stuff vs. this (from the example), I
can't see where it differs in the 2nd page call vs. mine!!!

(part of the Private Sub PrintDocument1_PrintPage sub...)

While itm < ListView1.Items.Count
Dim str As String
str = ListView1.Items(itm).Text
e.Graphics.DrawString(str, tableFont, Brushes.Black, X1, Y)
str = ListView1.Items(itm).SubItems(1).Text
Dim R As New RectangleF(X2, Y, W2, 80)
e.Graphics.DrawString(str, tableFont, Brushes.Black, R)
Dim lines, cols As Integer
e.Graphics.MeasureString(str, tableFont, New SizeF(W2, 50), New
StringFormat(), cols, lines)
Dim subitm As Integer, Yc As Integer
Yc = Y
For subitm = 2 To ListView1.Items(itm).SubItems.Count - 1
str = ListView1.Items(itm).SubItems(subitm).Text
e.Graphics.DrawString(str, tableFont, Brushes.Black, X3, Yc)
Yc = Yc + tableFont.Height + 2
Next
Y = Y + lines * tableFont.Height + 5
Y = Math.Max(Y, Yc)
With PrintDocument1.DefaultPageSettings
e.Graphics.DrawLine(Pens.Black, .Margins.Left, Y, .PaperSize.Width -
..Margins.Right, Y)
If Y > 0.95 * (.PaperSize.Height - .Margins.Bottom) Then
e.HasMorePages = True
Exit Sub
End If
End With
itm = itm + 1
End While
e.HasMorePages = False

You have to move the following outside of PrintPage...
so it doesn't start the data over each time that PrintPage is called.

Thanks Tom... I'll examine my example again in detail and see just where I'm
going wrong in the logic (as usual, it usually IS just something damn stupid
that you can't see).

Thanks again! I'll keep on trying...

Bruce
 
Okay... I'll try that. But like I said, it does print out okay (even though
on top of each other). And I took the code from an example CD that works
fine!

It's a just a rule to keep in mind. With less code you have fewer potential
causes and fewer things to consider when looking for a solution. I can
guarantee it isn't drawing the linebreak but why make your eyes skip over
that code (and the rest) for "hours."
Hmmm... if you compare my original post stuff vs. this (from the example), I
can't see where it differs in the 2nd page call vs. mine!!!

If the following is the code a careful reading will reveal the differences.

this one loops while there is still data
While itm < ListView1.Items.Count

Yours resets the counter every time it prints a page
For cntrI = 0 To lbWeekItems.Items.Count - 1

this one exits if the end of the page is reached
If Y > 0.95 * (.PaperSize.Height - .Margins.Bottom) Then
e.HasMorePages = True
Exit Sub

Yours doesn't
Next ' cntrI

This one tells it to stop printing pages when it runs out of data
End While
e.HasMorePages = False

Yours tells it to stop printing pages when it runs out of data
except you printed all your data in your for... next loop
' No More Pages to Print
e.HasMorePages = False
Thanks Tom... I'll examine my example again in detail and see just where I'm
going wrong in the logic (as usual, it usually IS just something damn stupid
that you can't see).

It sounds like just a little misunderstanding it how it works. PrintPage
doesn't render a report, just a page. You can see why if you print a very
long report. You will be able to interrupt the report while the pages are
printing... yet you won't have any code that says it should be
interruptible. It gets that chance as each page is rendered and it goes
back around for another page.

So basically you have to write the code such that PrintPage can generate a
page of printing (moving a record pointer or incrementing an index or
whatever to change the data) as well as determine if it has run out of data
(that's when it returns False) but it can't initialize all the control
variables or they will get reset each time it goes to print a page.

My suggestion would be you pull all the non-essentials out... just print
"Page " & pagenum.tostring & " line " & linenum.tostring on (for instance 3
pages with 10 lines on each page.) Once you have the simple example
operating you can go back to finishing your more elaborate one.

Tom
 
It's a just a rule to keep in mind. With less code you have fewer potential
causes and fewer things to consider when looking for a solution. I can

GOT IT! (sheeeesshhhh)

Apart from a couple of things that needed fixing, I finally 'saw' the problem.

As you suggested, the Next Page wasn't been sent. And where the problem was,
was I wasn't exiting the sub (like my sample did). What I had to do was set
up my print sub using the WHILE statement. Then I added the EXIT SUB at the
correct spot... Voila'.

' That's it for this page...
If rwCntr = 18 Then
e.HasMorePages = True
cntrI = cntrI + 1
rwCntr = 0
Exit Sub < -------- HERE !!!!
End If

cntrI = cntrI + 1
End While

' No More Pages to Print
e.HasMorePages = False


What I didn't realize was that (and correct me if I'm wrong) it appears that
the PrintDocument1_PrintPage sub has to be EXITed for each Page. That is what
it looks like to me. That being so, no wonder why I didn't see it as I'm
still in VB6 mode (:

Anyways.... finally I'm moving on to the next problem.

Thanks again for the 'tips'.

James
 
JamesBV said:
' That's it for this page...
If rwCntr = 18 Then
e.HasMorePages = True
cntrI = cntrI + 1
rwCntr = 0
Exit Sub < -------- HERE !!!!
End If

I don't have the exact code but generally speaking (if the phrase isn't
bothering you too much) e.HasMorePages isn't true simply because rwCntr =
18. You might have other logic that prevents it (I'm just guessing there
isn't) but your counter can hit 18 exactly at the point there isn't any more
data.
What I didn't realize was that (and correct me if I'm wrong) it appears that
the PrintDocument1_PrintPage sub has to be EXITed for each Page.

Well that's what I was trying to say. I'd phrase it differently though. It
has to be _called_ for each page. It's a "print page event" so you don't
print a report in it unless your report happens to be only one page.
Anyways.... finally I'm moving on to the next problem.
Thanks again for the 'tips'.

Sounds good...
 
Sounds good...

Yeah... too good to be true. NOW... somehow I'm printing blank sheets!!!! No
kidding. Just tried it on the printer (and to a PDF file)... nothing!

I think I'll go buy a MAC now thank you! :(

I think I'm going to leave this until tomorrow. I (for the life of me) can't
see what I've done now. I've tried my old (broken) code... I get the
overlapping... but it does print!

My new code does show the Print preview's with multiple pages... but nothing
comes out to the printer (unless my black toner is white?) (:

This is just too much for me...

Jame
 
Back
Top