Creating Advanced PDF documents in VB

Level:
Level3

This VB tutorial builds off the last and demonstrates how you can create more advanced PDF files. It teaches you how to create a multi-page document, with page headers, footers, page numbers, shapes, and images.

In the previous tutorial we looked out how to create a simple PDF document that was one page and was only text. If you've seen many PDF documents on the web or elsewhere you know that they usually include more than just text. Fortunately we are able to do these things as well. In this VB PDF tutorial we're going to look at how to further use the mjwPDF class accomplish what we need. By the end of the tutorial you should be able to create a multi-page document that has headers, footers with page numbers, shapes, graphics, and web links.If you want, you can download the source code for this VB PDF tutorial and follow along with it.

If you haven't read the introductory tutorial about Creating a PDF document using Visual Basic. Please do so first. This VB tutorial builds off the previous one. In fact to start with lets look at the code we created before:

Private Sub Command1_Click()
    ' Create a simple PDF file using the mjwPDF class
    Dim objPDF As New mjwPDF
    
    ' Set the PDF title and filename
    objPDF.PDFTitle = "Test PDF Document"
    objPDF.PDFFileName = App.Path & "\test.pdf"
    
    ' We must tell the class where the PDF fonts are located
    objPDF.PDFLoadAfm = App.Path & "\Fonts"
    
    ' View the PDF file after we create it
    objPDF.PDFView = True
    
    ' Begin our PDF document
    objPDF.PDFBeginDoc
        ' Set the font name, size, and style
        objPDF.PDFSetFont FONT_ARIAL, 15, FONT_BOLD
        
        ' Set the text color
        objPDF.PDFSetTextColor = vbBlue
        
        ' Set the text we want to print
        objPDF.PDFTextOut "Hello, World! From mjwPDF (www.vb6.us)"
    
    ' End our PDF document (this will save it to the filename)
    objPDF.PDFEndDoc
End Sub

Great. With this code we've done all the initializing and created a basic file. Now lets add some formatting options. Right after we set the fonts folder lets add a few lines of code that tell mjwPDF what the document layout should be like.

    ' We must tell the class where the PDF fonts are located
    objPDF.PDFLoadAfm = App.Path & "\Fonts"
    
    ' Set the file properties
    objPDF.PDFSetLayoutMode = LAYOUT_DEFAULT
    objPDF.PDFFormatPage = FORMAT_A4
    objPDF.PDFOrientation = ORIENT_PORTRAIT
    objPDF.PDFSetUnit = UNIT_PT
    
    ' View the PDF file after we create it
    objPDF.PDFView = True

This code sets up a standard page (letter size) in portrait orientation and our units of measure as points.

Next lets do something fun. Often times you want to add a heading to a PDF document such as "Very Important Report Blah Blah" Lets figure out how to add a heading such as this to our document. Delete the bold lines of code below:

    ' Begin our PDF document
    objPDF.PDFBeginDoc
        ' Set the font name, size, and style
        objPDF.PDFSetFont FONT_ARIAL, 15, FONT_BOLD
        
        ' Set the text color
        objPDF.PDFSetTextColor = vbBlue
        
        ' Set the text we want to print
        objPDF.PDFTextOut "Hello, World! From mjwPDF (www.vb6.us)"
    
    ' End our PDF document (this will save it to the filename)
    objPDF.PDFEndDoc

And add these lines of code in their place:

' Lets add a heading
objPDF.PDFSetFont FONT_ARIAL, 15, FONT_BOLD
objPDF.PDFSetDrawColor = vbRed
objPDF.PDFSetTextColor = vbWhite
objPDF.PDFSetAlignement = ALIGN_CENTER
objPDF.PDFSetBorder = BORDER_ALL
objPDF.PDFSetFill = True
objPDF.PDFCell "A centered heading", 15, 15, _
    objPDF.PDFGetPageWidth - 30, 40

