Anatomy of a Template I - Fixed Row Enumeration

The bursting articles are still in process ... I did some work a while back for a training course on the 'anatomy of an invoice template' ... there are some useful 'bits' that I thought you might like to see. 


One of the most requested features on the forum for RTF templates is to show a fixed number of rows per page. Maybe you have pre-printed stationary that can only take a certain number of lines, maybe you have a functional requirement for it. For whatever the reason id the functional folks have given it to you to implement.  Up until now there has been a template floating around that I think I let loose that shows how this can be done for invoices. There is little explanation of whats going on and how it's done. I'll try and make ammends to those of you that may have gotten a little lost but plugged it in anyway and it worked so what the heck.


I have started off small and we'll build this template up into a full invoice format that can run against the standard AR Oracle Report in 11i (RAXINV) ... those of you that are not EBSer's or are not interested in the invoice format, dont worry, you can follow along and apply the same principles to any data set. Here's the features out template is going to have.

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.


For all of the explanations we are going to use the attached XML. Its a full invoice batch, thats multiple invoices having multiple lines.

The Data


Lets start with number 1, for the fixed row enumeration we are only interested in the lines section of the XML, so we can focus on this portion Im going to ignore the rest of the XML. We are only interested in the G_LINES group of the XML structure:

<G_LINES>
 <LINE_NUMBER>1</LINE_NUMBER>
 <LINE_CUSTOMER_TRX_ID>1903</LINE_CUSTOMER_TRX_ID>
 <LINE_CUSTOMER_TRX_LINE_ID>1801</LINE_CUSTOMER_TRX_LINE_ID>
 <LINE_CHILD_INDICATOR>0</LINE_CHILD_INDICATOR>
 <LINE_TYPE>LINE>LINE</LINE_TYPE>
 ...
</G_LINES>
<G_LINES>
 <LINE_NUMBER>2</LINE_NUMBER>
 <LINE_CUSTOMER_TRX_ID>1903</LINE_CUSTOMER_TRX_ID>
 <LINE_CUSTOMER_TRX_LINE_ID>1817</LINE_CUSTOMER_TRX_LINE_ID>
 <LINE_CHILD_INDICATOR>1</LINE_CHILD_INDICATOR>
 <LINE_TYPE>LINE>LINE</LINE_TYPE>
 ...
</G_LINES>


There are obviously a lot more elements and a lot more lines but all we are interested in is, the grouping and the line type for now.


The Template


Now take a look at the template; if you just look at the table and nothing else it all looks pretty normal. We have a for-each, some fields followed by an end for-each ... straightforward stuff right. You'll notice the for-each has a little more going on thou and there's that 'if' condition:

<?for-each:$invLines?>
<?if:position()>=$start and position()<$start+$lpp?> 

I'll come back to these, lets look first at the fields above the table:

LinesPerPageVariable - this does what it says on the can and sets up the number of lines we want to see per page and assigns it to a variable 'lpp'. Now remember native XSL 'variables' are not like other language variables, think of them more as constants.

        <xsl:variable name="lpp" select="number(15)"/>

LinesTreeVariable - this holds not just a single value but a complete tree of values. Word of caution here, if you are going to do this you need to be aware that the XSLT engine is going to load this tree into memory ... so do not load huge trees. In our completed invoice template we will only load the lines tree for each invoice. In this example we are loading all the lines in the XML regardless of invoice ... thats OK thou, our XML is small, just be aware of what are doing here.
We have a variable 'invLines' and we are loading the members of the G_LINES group where the TYPE is equal to 'LINE'. Notice we use an XPATH expression to do this. We also use the 'incontext' command to ensure we are picking up the lines only for the current position i.e. within the current invoice. For this example remember we have no invoice header so we pick up all lines into the tree.

          <xsl:variable xdofo:ctx="incontext" name="invLines" select=".//G_LINES[LINE_TYPE='LINE']"/>

FEinvLines - this is the first loop we need to to go over the G_LINES group we created earlier. Although there is only a single group we need to iterate over it so we can set up a variable to hold the starting line position.
The if statement is checking if the record position we have reached modulizing with the line per page count equals zero i.e. we have reached the first record
 the create a variable (constant) called 'start' and initialize it with '0'.

<?for-each:$invLines?>  
 <?if:(position()-1) mod $lpp=0?>  
   <xsl:variable name="start" xdofo:ctx="incontext" select="position()"/>


Now we get into the table, the first field in their is another for-each but this time we are going to loop over the members of the invLines tree. Notice the use of the '$' to reference the variable.


<?for-each:$invLines?>
 <?if:position()>=$start and position()<$start+$lpp?>

The if statement here is checking that the current record pointer 'position()' is either greater than 'start' ie the first record or less the 'lpp' value we set up earlier. If it is then show the record otherwise not. the rest of the table is standard stuff.

Now we wanted a fixed number of rows per page and the logic above will provide that but of course the template needs to signify the need for a page break after the alloted number of rows have been shown. Looking at the 'Page Break' field:


