Sunday, December 13, 2009

Create PDF / FDF in Lotus Notes using LS

I had task where I should create PDF file from template and fill fields by values from documents
So what did I do?

I spoke with my colleagues :-) they recommended to use FDF Toolkit For Windows, instead of iText approach that I used before, and I have to say that it is very cool approach, it is much better at least for me. Instead of generation new PDF file we just export data to FDF file and link it with PDF template and that's all, so our FDF will show data using PDF form/template. -> No Java required and now no non-supported libraries.

Here is an instruction how to do this:
  • register FDFACX.DLL (in order to do that, I copied FdfTk.dll and FDFACX.DLL to windows\system32, but I believe there is better way)
 regsvr32 C:\WINDOWS\system32\FDFACX.dll  
  • example of code now (it is from Adobe)

Using the FDF tooklit in LotusScript

 Sub Initialize  
 ' Set up for using the FDF Toolkit for ActiveX  
 Dim FdfAcX As Variant  
 Dim outputFDF As Variant  
 Dim sPdfFileName As String, sFdfFileName As String, sFilePath As String  
 Set FdfAcX = CreateObject("FdfApp.FdfApp")  
 Set outputFDF = FdfAcX.FDFCreate()  
 ' % REM  
 ' Change these paths to reflect your server environment  
 ' Ideally, you could use a Lotus Notes profile document to store this  
 ' information.  
 ' Below are the three options for storing the PDF that was discussed in  
 ' the documentation for this application.  
 ' Option 1 : UNC Directory Share  
 ' This option oddly asks if you would like to save on close.  
 ' sPdfFileName = "\\Mage\domdata\domino\html\pdf\panarama.pdf"  
 ' Option 2 : Store in a Lotus Notes Page element  
 sPdfFileName = "http://mage/pdf/panarama.nsf/PDFs/$file/panarama.pdf"  
 ' Option 3 : Store in the Domino HTML directory  
 ' REM %  
 ' sPdfFileName = "http://mage/pdf/panarama.pdf"  
 sFilePath = "d:\domdata\domino\html\pdf\tmp\"  
 ' Set up for getting Lotus Notes information  
 Dim session As New NotesSession  
 Dim contextDoc As NotesDocument  
 Dim dateTime As NotesDateTime  
 Dim tempNumber As Single  
 Dim rounded As Integer  
 Dim fileName As String  
 Set contextDoc = session.documentContext  
 8 Integrating Adobe Acrobat FDF  
 with Lotus Domino  
 ' This will create a random number between 0 and 100.  
 ' The number will give  
 ' us a good chance of not temporarily having the same file name in the tmp  
 ' directory at the same time. The file will briefly be in the tmp  
 ' directory,  
 ' attached to the Notes document and then deleted.  
 temp = Rnd  
 rounded = Round((temp * 100), 0)  
 fileName = Cstr(rounded)  
 sFdfFileName = sFilePath & fileName & ".fdf"  
 ' FDFSetValue will set the value you pass it. See page 139 of the  
 ' FDF Toolkit Overview and Reference.  
 outputFDF.FDFSetValue "FirstName", contextDoc.FirstName(0), False  
 outputFDF.FDFSetValue "MidInit", contextDoc.MidInit(0), False  
 outputFDF.FDFSetValue "LastName", contextDoc.LastName(0), False  
 ' Get the value of the date fields. The DateOnly property  
 ' returns a string.  
 Set dateTime = New NotesDateTime( contextDoc.HireDate(0) )  
 outputFDF.FDFSetValue "HireDate", dateTime.DateOnly, False  
 Set dateTime = New NotesDateTime( contextDoc.ModDate(0) )  
 outputFDF.FDFSetValue "ModDate", dateTime.DateOnly, False  
 outputFDF.FDFSetValue "Address1", contextDoc.Address1(0), False  
 outputFDF.FDFSetValue "Address2", contextDoc.Address2(0), False  
 outputFDF.FDFSetValue "City", contextDoc.City(0), False  
 outputFDF.FDFSetValue "State", contextDoc.State(0), False  
 outputFDF.FDFSetValue "ZipCode", contextDoc.ZipCode(0), False  
 outputFDF.FDFSetValue "Country", contextDoc.Country(0), False  
 outputFDF.FDFSetValue "MAddress1", contextDoc.MAddress1(0), False  
 outputFDF.FDFSetValue "MAddress2", contextDoc.MAddress2(0), False  
 outputFDF.FDFSetValue "MCity", contextDoc.MCity(0), False  
 outputFDF.FDFSetValue "MState", contextDoc.MState(0), False  
 outputFDF.FDFSetValue "MZipCode", contextDoc.MZipCode(0), False  
 outputFDF.FDFSetValue "HomePhone", contextDoc.HomePhone(0), False  
 outputFDF.FDFSetValue "WorkPhone", contextDoc.WorkPhone(0), False  
 outputFDF.FDFSetValue "Emer1Contact", contextDoc.Emer1Contact(0), False  
 outputFDF.FDFSetValue "Emer1Phone", contextDoc.Emer1Phone(0), False  
 outputFDF.FDFSetValue "Emer2Contact", contextDoc.Emer2Contact(0), False  
 outputFDF.FDFSetValue "Emer2Phone", contextDoc.Emer2Phone(0), False  
 ' Tell it which file we're writing to and do a save.  
 outputFDF.FDFSetFile sPdfFileName  
 outputFDF.FDFSaveToFile sFdfFileName  
 ' Always close your open FDF files.  
 User Guide  
 ' This will attach the FDF file we just closed to our Notes document  
 ' and then delete it from the tmp directory.  
 Call MoveFdfToAttachment(contextDoc, sFdfFileName)  
 End Sub  
 Public Function MoveFdfToAttachment(doc As NotesDocument, fileName As  
 String) As Integer  
 '// move each attachment to a rich text field.  
 Dim attachItem As New NotesRichTextItem(doc, "fdfAttachment")  
 Dim attachObj As notesEmbeddedObject, newObjName As String  
 Call attachItem.EmbedObject(EMBED_ATTACHMENT, "", fileName, "")  
 Kill fileName  
 MoveFdfToAttachment = True  
 End Function  

