Skip to Content
Technical Articles
Author's profile photo Alwin van de Put

Adobe Forms – Subtotals on each page

The goal is to generate in a PDF document a subtotal on each page in case the document has multiple pages. The PDF Form is designed using Adobe LiveCycle Designer (transaction SFP).

Scenario’s

  1. There is only one page, no subtotals needed.
  2. There are more than page, subtotals are needed.
    Pages with only items contain a “Previous page subtotal” and a “Bottom page subtotal”.
    1. The End block is pushed to the next page to keep the lines of the End Block together, so the last page does not contain items. The “Previous page subtotal” is not needed on the last page, because the last page does not contain items.
    2. The End block is not pushed to the next page, the last page also contains items, so the last page does contain “Previous page subtotal”.

Items

The form contains a table called “ITEMS” which contain the sales order items. Each line contains the field “TOTAL_AMOUNT”, which is the Nett total amount of the line. The subtotals have to be calculated based on this field.

Masterpages

The layout of the first page differs from the next pages, so there are 2 master pages. A “First page” and a “Next page”. The First page contains only a “Bottom page subtotal”. The Next page contains a “Previous page subtotal” and a “Bottom page subtotal”.

The “Bottom page subtotal” is sum of the “Previous page subtotal” plus the Total amounts of the Sales order items of the current page.

Subtotal Sub forms and Amount calculation

“Bottom page subtotal Sub form” on First and Next page – showing/hiding subtotal

The “Bottom page subtotal Sub form” contains all the layout elements of the subtotal like the Label, the Text field and some graphical lines. So when this sub form is hidden, than all these elements are hidden. Therefor the code below is placed in the calculation method of the “Bottom page subtotal Sub form”.

The Sub form is only shown when the “EndBlock” is not shown on the page, because the End block contains the total.

//Get current page
var CurrentPage = xfa.layout.absPage(this);

//Get current page - content page - fields
var FieldList = xfa.layout.pageContent(CurrentPage, "subform",false);
var FieldListLength = FieldList.length; 
        
//Check page contains EndBlock
var FieldListIndex = 0;
var Item;
var FoundInd = false;;
        
for (FieldListIndex; FieldListIndex < FieldListLength; FieldListIndex++) {
  Item = FieldList.item(FieldListIndex);
  if (Item.name === "EndBlock") {            
    FoundInd = true;
  }
}

//Hide subform if EndBlock found
if (FoundInd === true) {
  this.presence = "hidden";
}

“Bottom page subtotal amount” on First page – calculation

The “Bottom page subtotal” on the first page does need to read the “Previous page subtotal”, because there is no Previous page.

So it searches for all “field” elements and than sums all “TOTAL_AMOUNT” fields. To overcome rounding issues all amounts are first multiplied by 100 and after that divided by 100.

//Get current page
var currentPage = xfa.layout.absPage(this);
var currentPage_Index = currentPage.toString();

//Sum TOTAL_AMOUNT fields
var oFields = xfa.layout.pageContent(currentPage, "field"); 
var nNodesLength = oFields.length; 
var oTotalAmountFloat = Number(0);

for (var nNodeCount = 0; nNodeCount < nNodesLength; nNodeCount++) {
  if (oFields.item(nNodeCount).name == "TOTAL_AMOUNT") {            
    oTotalAmountFloat = ((oTotalAmountFloat * 100) + 
      (Number(oFields.item(nNodeCount).rawValue) * 100))/100;
  } 
}

this.rawValue = Number(oTotalAmountFloat);

“Previous page subtotal Sub form” on Next page – showing and hiding the subtotal

The “Previous page subtotal Sub form” is only needed when the current page contains Sales order items. This is check by the name of the “TOTAL_AMOUNT”.

//Get current page
var CurrentPage = xfa.layout.absPage(this);

//Get current page - content page - fields
var FieldList = xfa.layout.pageContent(CurrentPage, "field",false);
var FieldListLength = FieldList.length; 
        
//Check for a Sales order item line
var FieldListIndex = 0;
var Item;
var FoundInd = false;;
        
for (FieldListIndex; FieldListIndex < FieldListLength; FieldListIndex++) {
  Item = FieldList.item(FieldListIndex);
  if (Item.name === "TOTAL_AMOUNT") {            
    FoundInd = true;
  }
}

//If no Sales order item line, than hide Previous page subtotal
if (FoundInd === false) {
  this.presence = "hidden";
}

“Previous page subtotal amount” on next page – calculation

The “Previous page subtotal” shows the “Bottom page subtotal” of the previous page. So the code first gets the “Previous page” and than the “Bottom page subtotal”.

The third parameter of method pageContent has value “true” to get the elements of the Master page instead of the Content page.

//Get previous page
var CurrentPage = xfa.layout.absPage(this);
var CurrentPage_Index = Number( CurrentPage.toString() );
var PreviousPage_Index = CurrentPage_Index - 1;

//Get Bottom page subtotal
var FieldList = xfa.layout.pageContent( PreviousPage_Index, "field", true);
var FieldListLength = FieldList.length; 