<xsl:if xdofo:ctx="inblock" test="$start+$lpp<=count($group)">
 <xsl:attribute name="break-before">page</xsl:attribute>
</xsl:if>

We have an 'if' statement wrapped around the page break instruction. This is just like the if in the table, if the specified number of rows has been met then insert a page break.

So thats fixed row enumeration, hope things are a little clearer. Next we'll add in the header for th invoices so we can then ensure we have a fixed layout per page of each invoice. Complete template, data and PDF are here.

Comments:

Tim: This really helps clarify the use of native XSL commands in the Word Template Builder. Regards, Rich Locus

Posted by Rich Locus on July 17, 2008 at 07:40 AM MDT #

The short name RAXINV should be ARXINV.

Posted by Steve on September 06, 2008 at 07:28 PM MDT #

Steve, not in my master instance. You might be correct for R12 thou. Tim

Posted by Tim on September 07, 2008 at 09:43 AM MDT #

Hi Tim, This doesn't work if some the line descriptions are long and wraping over to the next line.

Posted by BB on February 09, 2009 at 09:43 PM MST #

Tim, I opened a TAR at oracle and they pointed me to your Blog. I have the blank page issue for my .RTF template report But my report has multiple Groups. ORG --> Customer --> Transaction...... Can we use the same logic for multiple groups as well.How do we count the no of records in that case?I am not able to arrive at the RESET/COUNT logic I appreciate you help. Thanks, Venkat

Posted by Venkat on February 23, 2009 at 04:25 AM MST #

Hey Tim, BI Ver: 10.1.3.3.2 I am using this logic to page my records across multiple pages, but I have one issue. I do not show borders around the cells and so when the page break hits for the table it does not put a bottom border on the table or a top border on the next page. How would I get the table to print the bottom border for the last record and first record on every page? I am using a combination of node levels to give me the data for each line and group by it. <?xsl:variable xdofo:ctx="incontext" name="bu_group" select="../../../PYMNT_BU"/> <?for-each:$bu_group?> <?for-each:PYMNT_ADV?> <?PAY_DOC_ID?> <?for-each:PYMNT_MSG?> <xsl:choose><xsl:when test="LINE_COUNT>$first_rec and LINE_COUNT mod ($no_of_lines_per_page+1) != 0"> <?PYMNT_MESSAGE?></xsl:when><xsl:otherwise<xsl:attribute name="break-before">page</xsl:attribute></xsl:otherwise></xsl:choose> <?end for-each?> <?INVOICE_ID?> <?PAID_AMT?> <?end for-each?> <?DESCR?> <?PHONE?> <?BU_TOTAL?> <?end for-each?> I then use a recursive template to pad the remaining rows with a blank cell to print a full page of info. Everything works great except the borders on page breaks. Any help you can provide would be appreciated. Thanks, Tyler

Posted by Tyler Lawrence on March 31, 2009 at 04:24 AM MDT #

thanks for the template. I am trying this template and uploaded the same xml. I am receving the error saying "Variable Not Defined : 'invLines'

Posted by Ram on April 06, 2009 at 09:49 AM MDT #

Hi From Spain! Tim your blog is really amazing. I am a Newbie that need some help... I'm trying to create a rtf template for to print checks in cart format,(sorry for my english I hope to be clear), using the standar xml that oracle provides for Payments Formats. The matter is that I'm not printing in a blank page so I had to limit the number of rows of the section that contains the details of payments documents inside the outbound payment, this means that althougt I have 2 or 6 row os payments document I have always to fill with empty rows till 10 rows so the total section fits in the correct row of the page the other condition is that I have the maximum of 10 rows in this frame but this is solved with the example that you provide. I hope I hhad explained well , and you can help me , in any case if you want to give me your mail I can send you my template. Thanks a lot! Cheers!

Posted by Jeroni on May 09, 2009 at 02:59 AM MDT #

Hi From Spain! Tim your blog is really amazing. I am a Newbie that need some help... I'm trying to create a rtf template for to print checks in cart format,(sorry for my english I hope to be clear), using the standar xml that oracle provides for Payments Formats. The matter is that I'm not printing in a blank page so I had to limit the number of rows of the section that contains the details of payments documents inside the outbound payment, this means that althougt I have 2 or 6 row os payments document I have always to fill with empty rows till 10 rows so the total section fits in the correct row of the page the other condition is that I have the maximum of 10 rows in this frame but this is solved with the example that you provide. I hope I hhad explained well , and you can help me , in any case if you want to give me your mail I can send you my template. Thanks a lot! Cheers!

Posted by Jeroni on May 09, 2009 at 03:00 AM MDT #

Hi, I want to break page if the next group does not fit in the page. I tried to put my table in one cell, and it works for most part, but if the data on first page has 40 records, the first page comes out blank. Now I am trying to create conditional page break. The issue I have is I am trying to reset my counter at the top of every page. I tried the following, but not working. Any help will be appreciated. How do I reset counter when a new page is started. I tried to create this variable But when I try to get value of this variable, it doesn’t work. Thanks, Ravin L. Gogri

