Monday Aug 06, 2007

Ripped Crosstabs

[Read More]

Wednesday Aug 01, 2007

PDF Data Entry - Part III

[Read More]

Monday Jul 30, 2007

PDF Data Entry - Part II


Last time we looked at building and pre-filling the PDF data entry form. We now need to look at how we can allow the user to 'submit' the data they have entered back to the server and to then let them know that their data has been received.

There are a several of ways that Adobe will allow you to post data from a form.


Im using Adobe 6 you may be on another version, things should be similar thou. The properties dialog, for a button reveals the folloiwn submission methods:

  • FDF - this is Adobe's 'Form Data Format' - you can get more info on this here. It's a proprietory format for sending (and receiving) form data and comments. Im not going to deal with this format.
  • HTML - need I say more except Im not going to deal with this either
  • XFDF - XML Forms Data Format. Yep, you guessed it, it's Adobe's proprietory XML format for the forms data - now this we can and will use. Not the friendliest format but guess what? We have an API for that.
  • PDF - you can just submit the complete PDF form. This is useful if you wanted to store a copy of a form created by a user. Even better if they signed the form with a digital signature - as good as a paper signature. Of course we need to scrape the data out of the form too - yep, we have an API for that too and we're going to try that too.

Now I guess you could use the HTML format and Adobe provides an SDK to parse the FDF format but why bother, Publisher has all you need for for the last two formats and they have enough information.

Using the properties dialog we can choose XFDF or PDF. Initially I chose XFDF, I need to POST the XFDF to some CGI process on a web server. I elected to use a servlet. Looking at the graphic above you'll see I have entered a URL. Therein lies an issue, I have hardcoded the URL on the button - you got it. We have an API for that, now I have to admit this one is hidden and again I lent on Incheol for information.

We have an undocumented class FieldEditor, as the name suggests you can edit fields with it - that includes adding fields too. So, we can  create the button in its entirity and enter the submission destination and format and then put it on the page.

We first need to instantiate a PDFParser object, this takes the file we want to edit as an input. We then create a FieldEditor object and add the button and then re-generate the form. The addButton method takes a series of parameters.


Most I hope are self explanatory except maybe:
btnCode - you can create a submit or javascript type button and here is where you pass either the

            //Add the button
            float[] btnCoords = {350f,350f,470f,380f};
            float fontSize = 16f;
            String btnName = "SUBMIT_BTN";
            String btnLabel = "Submit";
            String btnDest = "";
            int btnPg = 0;
            //Create a PDF Parser instance
            PDFParser pdfP = new PDFParser(pdfForm);
            //Create a FieldEditor instance
            FieldEditor fldEd = new FieldEditor(pdfP);
            //Add the button
            //Regenrate the form

Now the only drawback is that the API does not let you influence the look and feel of the button, so you get a flat button ... not exactly a nice beveled 'clickable' affair but it gets the job done. Before you ask, no there is not a method to update a button. We can look into that if enough of you scream loud enough. I also have to admit that we do not give you the control over the posting format of the button e.g. XFDF, PDF, etc. It defaults to HTML ... dang - Im logging an enhancement for this today.

Apologies for this tangent we got on to with buttons that led down a rather disappointing cul-de-sac. Next time, we get into receiving the contents of PDF via a servlet and letting the user know we got their information. 


Wednesday Jul 25, 2007


[Read More]

Thursday Jul 19, 2007

I want a default font!

[Read More]

Tuesday Jul 17, 2007

One Page Only Please

[Read More]

How to improve your image

[Read More]

Tuesday Jul 10, 2007

Dynamic Formatting Again


Question on the forum today asking how you might use some meta information stored in the incomng XML data to format the final output i.e. override any formatting you might have created in the RTF template. I covered how to do this if the XML is actually HTML e.g.

<TEXT><B>Report Title</B></TEXT> 

You can check that out here.

What to do if you have something like the following:

<?xml version='1.0'?>


<TITLE format="bold">The Crazy Dog</TITLE>

<TEXT format="italic">I've seen many strange dogs but this is the one. you should see some of the things hes done. I've seen him jump and try to eat sand. he had a mouth full of dirt as soon as he would land. if you saw him you'd probably giggle. if you do you have probably seen him squiggle. the strange thing is hes never snappy but he is always happy! every one knows him now and he says to you "bow wow!" </TEXT> </POEM>

Notice the format attributes specifying how the text shuld be formatted.
We need to use some of the techniques from the HTML formatting article to specify the formatting required using the XSLFO syntax. Keeping things simple we can just use simple conditional 'if' statements to check the value of the 'format' attributes. Using the TITLE element we can use:

 <xsl:attribute xdofo:ctx="block" name="font-weight">bold</xsl:attribute>
<?end if?>

Similar approach for the italic or any other attribute. You could build a subtemplate to handle all of the possible 'formatting' options to simplify your coding and making it more dynamic. Get ya example files here.

In case you're wondering, the poem is from my son about our new puppy.


Thursday Jun 21, 2007

Get Templates from Microsoft

[Read More]

Wednesday Jun 20, 2007