Related articles about creating PDF files


sean said...

what other software is required - it looks as though paid for acrobat software is needed ?

Thanks, Sean

sean said...

oops - the link is

Dmytro Pastovenskyi said...

you don't need to pay at all. of course if you want create PDFs you have to buy licensed versio of Adobe.

but if you already have PDF you can do it for free

AxelJanssen said...

Why not simply use iText with an Java Agent? iText is very good, feature-rich, often used, very good documented and stable.

Dmytro Pastovenskyi said...

answer is simple,

because I believe it is always better to use official toolkit instead of free libraries.

and another point, this iText does not work properly with LS2J appraoch (at least in my case).

and I did not talk that iText is bad, I just found for myself another approach that I believe is much better

Bruce Lill said...

You can also just parse the fdf file and do a replace with the new values. I used ~~fieldname~~ in the fdf fields and then just replaced the value with the actual field value. Works in LS & Java.Also you didn't have to recode for additional fields added to the form that were on the form.

Pawan said...

I am not understanding the concept of storing the PDF. What type of pdf i have to store under html/pdf.

I followed all the steps an when calling the agent from notesdocument(Web) I can see the a link with cross maek in the Rich Text field "fdfAttachment" link is

When I'm clicking on ths link No Page is displaying.
What I have to do to open pdf.

Dmytro Pastovenskyi said...

you have to open FDF file
FDF file should contain link to PDF file inside.

and I would propose to use XFDF approach instead of FDF. FDF is old approach and I did not know that before :)

Pawan said...

Ok..Thanks. but for XFDF what steps i have to perform

Dmytro Pastovenskyi said...

generate XML file like on screen

you can export your document to DXL and use XSL to easily get XFDF file.