Let me explain what these mean. You should recognize the first line of code. It just sets the font info. Next we set the DrawColor (which in this case will be the highlight or inside color of our box). Next the text color is set and our alignment and border. The PDFSetFill=true tells mjwPDF to fill this box in when it prints out our text. The next line is what displays it all.

Let me break it down. The first parameter is simply the text we want displayed. Next we tell it how far over from the left we want the box (or cell) in our case we said 15 points over from the left. The next parameter is 15 points down from the top. Next we have to specify how wide the box is going to be. We want it to stretch all the way over to the right side of the page (minus the 15 point right border). To accomplish this we can use the mjwPDF classes PDFGetPageWidth function. This will give us the full width of the page we then subtract 30 off of it (15 for the left border and 15 for the right border), the last parameter is the height of the cell, 40 will be plenty high to accommodate our text.

If you run the code you should see your PDF pop up with a beautiful header at the top of the page.

Another fun thing is to create shapes in your PDF files. This can be used to create bar graphs or to highlight certain areas. Here is some sample code that creates a square.

        ' Lets draw a dashed red square
        objPDF.PDFSetLineColor = vbRed
        objPDF.PDFSetFill = True
        objPDF.PDFSetLineStyle = pPDF_DASHDOT
        objPDF.PDFSetLineWidth = 1
        objPDF.PDFSetDrawMode = DRAW_NORMAL
        objPDF.PDFDrawPolygon Array(300, 150, 400, 150, 400, 250, 300, 250)

Most the settings are self explanatory. Notice that you can specify the line style and the line width. Also notice that there is no draw square function. Instead there is a draw polygon function. It takes one parameter, but that parameter is an array of points specified in x y coordinates. X being how far from left to right to draw the point and Y being how far from top to bottom. So in our example we are specifying 4 points (the four corners of the square).

  • Point 1 is 300 pixels to the right, 150 pixels from the top
  • Point 2 is 400 pixels to the right, 150 pixels from the top
  • Point 3 is 400 pixels to the right, 250 pixels form the top
  • Point 4 is 300 pixels to the right, 250 pixels from the top.

Next lets draw an ellipse. An ellipse is simply a circle that can be squeezed either vertically or horizontally. To define it correctly we have to use some mathematical terms. If you remember from geometry class a circle has a radius. The radius is the distance from the center of the circle to the edge of the circle. An ellipse has two radiuses. One is horizontal the other is vertical. So the code for our ellipse is this:

        ' Lets draw an ellipse
        objPDF.PDFSetDrawColor = vbYellow
        objPDF.PDFSetLineColor = vbBlack
        objPDF.PDFSetLineStyle = pPDF_DASHDOT
        objPDF.PDFSetLineWidth = 1.25
        objPDF.PDFSetDrawMode = DRAW_DRAWBORDER
        objPDF.PDFDrawEllipse 300, 150, 75, 25

All the parameters should make sense by now. The new line is the PDFDrawEllipse call. Its a very simple call except that many times you think the x and y coordinates would correspond to the center of the circle. However, you would be wrong. Instead the first to parameters correspond to the upper left corner of the square that bounds the ellipse. The next two parameters specify the horizontal radius and the vertical radius respectively. If this seems confusing just run the program and you will see what I mean. The x & y parameters for our ellipse are the same as the x & y parameters for our first point in the square so you will see how it works. If you run the program you should see this:

Lets step back to text manipulation in PDF documents again. One thing you usually see in a professional document is the header like we did above. Another thing is usually page numbers in the footer. We can use the same logic we used for our header to add page numbers. I would like to add the numbers in the footer of the page on the right side, like most documents have. I'm not going to walk through how you can do this step by step, but here is the code for a visual basic subroutine that adds the page number to the bottom right corner of your PDF document.

