Hey there everyone.

This forum has always provided me amazing guidance and help, and I have all the faith that you guys will be able to figure this problem out again. I'm just beyond stumped.

I was able to modify the RTB print function that's available all over the forum to print the text from a RTB. Unfortunately, I had to make the printout look slightly more professional, which required modifying the stable routine.

Problem is, when a printout with a large number of pages prints, it does REALLY funky stuff. It doesn't do said funky stuff with a short printout (about 4 pages or so), but it does with a higher numbered one. I can't figure out where my inconsistancy lies. Can anyone help?

See attachments for the before-I-messed-with-it-code and after, and the modified code below:
Before: before.pdf
After: after.pdf

Notice that the "key" that the program looks for is the term "Container ". I plan to change the report slightly so that it doesn't break at awkward intervals, but here's an example of the screwy version:

fixtest 6 (09-0189) BIGGER.pdf


Ignore the first blank page - that's not part of the issue. It's just a result of messing with code as the sub was running. The problem becomes noticable on page 3, and becomes deathly obvious on page 5.


Any ideas at all would be helpful. I've been trying to nail this issue for a week


vb Code:
  1. ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  2.    '
  3.    ' PrintRTF - Prints the contents of a RichTextBox control on the default printer using the
  4.    '            provided margins
  5.    '
  6.    ' RTF - A RichTextBox control to print
  7.    '
  8.    ' LeftMarginWidth - Width of desired left margin in twips
  9.    '
  10.    ' TopMarginHeight - Height of desired top margin in twips
  11.    '
  12.    ' RightMarginWidth - Width of desired right margin in twips
  13.    '
  14.    ' BottomMarginHeight - Height of desired bottom margin in twips
  15.    '
  16.    ' Notes - If you are also using WYSIWYG_RTF() on the provided RTF
  17.    '         parameter you should specify the same LeftMarginWidth and
  18.    '         RightMarginWidth that you used to call WYSIWYG_RTF()
  19.    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  20.    Public Sub PrintRTF(RTF As RichTextBox, LeftMarginWidth As Long, _
  21.       TopMarginHeight, RightMarginWidth, BottomMarginHeight)
  22.       Dim LeftOffset As Long, TopOffset As Long
  23.       Dim LeftMargin As Long, TopMargin As Long
  24.       Dim RightMargin As Long, BottomMargin As Long
  25.       Dim fr As FormatRange
  26.       Dim rcDrawTo As RECT
  27.       Dim rcPage As RECT
  28.       Dim TextLength As Long
  29.       Dim NextCharPosition As Long
  30.      
  31.       Dim vl_LastContainerPos_lng As Long
  32.       Dim vl_ContainerPos_lng As Long
  33.       Dim vl_PotentialPgBreakPos_lng As Long
  34.       Dim vl_CurrentPage_int As Integer
  35.       Dim r As Long
  36.  
  37.       ' Start a print job to get a valid Printer.hDC
  38.    On Error GoTo PrintRTF_Error
  39.    Stack.Push "PrintRTF"
  40.  
  41.       Printer.Print Space(1)
  42.       Printer.ScaleMode = vbTwips
  43.  
  44.       ' Get the offsett to the printable area on the page in twips
  45.       LeftOffset = Printer.ScaleX(GetDeviceCaps(Printer.hdc, _
  46.          PHYSICALOFFSETX), vbPixels, vbTwips)
  47.       TopOffset = Printer.ScaleY(GetDeviceCaps(Printer.hdc, _
  48.          PHYSICALOFFSETY), vbPixels, vbTwips)
  49.  
  50.       ' Calculate the Left, Top, Right, and Bottom margins
  51.       LeftMargin = LeftMarginWidth - LeftOffset
  52.       TopMargin = TopMarginHeight - TopOffset
  53.       RightMargin = (Printer.Width - RightMarginWidth) - LeftOffset
  54.       BottomMargin = (Printer.Height - BottomMarginHeight) - TopOffset
  55.  
  56.       ' Set printable area rect
  57.       rcPage.Left = 0
  58.       rcPage.Top = 0
  59.       rcPage.Right = Printer.ScaleWidth
  60.       rcPage.Bottom = Printer.ScaleHeight
  61.  
  62.       ' Set rect in which to print (relative to printable area)
  63.       rcDrawTo.Left = LeftMargin
  64.       rcDrawTo.Top = TopMargin
  65.       rcDrawTo.Right = RightMargin
  66.       rcDrawTo.Bottom = BottomMargin
  67.  
  68.       ' Set up the print instructions
  69.       fr.hdc = Printer.hdc   ' Use the same DC for measuring and rendering
  70.       fr.hdcTarget = Printer.hdc  ' Point at printer hDC
  71.       fr.rc = rcDrawTo            ' Indicate the area on page to draw to
  72.       fr.rcPage = rcPage          ' Indicate entire size of page
  73.       fr.chrg.cpMin = 0           ' Indicate start of text through
  74.       fr.chrg.cpMax = -1          ' end of the text
  75.    
  76.       ' Get length of text in RTF
  77.       TextLength = Len(RTF.Text)
  78.  
  79.     vl_CurrentPage_int = 0
  80.    
  81.         'This next bit of code is a bit confusing.
  82.         'It was used as an attempt to prevent "orphan" paragraphs. The page had to be divided
  83.         'into sections denoted by the ". Then, each page had to be rendered,
  84.         'the next break found, and the page break moved if necessary. Each page break was two parts:
  85.         'the cpMin parameter of the next page, and the cpMax parameter of the current page.
  86.         'Therefore, we had to go through the following steps:
  87.         '       -Rendering the page
  88.         '       -Determine if any CP_PAGEBREAKCHAR_STRs were present between this page and the next (half on this page)
  89.         '       -Adjsut the break if necessary
  90.                
  91.       ' Loop printing each page until done
  92.         Do
  93.        
  94.           'Increment the page counter to keep track of the current page
  95.           vl_CurrentPage_int = vl_CurrentPage_int + 1
  96.          
  97.          
  98.           'Render the page and record the "proposed" end
  99.            vl_PotentialPgBreakPos_lng = SendMessage( _
  100.                     RTF.hWnd, _
  101.                     EM_FORMATRANGE, _
  102.                     False, _
  103.                     fr)
  104.           'If the proposed printout is only one page long, no further processing needs to occur.
  105.           'We can determine if the printout is only one page long by testing if the potential page break position
  106.             'ís greater than the text length.
  107.            
  108.             If vl_PotentialPgBreakPos_lng < TextLength Then
  109.                 'In this case, there is definately more than one page, so the printout shouldn't have an issue.
  110.                 'We have to check if there is more than one page to avoid page breaks that are the only container on a page.
  111.                
  112.                 'See if there are any key characters in between the last position and the proposed page break
  113.                 'The easiest way to do this is to look for the key characters until the page is either reached or exceeded.
  114.                 'If one of those conditions are met, then set the new page break position.
  115.                 vl_LastContainerPos_lng = fr.chrg.cpMin + 1
  116.                 Do
  117.                       vl_ContainerPos_lng = InStr(vl_LastContainerPos_lng + 2, RTF.Text, CP_PAGEBREAKCHAR_STR, vbBinaryCompare)
  118.                      
  119.                       'There will only be a few situations following this instr operation:
  120.                      
  121.                       'The key characters will be found farther than the limit (result of instr >proposed limit)
  122.                       If vl_ContainerPos_lng >= vl_PotentialPgBreakPos_lng Then
  123.                             'ín which case', we just have to set the maximum to the previously found key character and exit the loop
  124.                             fr.chrg.cpMax = vl_LastContainerPos_lng - 1
  125.                             Exit Do
  126.                       ElseIf (vl_ContainerPos_lng = 0) And (vl_CurrentPage_int = 1) Then
  127.                           fr.chrg.cpMax = vl_LastContainerPos_lng - 1
  128.                           Exit Do
  129.                       'There will be no more instances of the key chracters after the page break, (result of instr = -1)
  130.                       ElseIf vl_ContainerPos_lng = 0 Then
  131.                             'in which case, the current stopping position is fine, and the loop can be exited.
  132.                             Exit Do
  133.                       'Or, there will be more searching to do
  134.                       Else
  135.                           vl_LastContainerPos_lng = vl_ContainerPos_lng
  136.                       End If
  137.                 Loop
  138.            
  139.             End If
  140.  
  141.          ' Print the page by sending EM_FORMATRANGE message
  142.          NextCharPosition = SendMessage(RTF.hWnd, _
  143.              EM_FORMATRANGE, True, fr)
  144.        
  145.          If NextCharPosition >= TextLength Then Exit Do  'If done then exit
  146.          
  147.          Printer.NewPage                  ' Move on to next page
  148.          Printer.Print Space(1) ' Re-initialize hDC
  149.          fr.hdc = Printer.hdc
  150.          fr.hdcTarget = Printer.hdc
  151.          fr.chrg.cpMin = NextCharPosition
  152.          fr.chrg.cpMax = -1
  153.       Loop
  154.  
  155.       ' Commit the print job
  156.       Printer.EndDoc
  157.  
  158.       ' Allow the RTF to free up memory
  159.       r = SendMessage(RTF.hWnd, EM_FORMATRANGE, False, ByVal _
  160. CLng(0))
  161.  
  162.    On Error GoTo 0
  163.    Stack.Pop
  164.    Exit Sub
  165.  
  166. PrintRTF_Error:
  167.  
  168. ErrHandler "Print", "Module", "PrintRTF", Erl
  169.    End Sub