Template Builder Issues Fixed

[Read More]

Thursday May 24, 2007

Turning Rows into Columns

[Read More]

Tuesday May 22, 2007

Where're my Checkboxes?

[Read More]

Monday May 21, 2007

New Template Builder release available for Apps

[Read More]

Tuesday May 15, 2007

More Chart Tips

[Read More]

Friday May 04, 2007

New Template Builder

[Read More]

Monday Apr 30, 2007

Dastardly Dynamic Data Dilemma

[Read More]

Friday Apr 20, 2007

A date addition

[Read More]

Wednesday Apr 11, 2007

Getting Vertical

[Read More]

Friday Mar 30, 2007

Anatomy of a Template III - Page Totals and Last Page


Finishing up on this series we will now add a page total and a region that needs to show only on the last page of the document.

Page Totals - as many of you know we have direct support for page totals. You register a page total object in the template and then place it where its required to be rendered. The total is not actually calculated until the rendering engine starts to layout the data on the page, thats the only point at which the engine knows how many 'line' can fit on the page. In our case we know how many lines we are going to fit because we have fixed the number of rows before the rendering engine starts. We also already have those lines loaded into a variable 'invLines' so calculating a total is going to be relatively straightforward.

<?sum($invLines[(position()>=$start) and (position()<($start+$lpp))]/LINE_EXTENDED_AMOUNT)?>

Here's an XPATH expression again inside the '[ ]', this limits the number of rows we want  to sum. it's like a 'where' clause on our data.

If we wanted the word 'Continued ...' to be shown we test the current record position against the total number of lines for the invoice. If they were not equal then we would show the 'Continued ...' string.

Last Page Only - again we now have native support for this when you do not know how much data is going to fit on a page with 5.6.2. In this case thou, we know how much data is going on the page and can ensure that a section on prints on the last page. Take a look a the template, there is a table to hold the summary/special instructions for the invoice at the end of the template. All we have done is wrap an if condition around that table:

<?if:count($invLines) < $start+$lpp?>

This checks to see if we have reached the end of the invoice lines section and if so then render the summary section i.e. on the last page. Then we close out the if condition. To get the table to appear at the bottom of the last page you'll have notived that we created a two celled table and put the line table in the top cell then the summary in the lower one and then drageed the cell border down the page to position the summary at the bottom of the page.

We now have an all singling all dancing invoice template, the features we added were:

1. A fixed number of rows per page,
2. 'Filler' space for lines, because that last page may only have 3 lines but you want to maintain the layout
3. Page totals or 'Continued' in place of a total
4. Last page only content
5. Header and page number resetting as we hit each new invoice in the batch.

The final template, data and output are available here.

We can now take some of those individual features and apply them to pretty much any other document whether than be a batch of purchase orders or a single standard letter showing outstanding invoices. Hope it's been helpful.

Wednesday Mar 28, 2007

Anatomy of a Template II - Headers and Filler


Continuing on from yesterday, today we'll add in the repeating header and a filler for the invoice lines. Imagine you have pre-printed stationary, yesterday we tacled how to get X number of lines on each page, now assume that on the last page of the document you need a summary at the bottom of the page. If that last page only has 5 rows of data and we were printing 20 rows on the previous pages then once the 5 rows are rendered the summary will then render directly under the five rows i.e. not at the bottom of the last page ... still with me? With 5.6.2 we introduced the concept of a last page only command; we could use that here but I want to continue with the idea of filler rows and we'll tackle the last page only option later.

Taking a batch invoices as our example we can add the header and the filler rows.

Reset your Head

For the header we want to have say an invoice header with page numbering, etc. As we hit a new invoice we want the header information to change and the page numbering to reset. To do this we can use the '@section' option for the for-each command. We create the header layout in the MSWord header.


Notice we can not put formfields in to the MSWord header section so we either need to type in the commands or use a header template and reference it.
The only extra fields added are:a
FE G_INVOICE - this starts the looping over each invoice using the @section to reset the header information as each new invoice is reached.
EFE - this closes out the loop above

Running this template (Inv_Header.rtf) gives us two invoices with a repeating header on each page with page numbering per invoice.

Spaced Out

Now lets add the logic for the filler rows, you can see the new fields and empty table just below the lines table in the Inv_Header_Spacer.rtf template. There are two new fields
Filling Out Space - this contains the logic to check if the number of rows rendered above equals the lines per page variable. If not then insert the table row until it does.
<?if:not(count($invLines) mod $lpp=0) and ($start+$lpp>count($invLines))?>
     <?if:position()<$lpp - (count($invLines) mod $lpp)?>

then we have the blank table row, then 
End Filling - this just closes out the for-each and the if statements. 

I just added a static string 'End of padded lines' to check that we are actually padding. Complete samples available here.

Next, page totals and last page only ...


Follow bipublisher on Twitter Find Us on Facebook BI Publisher Youtube ChannelDiscussion Forum

Join our BI Publisher community to get the most and keep updated with the latest news, How-to, Solutions! Share your feedback and let us hear your voice @bipublisher on Twitter, on our official Facebook page, and Youtube!


« June 2016