' Adds the page number to the current page
Private Sub AddPageNumber(objPDF As mjwPDF, pageNumber As Integer)
    Dim sPageInfo As String
    Dim fontSize As Double
    Dim margin As Double

    fontSize = 10       'Size of font to use
    margin = 40         'Size of margin (left, right, bottom)
    
    ' Set what we want to print for page info
    sPageInfo = "Page " & pageNumber
    
    ' Should save these settings and change them back for more robust code
    objPDF.PDFSetTextColor = vbBlack
    objPDF.PDFSetAlignement = ALIGN_RIGHT
    objPDF.PDFSetFont FONT_ARIAL, Conversion.CInt(fontSize), FONT_NORMAL
    objPDF.PDFSetFill = False

    ' Uncomment the below line if you want to see how our formatting works
    'objPDF.PDFSetBorder = BORDER_ALL
    
    ' Draw the page number at the bottom of the page to the right
    objPDF.PDFCell sPageInfo, margin,  _
        objPDF.PDFGetPageHeight - margin - fontSize, _
        objPDF.PDFGetPageWidth - (margin * 2), fontSize

End Sub

Now that we know how to add page numbers how do we actually create multiple pages? Its very simple. When you are done with the first page, simply call the PDFEndPage method. Next call the PDFNewPage method to start the next page. Than just call the commands to add your text or shapes to the next page. You can do this as many times as you want. Don't forget to call the AddPageNumber method on each page though.

Another useful feature of PDF documents is adding bookmarks. Bookmarks allow you to jump from section to section in a PDF document easily. When the user views a PDF document with bookmarks, they are able to see a table of contents type tab on the left side of the screen. Note: if you want that pane to be visible by default you should add this line of code to the initializing section of your program.

    ' Lets us set see the bookmark pane when we view the PDF
    objPDF.PDFUseOutlines = True

Adding a bookmark is very easy in Visual Basic using mjwPDF. For instance lets add four bookmarks to our first page of our document. Call these anywhere in your code before you call the PDFEndPage method.

        'Lets add a bookmark to the start of page 1
        objPDF.PDFSetBookmark "A. Page 1", 0, 0
        
        'Now a bookmark half way down page 1
        objPDF.PDFSetBookmark "A1. Page 1 Halfway down", 1, 300
        
        'Now one at the end page 1
        objPDF.PDFSetBookmark "A2. End of Page 1", 1, 500
        
        'Another one a little further down and shows nesting
        objPDF.PDFSetBookmark "A2-Sub1.", 2, 800

The first call to PDFSetBookmark creates a bookmark labeled "A. Page 1". The next parameter is the depth of this bookmark. Note: Start your depth at 0. The last parameter is the y position to where the bookmark will move the page. So the first call created a bookmark titled "A. Page 1" that points to the top of page 1. The next call creates a bookmark titled "A1. Page 1 halfway down". It has a depth of 1 (so it will be a child under our first bookmark) and it will scroll the page 300 points down. If you run the program you will see all the bookmarks created like this screen shows.

Another necessity to learn when creating PDF documents is how to add images to them. The mjwPDF class allows you to add any .jpg images to your PDF document. If the image is in a different format you will need to convert it to .jpg before you will be able to add it to your PDF file. However, if the image is a jpeg it is very easy to add it to the PDF doc. In the sample source code included with this tutorial you will see a logo.jpg file. Below is the code to end our first page and to start our second page. On the second page we add our logo to the upper left corner of the page.

        objPDF.PDFEndPage
        
        'Start page 2
        objPDF.PDFNewPage
        
        'Lets add an image to page 2
        objPDF.PDFImage App.Path & "\logo.jpg", _
            15, 15, 50, 50, "http://www.vb6.us"

The highlighted code is what adds the logo. We call the PDFImage function. The first parameter is the path to the jpeg file. The next two parameters are the x and y coordinates for the logo. The next two parameters specify the width and height of the image. These parameters can be left off and then it will just display the picture in its original size. You can also specify just the height or width and it will scale the other side of the picture to keep it in proportion. The last parameter is also optional, but it allows you to specify a web site to go to if someone clicks on the image.

