Friday, 8 July 2011

ASP: use FPDF to create a PDF with a dynamic table

   


Following my two previous articles about FPDF (Create PDF files with FPDF and FPDF MultiCell with multiple lines and positioning), today I would like to share a way to create a table dynamically, getting the items from a database, and displaying those items one after the other.

As usual, we have to make some assumptions. First of all we have a database from which we will get the records for the table. As an example, we can imagine our table is something like:

FRUITIMAGE_URL
orange/images/orange.jpg
apple/images/apple.jpg
pear/images/pear.jpg

Our goal is to create the PDF with the above table. We will create the table dynamically, and the table will have two columns: one for the fruits and one with the image of the related fruit.

If you are interested in the following explanation, but you haven't read the previous articles about FPDF, I suggest you read them before continuing, because here I assume you already know how to create a basic PDF file using FPDF.


The code
The main issue when creating the above table is the positioning of elements. Basically we need to position the MultiCell dynamically. We already saw something similar in my article about MultiCell positioning however, in this post we will approach the issue in a different way.
We need to use the recordset index to dynamically place the elements of the table. So, we need to determine the distance from the top margin before anything else. As an example, our top margin will be 50mm.

Ok let's see the code. In our ASP page, after creating the recordset (which is called FruitList) and after declaring all the FPDF parameters, we create a variable and give it a value of 50mm.
Dim topmargin
topmargin = 50
We declare the variables for the repeat region:
Dim FL_index
FL_index = 0
And we create the table:
While (NOT FruitList.EOF)
pdf.SetXY 8,topmargin
Set fs=Server.CreateObject("Scripting.FileSystemObject")
If (fs.FileExists(Server.MapPath("(FruitList.Fields.Item("IMAGE_URL").value))))=true then
   pdf.Image (FruitList.Fields.Item("IMAGE_URL").value),8,topmargin,0,10
else
   pdf.Image "/Images/noimg.jpg",8,topmargin,0,10
end if
set fs=nothing
pdf.SetFillColor 136,136,136
pdf.MultiCell 55,10,(FruitList.Fields.Item("FRUIT").value),1,2,1
FL_index=FL_index+1
topmargin=topmargin+(FL_index*10)
FruitList.MoveNext()
Wend
A few notes to the above code:
1) after opening the repeat region, we set the coordinates using the topmargin variable;
2) we then check for the existence of the image (just to be sure) and, if so, we display it, otherwise we display a generic noimg image;
3) the SetFillColor command is completely optional. I inserted it just to show you what you can do to change the MultiCell background color;
4) we insert the fruit into a MultiCell which has a width of 55mm and and height of 10mm (I say mm because I assume you set that as parameter with CreatePDF when the FPDF class is initialized);
5) we increase the index and the topmargin, before moving to the next record. The topmargin is increased multiplying the index by 10 (1x10, 2x10 and so on), because our MultiCell has an height of 10mm.

I hope everything is clear and that you find the example useful. Let me know what you think about it.

9 comments:

  1. OMG!
    I solved a hack with your code.
    From Spain, thank you.

    ReplyDelete
  2. Hey, I'm really glad the article has helped you in solving a problem! And a big thank you for letting me know about it. Hope it's sunny in Spain today, because here it's raining...

    ReplyDelete
  3. Hi Marco,

    I have a problem with repeat region.
    I can't get the Cell and Image function simultaneously.

    Cell function start after two height of 130 at a new page
    Image function continue. So I see a third image at the bottom of page 1.

    Do I something wrong with the y parameter.

    Set pdf=CreateJsObject("FPDF")
    pdf.CreatePDF()
    pdf.SetPath("../fpdf/")
    pdf.Open()

    Dim y
    y = 10

    pdf.AddPage()
    pdf.SetFont "Arial","",12
    pdf.setfillcolor 255,255,255
    pdf.SetXY 10,y

    While ((Repeat1__numRows <> 0) AND (NOT rsMember.EOF))

    Set fs=Server.CreateObject("Scripting.FileSystemObject")
    If (fs.FileExists(Server.MapPath("/images/member/"&Replace((rsMember("name"))," ","_")&".jpg")))=True Then
    pdf.Image "/images/member/"&Replace((rsMember("name"))," ","_")&".jpg",10,y,47,70
    Else
    pdf.Image "/images/member/empty.jpg",10,y,47,70
    End If

    pdf.Cell 190,130,""&(rsMember("name"))&"","1","1","R","L",True

    y = pdf.GetY()
    pdf.SetXY 10,y

    Repeat1__index=Repeat1__index+1
    Repeat1__numRows=Repeat1__numRows-1
    rsMember.MoveNext()
    Wend

    pdf.Close()

    ReplyDelete
    Replies
    1. Try to output the y variable and see how it goes.
      If you exactly know what's the height of the image (and I suppose you know it), try to increment the y variable by that height + margin.

      Delete
  4. Hi Marco,

    The script below works correct. I use the y height of the cell in this case 138 and substract this value from the image y parameter.

    I don't know of this the correct way but it works.

    So this script generate multiple A4 papersizes.Each paper contains 2 cells with an image.

    While ((Repeat1__numRows <> 0) AND (NOT rsMember.EOF))

    y = pdf.GetY()
    pdf.SetXY 10,y

    pdf.Cell 190,138,""&(rsMember("name"))&"","1","1","R","L",True

    y = pdf.GetY()

    Set fs=Server.CreateObject("Scripting.FileSystemObject")
    If (fs.FileExists(Server.MapPath("/images/member/"&Replace((rsMember("name"))," ","_")&".jpg")))=True Then
    pdf.Image "/images/member/"&Replace((rsMember("name"))," ","_")&".jpg",12,y-138,46,70
    Else
    pdf.Image "/images/member/empty.jpg",12,y-126,46,70
    End If

    Repeat1__index=Repeat1__index+1
    Repeat1__numRows=Repeat1__numRows-1
    rsMember.MoveNext()
    Wend

    ReplyDelete
  5. hi.. Marco
    first of all a big thanks for yours good work.
    I have an issue with FL_index variable in your sample code, I do not understand how it will count the no. of lines in

    multicell.
    i have 8 columns in my pdf and i am displaying records row by row in 8 columns using multicell and then a line
    after every row and it is impossible to draw line untill i know the maximum no. of lines in any multicell of the
    row because line has to be drawn below the multicell of max. no. of lines and multicells have no borders.
    please help.

    ReplyDelete
    Replies
    1. Ajay,
      The variable increments by one every time you add a new row. If you look at the end of the repeat region you will see that the index increments by 1.

      Delete
    2. Yeah, i understand that but issue is how to determine the no. of lines in a multicell when it is displayed on pdf file.

      Delete
    3. It will be the fl variable. Print it on your PDF and you will see that it will match the number of line/records.

      Delete

Comments are moderated. I apologize if I don't publish comments immediately.

However, I do answer to all the comments.