for (var FieldListCount = 0; FieldListCount < FieldListLength; FieldListCount++) {
  if (FieldList.item(FieldListCount).name == "PageSubtotalAmount") { 
    this.rawValue = FieldList.item(FieldListCount).rawValue;
  }        
}

“Bottom page subtotal next page” – calculation

First the “Previous page subtotal amount” on the current page is determined. Method pageContent has as third parameter the value “true” to get the elements of the Master page instead of the Content page.

After that the TOTAL_AMOUNT of the current page is summed. Method pageContent has as third parameter the value “false” to get the elements of the Content page.

//Get current page
var CurrentPage = xfa.layout.absPage(this);
        
//Get current page - master page - fields
var FieldList = xfa.layout.pageContent(CurrentPage, "field",true);
var FieldListLength = FieldList.length; 
        
//Get Previous page subtotal
var FieldListCount = 0;
var PreviousPageSubtotal = 0;        
for (FieldListCount; FieldListCount < FieldListLength; FieldListCount++) {
  if (FieldList.item(FieldListCount).name == "PreviousPageSubtotalAmount") { 
    PreviousPageSubtotal = +FieldList.item(FieldListCount).rawValue;
  }
}
        
//Calculate current page total
var TotalAmount = PreviousPageSubtotal * 100;
var FieldListIndex2 = 0;
var Item;
        
//Get current page - content page - fields
FieldList = xfa.layout.pageContent(CurrentPage, "field",false);
FieldListLength = FieldList.length; 
        
//Sum total amounts (X 100 to overcome decimal problems)
for (FieldListIndex2; FieldListIndex2 < FieldListLength; FieldListIndex2++) {
  Item = FieldList.item(FieldListIndex2);
  if (Item.className === "field" && Item.name === "TOTAL_AMOUNT") {            
    TotalAmount += Item.rawValue * 100;
  }
}
this.rawValue = TotalAmount / 100;

Author: Alwin van de Put

Assigned Tags

      4 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Swati Singh
      Swati Singh

      Hi Alwin,

      Thank you for this blog. It has been really helpful. I used the same logic to get the next page subtotals and previous page subtotals. Everything is working fine.

      I am a little confused about where to put the EndBlock though. Should it come on the first master page?

      Regards,

      Swati

      Author's profile photo Alwin van de Put
      Alwin van de Put
      Blog Post Author

      Hello Swati,

      Thank you for your feedback.

      The reason to choose for the EndBlock in the Content page in stead of the Master page is for two reasons.

      1. The customer wanted the EndBlock right after the last line of the items.
      2. The EndBlock had about 8 lines because it contained the Net amount, Vat (multiple lines, 0%, 6% and 21%, Gross amount and some extra lines for the payment terms and some other data. Reservering a place holder on the Master page would take to much space, so the space for the content page would become too small.

      Regards,

      Alwin

      Author's profile photo Trapti Jain
      Trapti Jain

      Hi Alwin,

      Thank you for this blog. It has been really helpful. I have one doubt, the previous page subtotal calculation block is not working properly. I wrote that block in calculation method but there I was not able to access previous page index. So, I wrote it in Initialization method. Now, previous page index is coming but I am not able to fetch the content of the previous page.

      Could you please help me how to solve this issue?

      Thankyou in advance!

      Regards,

      Trapti

      Author's profile photo Alwin van de Put
      Alwin van de Put
      Blog Post Author

      Hello Trapti,

      It hard to solve the issue without having the code.

      I wrote just a simple example and uploaded it here:
      https://github.com/alwinvandeput/ZAFDS_ADOBE_FORM_DEMO_SUBTOTA

      First you have to check whether the previous page can be determined:

      //Get previous page
      var CurrentPage = xfa.layout.absPage(this);
      var CurrentPage_Index = Number( CurrentPage.toString() );
      var PreviousPage_Index = CurrentPage_Index - 1;
      
      this.rawValue = PreviousPage_Index.toString();
      

      See field: Prev.page index in the picture below.
      This should have value 0 on page 2 and value 1 on page 3.

      Page 2 reads total op page 1 (=master page 1)

      Page 3 read total of page 2 (=master page 2)

      Than you can check whether you can read the fields. The fields are read from the master page.

      The Subtotal amount field on the all master pages must have the name PageSubtotalAmount.

      I added also field PrevPageFieldListLength to check whether the fields can be read.

      On page two it show 1, because I have 1 "field" on master page 1 and on page three it shows 4, because I have 4 "field"s on master page 2.

      //Get previous page
      var CurrentPage = xfa.layout.absPage(this);
      var CurrentPage_Index = Number( CurrentPage.toString() );
      var PreviousPage_Index = CurrentPage_Index - 1;
      
      //Get Bottom page subtotal
      var FieldList = xfa.layout.pageContent( PreviousPage_Index, "field", true);
      var FieldListLength = FieldList.length;
      
      this.rawValue = FieldListLength.toString();
      

      It this one does not work, than it could be that you are not using a "field" (text field) but a different kind of adobe UI component. See Adobe help for method pageContent:

      https://help.adobe.com/en_US/livecycle/10.0/DesignerScriptingRef/WS92d06802c76abadb-3e14850712a151d270d-7a3f.html

      I hope this helps.

      Kind regards, Alwin.