If you run your program now you will see a PDF file that has all the properties of a complete PDF document. Headers, shapes, images, and page numbers. Combining all these techniques you should be able to do just about anything you would want to. Download the Advanced PDF VB Tutorial source code to see the full sample.

Why would I buy a PDF control?

This is a common question. Although the mjwPDF class does allow you to do some pretty cool things you still may wish to buy a control for one or more of the reasons below:

  • You need to add other images besides JPGs on the fly.
  • You want to compress or encrypt your pdf file.
  • You need code that is more optimized for memory space or processor speed.
  • You need support from a reputable company.
  • You just like spending money for fun

If you get to a point where you do need to buy a PDF control I can probably recommend one to you. Send me an email and I can help you out. Otherwise if the mjwClass works for you feel free to use it. I would still ask you to send me an email just so I know what your using it for. Thanks.

Note: The original source code for this class (before modifications) can be found here.

If you enjoyed this post, subscribe for updates (it's free)

greek fonts

the program is VERY GOOD !!!!

Q: how can I create (or find) an AFM file with Greek fonts (courier) ?

thanks in advance

pavlos

mjwPDF.cls

I' m trying to get the code going and a pdf is created. However, Acrobat Prof (v7) keeps saying that the pdf document has errors and offers to save the file in a corrected state upon closing. Is the current source (download) up to date (per sept. 25, 2008)?

Regards, Ton

Reading data from PDF file and saving into database

Hi,

The above utility seems to be good.
I have requirement in which I have to read data from pdf file using VB6 and saving the data into Oracle database.
Please let me know if this can be done.

Thanks a lot,
Sania

Try this, works very

Try this, works very well:

http://support.microsoft.com/kb/194975

Try this, works very

Try this, works very well:

http://support.microsoft.com/kb/194975

Building A String with breaks or new line

Firstly, how does one view other replys?

I can't seem to get this to work is there another way to do this? Or have I got it all wrong?

Dim TestInputText As String
TestInputText = TestInputText & "Hello, World! " & vbCrLf
TestInputText = TestInputText & "From mjwPDF" & vbCrLf
TestInputText = TestInputText & "(www.vb6.us)" & vbCrLf

' Set the text we want to print
objPDF.PDFTextOut TestInputText

This is displayed like this:
Hello, World! From mjwPDF (www.vb6.us)

I would like it to be:
Hello, World!
From mjwPDF
(www.vb6.us)

multi Line

add this line
str_TmpText = Replace(str_Text, vbNewLine, ") Tj" & vbNewLine & PDFFontSize & " TL" & vbNewLine & "T*" & vbNewLine & "(")

below this in Sub PDFTextOut
str_TmpText = Replace(str_Text, "\", "\\")
str_TmpText = Replace(str_TmpText, "\\", "\\\\")
str_TmpText = Replace(str_TmpText, "(", "\(")
str_TmpText = Replace(str_TmpText, ")", "\)")

New line

It might be easier to just increment the Y every line yourself, you have more control that way.
I'm using inside loops:
objPDF.PDFTextOut _
Line1, 14, y
y = y + 14ish

New Line

Under the Class Module --> PDFTextOut --> add the second line below ...."12 TL"

PDFOutStream sTempStream, "BT"
' add the below line
PDFOutStream sTempStream, "12 TL"

You are very kind to share

You are very kind to share you programme.

I encounter some trouble while using the programme.

When I add a image to the pdf file,the image is invisible.

Could you please tell me why?

Start a new row/line

I can't seem to get this to work is there another way to do this? Or have I got it all wrong?

Dim TestInputText As String
TestInputText = TestInputText & "Hello, World! " & vbCrLf
TestInputText = TestInputText & "From mjwPDF" & vbCrLf
TestInputText = TestInputText & "(www.vb6.us)" & vbCrLf

' Set the text we want to print
objPDF.PDFTextOut TestInputText

This is displayed like this:
Hello, World! From mjwPDF (www.vb6.us)

I would like it to be:
Hello, World!
From mjwPDF
(www.vb6.us)

Form Fields

Hello,

I've had a quick look at your pdf class and it looks great. Here's what I need to be able to do (please tell me if it is possible). I need to create a "mail merge" type document using form fields on the pdf document. I will get values to load into the form fields from a database table. Is it possible to do this with your code?

Thanks in advance for your reply

If you are creating the

If you are creating the document from scratch than yes. If you are trying to fill in an already made PDF document than no.

Merging PDF ?

Hi everything sounds great in this page !

Do you have a VB solution to merge several PDF files in one ?

Ashlin

Not currently. The mjwPDF

Not currently. The mjwPDF class just writes PDF files it doesn't read them. You would need to read them in (w/ formatting) and re spit them out. You will have to go with a commercial PDF control for that.

Multiline

Is there a way to print Multiline of a text box, I have a text box set with Multiline=true and when I print it it is all in one line is there a way to index the output line

Thanks Joe

Print to what? The printer

Print to what? The printer or a PDF file or your textbox? I'm confused as to what your asking.

text box

In my vb program I have a text box with 30 lines of text when I print it to PDF it is one long line I need to print each line by it self
can this be done

Thanks for your great site to!!

Joe k

I see

You need to use objPDF.PDFCell instead of objPDF.PDFTextOut. See the example above of the header. If you use PDFCell it will automatically word wrap for you.

WordWrap

Well i tried the code and it works just fine with your box and header but if I tell it to use text1 I still get all 3 lines of text in a string and not
Line1
Line 2
Line3 ??

here is my code all i have is command1 button and a text box with 3 lines of text

I am sure it is me Sorry!!

' Create a simple PDF file using the mjwPDF class
Dim objPDF As New mjwPDF

' Set the PDF title and filename
objPDF.PDFTitle = "Test PDF Document"
objPDF.PDFFileName = App.Path & "\test.pdf"

' We must tell the class where the PDF fonts are located
objPDF.PDFLoadAfm = App.Path & "\Fonts"

' Set the file properties
objPDF.PDFSetLayoutMode = LAYOUT_DEFAULT
objPDF.PDFFormatPage = FORMAT_A4
objPDF.PDFOrientation = ORIENT_PORTRAIT
objPDF.PDFSetUnit = UNIT_PT

' Lets us set see the bookmark pane when we view the PDF
objPDF.PDFUseOutlines = True

' View the PDF file after we create it

' Begin our PDF document
objPDF.PDFBeginDoc
' Lets add a heading
objPDF.PDFSetFont FONT_ARIAL, 15, FONT_BOLD
objPDF.PDFSetDrawColor = vbRed
objPDF.PDFSetTextColor = vbBlack
objPDF.PDFSetAlignement = ALIGN_Right
objPDF.PDFSetBorder = BORDER_None
'objPDF.PDFSetFill = True
objPDF.PDFCell Text1, 15, 15, _
objPDF.PDFGetPageWidth - 30, 40

' End our PDF document (this will save it to the filename)
objPDF.PDFEndDoc

Your Just COOOOOOOOOOOOOOL!

Thank You so Much I have played for 4 days and you did in 4 min.

Joe k
PS I got my login e mail as well
Thanks Again

How did you solve your

How did you solve your issue? can you share with us?

Add text to existing pdf file

I would like to add a text to an existing pdf file? Can I use the mjwPDF class to do this?

Not easily. The mjwPDF class

Not easily. The mjwPDF class doesn't have any functions to read pdf files - only to write them.

Line

How do you just draw a line across the page
Thanks Joe
PS love your site

You can just use the

You can just use the DrawPolygon (like the square above - just put the points in the right places)

Thanks

Thank You

Good codes... will there be a tutorial in content searching?

The codes looks really good, although I haven't really got the chance to try it yet (going to soon!)

Before I dig deep into the codes which in many ways useful for my office in-house, would there be a possible tutorial about content search and highlight found searched words? My primary problem is this and I haven't found any decent codes nor dlls for me to use in this matter.

Hope that would be a response soon. ^_^

Thanks so much for sharing!

Michiyo

How to add table to pdf form?

Hi i want to add table to pdf form and have to fill using database. is it possible with this mjwPDF class?

RE: How to add table to pdf form?

Hi,

did you get any solution for it "\t" created a tab char but did not work that well pls let me know if you get an answer.

-Joseph

VB6-Excel-PDF

I have written a program in VB6 with Access DataBase. Data are entered in VB, save in access and report is created by creating Excel. This report is sent to the respective clients via e-mail thru vb6 codes. The task I need to do is to convert this Excel Workbook / sheet in pdf format ( which is non-editable ) , save it in pdf format and e-mail to the client. All need to be done using VB6 form and VB6 codes.
Any codes available ? or can anybody help?
MM

To alter the pages of a pdf

Thanks for your most helpful tutorials!

We need to manipulate (remove or add) pages of a pdf file through Visual Basic.
Our VB application saves an "Active Report" (similar to Crystal Reports) as a pdf file. The app was designed to print an actual booklet, thus there are empty/mostly-empty pages included for aesthetics, which we want to remove from our pdf version. For ex. the book has 24 pages, but we want to show only nine of them.
What code (VB?) could we use to open the pdf file, and remove specific pages (ex pages 3, 4-6, 9, 12, 13, 20), and then send the desired pdf pages?

Also, how could we remove some pages, and replace them with other ones?

Thanks so much for your help!
Avi

Print existing PDF files to printer in Visual Basic

Got any quick & easy ideas to take an existing PDF file and spool it to a printer (default printer is fine) using Visual Basic. Something where I'd pass the path name of the file and it would spool out to the printer. (Would be nice if it could return the number of pages printed -- but not necessary)

Pdf Class

Hello,
I tried to use this class to write in the PDF created on the following operating system: Windows embedded, and Windows 2003 Server.
The PDF is created, but what i want to write inside is not written.

Somebody can help me with same advises?
Also this function PDFFileName, if i create a PDF, and this is opened, and i press again the button create pdf, is giving me an error. "permission denied", and is related with this:
Err_File:
If Err = 70 Then
hWnd = FindWindow(vbNullString, "Adobe Reader - [" & sFileName & "]")
retval = PostMessage(hWnd, WM_CLOSE, 0&, 0&)
Sleep 17

Set Strm = Fso.CreateTextFile(sPDFName, True)
Resume Next
End If

GREAT CLASS Need GIF Image insertion

Hey ITs GREAT JOB!! It works perfect for my needs. I had one query. Why cant it support GIF and other formats? JPEG images are very bad in quality when I print them. I would like to try other formats like GIF etc. Please reply.

PDF class

Awesome PDF class you have there, have been tinkering with it for a week now. Sadly the files it generates are too large for what I need. (I suspect the repeated calls to .PDFCell to achieve the formatting I want have created a bloated and slow to generate file..). Is it possible to avoid this? If not, could you recommend any good commercial pdf generation applications? I am using it to display tabular information on multiple pages.. very repetative, just time consuming and large.

Thanks

Great great stuff... but there's a flaw!

Great code, thanks so much!

But there's a flaw with the JPG file validation code in PDFimage:

This validation (occurs twice in class module) is badly designed... If I'm trying to load a jpg image with a .JPG extension (upper case), it doesn't take it... you should check for all case jpg, jpeg, JPG, JPEG !

If Right(pFileName, 3) = "jpg" Or Right(pFileName, 4) = "jpeg" Then

Other than that, works really well, thanks!

Fred from Montreal, QC

tradition chinese

Hello!

Many thanks for your mjwClass, it is very great!

I tried it before. Use English is no problem. but when I use traditional chinese (Unicode), the program hangs up.

I think the mjwClass does not support any fonts other than english, and may be I must find the adobe chinese tradition fonts in one of a computer that installed adobe reader.

Can you give me some opinion?

Many thanks for your code.

tiomc