Posted by Ravin on June 22, 2009 at 02:08 AM MDT #

Hi, Thanks for providing lot of information. As mentioned in http://blogs.oracle.com/xmlpublisher/2007/03/anato my_of_a_template_i_fixed.html 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. Is there any example available for second feature. " 2. 'Filler' space for lines, because that last page may only have 3 lines but you want to maintain the layout" We need to implement this feature. Thanks for any help... Savitha

Posted by savitha on June 23, 2009 at 06:05 PM MDT #

Hi we have customised the Invoice Print to have our logos on it.How do you attach an XML invoice print in R12 within AR module?? Cheers sajid

Posted by sajid khan on July 01, 2009 at 02:42 AM MDT #

hi, Ur reply was good , could u please tell me the template for the same.

Posted by Divya on July 06, 2009 at 05:14 PM MDT #

Hi Tim, If you wanted to have a set number of rows for page 1, set by using "xsl:variable name="lpp" select="number(15)"/", but page 2 through the final page you wanted 20 rows, how would you set this after the initial page break? My latest attempt was to use set-get method for the variable lpp and re-setting it after the page break to 20, but then my line numbering starts at 21 instead of 16 on the second page. Do you have any suggestions or examples for this? Thank you! Cathy

Posted by Cathy Mello on July 20, 2009 at 05:16 AM MDT #

You mention that the LinesTreeVariable will not be be efficient with large XML file since the variable reads the entire structure into memory. How can you perform the same fixed row enumeration for large files? Assuming breaking the large file into smaller ones is not a option.

Posted by Pete on November 09, 2009 at 07:38 AM MST #

Ho to use a variable set dynamiccaly based on certain condition instead of 15 on above code,using getvariable method. Please reply asap. Regards, Manish Gupta

Posted by Manish Gupta on November 19, 2009 at 06:38 PM MST #

Hi Tim, I have used the similar concepts and created rtf template,when tested from rtf template builder tool,it is working fine and diplaying the report as expected. But when upload to Peoplesoft PIA,Report defination and try to run from Peoplesoft front end,it is not generating report output as expected,meaning it is not populating the table at all, (which is was showing and populating when tested from template builder). Please revert its solution as its really very urgent for me to implement and deliver. Thanks in advance. Regards, Manish Gupta

Posted by Manish gupta on November 19, 2009 at 09:09 PM MST #

I am trying to customize our Oracle Receivables invoice program for Release 12.0.6. I am modifying the seeded RAXINV.rdf because I need to add three fields into the query. I am adding the three columns in the data model and the Common Query user parameter. I am planning on using BIP to customize the layout. The issue I have with modifying the custom RAXINV.rdf is this. Everytime I modify the data model and the COmmon Query parameter, some of the object names change by appending a "1" to the object name (i.e. BILL_CUST_NAME become BILL_CUST_NAME1). Is there a better way of customizing the invoice? I would like to by pass Oracle Reports if at all possible. Thanks. More info that might help: I am using the following versions: Oracle Reports 10g (ORACLE Server Release 10.1.0.4.2) RAXINV.rdf 120.9.12000000.2

Posted by Michael on January 20, 2010 at 07:26 AM MST #

bb, Jeroni, Cathey Mello, I have a post on my blog for the long description and blank rows to maintain preprinted Stationary. But it will not have all the XSL tags Tim used in this post. I will soon update my post with these new XSL tags which should make more easier to maintain. Otherwise my logic is also similar to the one Tim explained here and it should take of other issues mentioned in the comment. Thanks AK Lakshmanan

Posted by Lakshmanan on September 14, 2010 at 11:15 PM MDT #

Hi Tim, The item descriptions are long and wraping over to the next line, so the continue word or the rest of the body does not print accordingly. Kindly suggest if you have any idea or throw some light to resolve this issue. Appreciate your time Thanks

Posted by KP on September 20, 2010 at 07:58 AM MDT #

Hi , I am getting error XPathException: Variable not defined: 'group' when i use the below syntax in template - The XML that i am using is - 1009 24-AUG-2010 1005 24-AUG-2010 Please help.

Posted by Akash on September 29, 2010 at 10:50 PM MDT #

Is there any example available for the feature. 'Filler' space for lines, because that last page may only have 3 lines but you want to maintain the layout" Please reply asap..urgent

Posted by rana on October 20, 2010 at 06:04 AM MDT #

hi the template path not opened and click here path also not opened

Posted by guest on May 09, 2011 at 04:31 PM MDT #

Hi Tim - the FixedRow.zip is no longer on the website. Can you send it to me? Thanks!

Posted by guest on May 17, 2011 at 08:48 AM MDT #

Hi Can you send the fixedrows.zip to my account ale_novelli@hotmail.com. Thanks in advance

Posted by Alex on May 20, 2011 at 02:48 AM MDT #

Post a Comment:
  • HTML Syntax: NOT allowed
About

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!

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today