Stefan Cameron on Forms
Building intelligent forms using Adobe LiveCycle Designer

Expandable Table with Totals

It seems that calculating totals in an expandable table with a dynamic/repeatable row is a hot topic lately so I thought I would post a tutorial on how to build a simple table which represents a purchase order where you can add and remove line items and various totals are automatically calculated.

Before we get started, you’ll need Designer 7.1 and Acrobat/Reader 7.0.5 at minimum to run through this tutorial. I will be using Designer 8.2 and Acrobat/Reader 9.0 to do the tutorial so it’s possible some of the UI may have changed slightly since the 7.1/7.05 versions.


Creating the Table

The first step is to drag a Table object from the Object Library palette’s Standard tab into your form. When you drop it, the Insert Table wizard appears. Set it to include 5 columns, 1 body row and header and footer rows:

Headers and Footers

Double-click on the first “Header” cell and set the text/caption to “#”. This will be the dynamic index column. Set the remaining headers as follows: “Item”, “Quantity”, “Cost”, “Total”.

In the footer, we only need two cells: One with a caption that reads, “Grant Total:”, and the other for the calculated grand total. To start, select the first 4 footer cells by Ctrl-Clicking each one:

Then, with the cells selected, click on the “Merge Table Cells” button in the Object palette (highlighted in yellow in the image below):

The 4 cells will merge into one and you can then double-click the text to change it to “Grand Total:”. While you’re editing the text, use the Paragraph palette to align it to the right.

We’re pretty much done with the header and footer row except for the grand total cell but we’ll come back to that after the body row has been defined.

Body Row

What we want for the body row is a text/read-only cell for the row number, a drop down list for selecting items, a numeric cell for the quantity, a numeric/read-only cell for the cost (which will be set depending on the selection in the item list) and a numeric/read-only cell for the calculated total (quantity * cost) for the row.

The first thing to do is to rename the “Row1″ body row to “Item” and set it to repeat for each data item by selecting Row1 from the Hierarchy palette and setting its “Object palette > Binding tab > Name property” to “Item”, its “Default Binding” property to “Normal” and checking its “Repeat Row for Each Data Item” property to enable it to repeat so that the table can expand.

Row Number Cell

While this may sound complex, it’s actually quite easy to achieve. Since the Item body row will repeat, it will have an index and the index will be zero-based. This means our row number is simply the index of the cell’s parent (Item body row) + 1.

Drop a text field from the Object palette onto the first cell in the Item row. This will change the cell’s type to a text field. Set its name to “ItemIndex” (not just “index” because it’ll cause conflicts with the Item row’s index property), its “Object palette > Binding tab > Default Binding property” to “None” (since we don’t need the index in the submitted data — it’s just for show, after all) and its “Object palette > Value tab > Type property” to “Calculated – Read-Only”.

Finally, using the Script Editor, set its Calculate event to the following JavaScript code:

(this.parent.index + 1) + ".";

If we preview the form at this point, we’ll see that the first and only Item row has a row number of “1.”:

Item Name and Cost Cells

The next cell is the item name. This will be a drop down list with a few items to choose from which have associated values that we’ll use to set the cost field depending on the selected item.

Drop a down down list from the Object Library onto the second cell in the Item row. Set its name to “ItemName” (not just “name” because it’ll cause conflicts with the Item row’s name property) and add some items to it using the Object palette’s Field tab. The following image shows that I’ve populated my list with 3 items:

An important thing to note here is that we did not associate values as costs to each item. It would’ve been convenient to store them like that however if we had, the item’s name would’ve shown-up as the cost in the submitted data which is not the intention. When data is submitted, we want the item’s name (e.g. “Helmet”) to show-up as the ItemName data.

With the ItemName cell defined, we need to setup the Cost cell so that we can set its value to the value associated with the selected item.

Drop a numeric field from the Object Library onto the 4th cell (the 3rd cell is for quantity) in the Item row. Set its name to “Cost”, its “Object Palette > Binding tab > Data Format property” to “Float”, its Value Type to “Read-Only” and its Display Pattern to “num{($zzzz9.99)}” (without the double-quotes).

Now set the following JavaScript code as the Change event for the ItemName drop down list:

switch (xfa.event.newText)
{
    case "Helmet":
        Cost.rawValue = 45.00;
        break;

    case "Pedals":
        Cost.rawValue = 150.00;
        break;

    case "Wheel":
        Cost.rawValue = 225.00;
        break;

    default:
        // unknown item
        Cost.rawValue = 0;
        break;
}

This simple script looks at the new selection in the ItemName list and sets the Cost field’s value accordingly.

At this point, we preview the form and choose “Pedals” as the item, the Cost cell will get a value of “150″ which will be displayed as “$150.00″ because of the display pattern we set on the Cost field earlier:

Quantity Cell

With the ItemName and Cost cells defined, we can now define the Quantity cell. This one is quite simple: Drop a numeric field onto the 3rd cell in the Item row. Set its name to “Quantity” and its default value to 1.

Total Cell

The last cell in the Item row is the one what will show the total for that Item which is “Quantity * Cost”. This is another easy one: Drop a numeric field onto the 5th cell in the Item row. Set its name to “Total”, its Default Binding to “None” (no need to store calculated values in the data), its Value Type to “Calculated – Read-Only”, its Display Pattern to “num{($zzzz9.99)}” (without the double-quotes) and its Calculate event to the following FormCalc code:

Quantity * Cost

That’s it! FormCalc is great for spreadsheet-like calculations and in FormCalc, the “rawValue” property is implied so you don’t need to specify it like in JavaScript.

At this point, previewing our form and choosing “Pedals” as the item shows a calculated total of “$150.00″ for that item:

Footer Grand Total Cell

Now that the Item body row is complete, we just have a couple of things left to do. First, we need to setup the Grand Total field in the footer row which will display the grand total of the order. This field will be a numeric/read-only field which will calculate the sum of all Total fields in all Item rows that exist. This may sound complicated but once again, FormCalc makes this easy-as-pie.

Drop a numeric field onto the 5th (or 2nd or last) cell in the footer row. Set its name to “GrandTotal”, its Default Binding to “None” (no need to store calculated values in the data), its Value Type to “Calculated – Read-Only”, its Display Pattern to “num{($zzzz9.99)}” (without the double-quotes) and its Calculate event to the following FormCalc code:

Sum(Item[*].Total)

You’re probably wondering what the “[*]” notation means. Put simply, it’s like a wildcard for the index of the Item row and it tells the Sum function to get the value of the Total field in all instances of the Item row and calculate their sum.

At this point, if we preview our form and choose “Pedals” as the item, the total and grand total values are automatically calculated:

Adding/Removing Items

Last but not least, we need a mechanism to add and remove items in the table. Since we had the Item row repeatable, this will be done using the Instance Manager associated with the Item row.

To start, place two buttons on the form and name them “Add” and “Remove”. Set their captions to “Add” and “Remove” as well.

Using the Script Editor palette, set the Add button’s Click event to the following JavaScript code:

Table1._Item.addInstance(0);

This script will add a new instance of the Item row to the table. Now set the Remove button’s Click event to the following JavaScript code:

if (Table1._Item.count > 1)
    Table1._Item.removeInstance(Table1._Item.count - 1);

This script will first make sure that there are at least 2 rows (since the minimum row count is 1) and if so, will remove the last row that was added to the table. Note the use of the underscore prefix to access the Item row’s Instance Manager.

Previewing the form at this point will now allow you to add/remove rows and you’ll see that the totals are all being calculated automatically as you choose items and set quantities:

Sample Form

Here is the sample form for the tutorial. It’s the solution so try not to look at it until you’ve run through the tutorial on your own…

Download Sample [pdf]

Sample Minimum Requirements: Designer 7.1/Acrobat 7.0.5

Sample Form with Page Totals

Reader Sandeep Goli asked an interesting question: How would one show a page total?

This can be done by adding first allowing the table’s content to break across pages by checking the “Object palette > Table tab > ‘Allow Page Breaks within Content’ property”. The next step is to add another footer row to the table, located prior to the existing “FooterRow” row object (select the FooterRow row, duplicate it, rename it to “PageFooter”, rename the field inside to “PageTotal” and drag it up above the FooterRow object in the Hierarchy palette), and set it up to be included on subsequent pages as well as a the final page (rather than just the final page) using the “Object palette > Pagination tab > ‘Include Footer Row in Subsequent Pages’ and ‘Include Footer Row in Final Page’ properties”. This will cause the footer row to appear at the bottom of all pages, including the last page, as the table breaks across pages.

The final step in making this work is to set script in the new footer row’s Layout:Ready event. (If you duplicated the FooterRow, make sure you remove its Calculate script.) In this event, you can use APIs from the Layout Model which will let you determine the set of table “Item” rows that are on a given page — that being the page on which the PageTotal field was rendered:

xfa.layout.page(object)

will return the 1-based page number on which that object (field, subform, etc.) was rendered and

xfa.layout.pageContent(zeroBasedPageIndex, type, 0)

will return a list of all form objects of the specified type (a string, such as ‘subform’, ‘field’, ‘draw’, etc.) on the specified 0-based page index.

The following script finds all Item rows on the same page as the rendered PageTotal field, sums their Total child field values and sets that number as the PageTotal’s value:

// get a list of all subforms rendered on the same page as this field
var pageSFList = xfa.layout.pageContent(xfa.layout.page(this) - 1, "subform", false);
var pageTotal = 0;
// for each subform named "Item", sum its "Total" field value
for (var i = 0; i < pageSFList.length; i++)
{
    var sf = pageSFList.item(i);
    if (sf.name == "Item")
        pageTotal += sf.Total.rawValue;
}
// set this field's value to the sum of all Item rows on this page
this.rawValue = pageTotal;

Download Sample [pdf]
Download Sample Data [xml]

Sample Minimum Requirements: Designer 8.0/Acrobat 8.0. This is due to bug fixes with table footer placement which are available only as of Acrobat 8.0.

Sample Form with Row Remove Button

Reader Susila asked an interesting question: How do you remove a specific row using a “remove” button in the row to be removed?

This is done simply by inserting a column to the left of the ItemIndex column in the table and setting the cell’s type to a button. The button’s Click event is then set to remove the row to which it belongs.

The trick lies in writing the script in such a way that it automatically relates to (i.e. removes) the row instance to which it belongs. This is achieved by retrieving the instance index of the row to which it belongs and using that as the parameter supplied to the Item row Instance Manager‘s removeInstance([index]) method. The method expects a zero-based index and that’s what the index property gives you:

// JavaScript:
this.parent.parent._Item.removeInstance(this.parent.index);

The script above first accesses the button’s grand-parent (Table1). Then it gets the Instance Manager for the Item row and executes its removeInstance() method providing it with the index property value of its (the button’s) parent (Item row instance). By accessing parent objects, you ensure that you’re doing things with relation to the button that was clicked and, therefore, the row that contains the button.

Note that simply removing the row won’t necessarily update the ItemIndex field in other row instances that remain. If your form’s Target Version is set to Acrobat/Reader 7.0.5, you will have to explicitly tell the form to re-execute calculations. This issue was addressed in Acrobat 8.0+ so there’s no need to do this if your form targets a later version of Acrobat/Reader.

Download Sample [pdf]

Sample Minimum Requirements: Designer 7.1/Acrobat 7.0.5

Further Improvements

As I mentioned earlier, this is a simple dynamic table with a repeatable row. It demonstrates only the basics. You could enhance it further by including row shading options, validations, better formatting (font and paragraph), smarter add/remove buttons (e.g. put the remove button on the Item row in order to delete that specific row instead of always deleting from the end), put an insert button on the Item row in order to insert new items instead of always appending to the end of the list, etc.

For an advance sample, you should check-out the “Dynamic Interactive Purchase Order” sample that ships with Designer. Depending on how Designer was installed (either with Acrobat, with LiveCycle or standalone) and whether it was on Win 2k, XP or Vista, you should be able to find it in one of the following folders:

C:\Program Files\Adobe\LiveCycle ES\Workbench ES\Designer ES\{version}\EN\Samples\Forms\Purchase Order\Dynamic Interactive\Forms

C:\Program Files\Adobe\LiveCycle Designer ES\{version}\EN\Samples\Forms\Purchase Order\Dynamic Interactive\Forms

C:\Program Files\Adobe\Acrobat\Designer\{version}\EN\Samples\Forms\Purchase Order\Dynamic Interactive\Forms

(Note that in Vista, “Program Files” changes to “Program Files (x86)”.)

Updated Oct 2, 2009 — Added page totals sample.

Updated Oct 2, 2009 — Added row remove button sample.


Posted by Stefan Cameron on February 25th, 2009
Filed under Data Binding,Designer,FormCalc,Scripting,Tables,Tutorials,XFA
Both comments and pings are currently closed.

107 Responses to “Expandable Table with Totals”

  1. Justin on February 26th, 2009

    Nice tutorial, really well made. I’ve found it almost impossible to find any good Livecycle documentation that doesn’t cost a bundle.

    I noticed you went to Ottawa Winterman, are you actually in Ottawa?

  2. Stefan Cameron on February 26th, 2009

    Justin,

    Thanks for the feedback. I’m glad you found my tutorial useful!

    Yes, I’m based in Ottawa. Did you run the Winterman as well?

  3. Omer on February 27th, 2009

    Thanks Stefan. I used it to create a sample form for an SME after localized currency field.

    After distributing it with Acrobat 9, I added three rows and then submitted. I received “Submitting Completed Form” response email:

    “Instructions to add this form to a responses file:
    1. Double-click the attachment.
    2. Acrobat will prompt you to select a responses file.”

    when double-click the attached form, the message is:
    “The fields in the file ‘form_distributed.pdf’ do not exactly match the fields in the template in the specified responses file.”

    Is there a way to expand form_responses.pdf file’s fields according to response data?

    Btw, Forms > Manage Form Data > Export Data works well.

    Your blog saves me lots of time. Last time, I used your MAX 2007 tutorials about Instance Manager. Thanks for sharing.

  4. Cristi on February 28th, 2009

    Hi,

    Very nice and useful article. Thanks for posting it.

    I am having some trouble with an expandable table and I was wondering if you might have some ideas on what could cause the behavior and hopefully how I could fix it…

    I have a table with 1 row and Add Row and Delete Row buttons.

    Everything works fine, except that when a user puts a lot of text in one of the cells, the header row shows on one page, and depending on how much text there is in the cell, the row with the text shows either on the next page, with header row, or on the third page, while on the second page one more instance of the header row is shown.

    Any ideas what could cause this behavior and how I could fix it?

    I’ve been struggling with this for a few days now and couldn’t find any documentation that would show how to make the dynamic rows to stick together with the header row and if overflowing to behave exactly like a text field (splitting the row and displaying on the next page).

    Any ideas / suggestions are welcome.

    Thanks,
    Cristi

  5. Cristi on February 28th, 2009

    Hi,

    I just discovered the problem with my dynamic Table when it expands to fit the entire value.

    The issue is that I have a drop down box in the row, and the drop down box doesn’t know how to grow.

    Any ideas how I could make it work?

    Thanks,
    Cristi

  6. Arnold Love on March 4th, 2009

    Hello,

    I’m very new to LiveCycle so this is a great tutorial with guided steps has been the most helpful by far. I value and thank you for your work .

    I’m having trouble with the ADD & DELETE Button.
    I managed to get all the components into my Adobe LiveCycle ES 8.2 step by step.

    When I goto my PDF preview the ADD feature will not add rows therefore I can’t delete.

    I did download your sample and your sample works great.

    Your help with a resolution will finalize a form I’m working on.
    Thank You.
    Arnold Love

  7. Stefan Cameron on March 4th, 2009

    Omer,

    I’m glad you found this post useful. I’m not 100% certain what happens when you distribute a form via Acrobat Pro. It sounds like Acrobat is having a hard time negotiating the data bindings in the form.

    If your goal is to capture data filled in the forms and submitted to you via email, you should put an email submit button on your form. Clicking on this button will save the filled data as an XML data file and attach it to a new email in the user’s default email application. They can then submit that XML data file to you via email.

    On the receiving end, you would first save the XML data file to your local file system. Then you would open the empty form in Acrobat and choose “Forms > Manage Form Data > Import Data”. Select the XML data file in the dialog that appears and the data submitted to you should be loaded into the form, thus reproducing the form just like it was when the user filled it out. You can then save a copy of the form including the XML data for your records.

  8. Stefan Cameron on March 4th, 2009

    Cristi,

    Unfortunately, I think you’re hitting a couple of issues:

    1. You’re correct: The presence of an object that cannot break across pages (e.g. drop down boxes) in the row will prevent the row from breaking. Also, there are many other factors that come into play when the XFA processor attempts to break the row (whether all ancestors allow breaking and whether a common break point can be found across all cells in the row to name a few).
    2. Even if you removed the drop down list, you won’t get the row to break, likely due to issues related to table rendering. There have been many fixes made in this area however they won’t be available until a future release.

    If you really need the cell to break, I can only think of one way to do it however it would be heavily scripted. You could use the script I built with my colleague Stephanie which auto-splits text across multiple text fields and, upon breaking, inserting a new instance of a table row with just the text field in the right cell and continuing to fill it with the data. That being said, it would be difficult to achieve and likely wouldn’t give you the appearance you’re looking for.

  9. Stefan Cameron on March 4th, 2009

    Arnold Love,

    There are at least a couple of things that could be happening:

    1. Are you certain you’re previewing your form as a Dynamic PDF? If not, you won’t be able to add/remove rows even if your script is correct.
    2. Is there an error output to the JavaScript Console in Acrobat when you click the Add button? If so, it would indicate an error of some kind with the Add button’s Click event script.
  10. Kurt Renfro on March 5th, 2009

    Floundered for days trying to figure this out on my own. Your tutorial is a godsend.
    In the tutorial the rows are numbered: 1., 2., 3., etc.
    Is there a way to change the numbering to 1.0, 1.1, 1.2, etc?

  11. Stefan Cameron on March 5th, 2009

    Kurt Renfro,

    I’m glad you found it so useful!

    To change the numbering sequence to “1.0, 1.1, 1.2…”, just set the Calculate script on the ItemIndex cell to the following:

    // In JavaScript:
    "1." + this.parent.index + ".";
  12. Kurt Renfro on March 6th, 2009

    Thanks for answering my previous post.

    The script you provided works perfectly, however, I forgot to mention that the numbering sequence needs to start at 1.1.

    The table I’m creating will be used as part of a maintenance procedure and all numbering needs to be in outline form.

    The way the table is structured, the first cell in the Header row is numbered 1.0. The first cell in the repeating “body row” needs to start at 1.1 with all subsequent repeated rows numbered 1.2, 1.3, etc.

    I tried altering the script to start the numbering sequence at 1.1 but can’t seem to figure it out.

    Thanks!

  13. Stefan Cameron on March 10th, 2009

    Kurt Renfro,

    Just add 1 to ‘this.parent.index’. That will give you a one-based number. Stick that next to ’1.’ and you’ve got your sequence…

  14. chuck becker on March 22nd, 2009

    great site, stefan! you have another fan (me:-). you knowledge and ability to communicate clearly are singular.

  15. Stefan Cameron on March 22nd, 2009

    chuck becker,

    Thanks Chuck! I appreciate the feedback.

  16. Nico on April 7th, 2009

    Hi stefan , how are you ?
    can you help me!!
    i have this problem,
    I want to render invisibile a button in every line of my table, I succeed to render invisibile the button in the header, but I do not succeed in the lines of my table. how I can make?
    thanks you

  17. Stefan Cameron on April 11th, 2009

    Nico,

    I’m assuming you’re wanting to make the button in each row invisible at some point after the form has been rendered (i.e. at run-time, not design-time) and that you’re using the table from the sample in this post which means the buttons you’re wanting to make invisible are in instances of the Items row in the Table1 object:

    var itemRows = Table1.Item.all;
    for (var i = 0; i < itemRows.length; i++)
        itemRows.item(i).Button1.presence = "invisible";

    The "all" property retrieves all existing instances of the Item object within Table1. The FOR loop then iterates through the returned array and sets the presence of a Button1 object inside the Item row instance to "invisible".

  18. Nico on May 6th, 2009

    Hello stefan , thanks for you respons.
    i have new problem
    have 2 tables.
    1 table have 10 rows , only rows have a button, on click create row in second table and assign in the field value the index the 1 table. excuse for my english.
    i use:
    Table1._Item.addInstance(0); for add row.

  19. Stefan Cameron on May 15th, 2009

    Nico,

    It sounds like you have 2 tables, Table1 and Table2, and when you click on a button in a row in Table1, you want to add a row with a field in Table2 where the field contains the index of the row pertaining to the button that was clicked in Table1.

    To do that, you would using this script in the button in a row in Table1, assuming Table2 has a repeatable row named ‘Item’ which contains a field named ‘indexField’:

    // JavaScript:
    var newRow = Table2._Item.addInstance(0);
    newRow.indexField.rawValue = this.parent.index;
  20. DavidScD on May 18th, 2009

    Hi Stefan,
    Thanks for all the helpful advise. I’ve created a dynamic form which needs several tables. The first table works fine using the row insert command you detail in the tutorial.. If I insert a second table (either in the same subform or by creating another subform) when I preview the form the insert command in Table1 adds rows overlapping on Table2. I’m relatively inexperianced in LiveCycle Designer so appologise if I’m missing the obvious!
    Your advise would be much appreciated.

  21. Stefan Cameron on May 25th, 2009

    DavidScD,

    I believe the issue here is that your tables are placed inside subforms that have positioned content instead of flowed content.

    In XFA forms, objects in flowed subforms flow “left to right, top to bottom” or simply “top to bottom” (depending on flow direction) when objects are added above them. Similarly, when adding rows to the first table, the table expands to fit the new rows however if the second table is positioned below it (rather than flowed below it), new rows will overlap the second table.

    To fix this, place both tables in the same subform, select the subform and then set the “Object palette > Subform tab > Content property” to “Flowed”.

  22. Penelope on June 8th, 2009

    Hi Stefan,

    I found your advices very helpful since then.Thanks!

    Anyways, I also need help on calculating total in expandable tables. I have 2 Tables (DetailTable & SummaryTable).
    Both are expandable and both have 2 columns:

    DetailTable= CODE1 & DURATION
    SummaryTable = CODE2 & TODAY

    In DetailTable, under CODE1 column user will select the acitivity code from dropdown list (MB, OC, SF, DM) and after selecting will input the time elapsed under DURATION (in hh:mm) column. User can input as many MB or SF & so on as he/she likes.

    In SummaryTable, the total time elapsed for EACH activity code that were input in the DetailTable will be calculated under TODAY column. This means that summation will only happen if the condition CODE1.rawValue = CODE2.rawValue is satisfied.

    Can you help me solve this problem? Thank you very much

  23. Stefan Cameron on June 8th, 2009

    Penelope,

    I thought a working sample might be easier than trying to explain in words.

    Basically, in the SummaryTable has a row for each type of activity and each row has a cell to contain the total time for a specific activity. The activity total cell has a Calculate script that finds all of the rows in the DetailTable that relate to a particular activity type and sum their related duration. The DetailTable then simply holds rows for each activity performed and a button uses the Instance Manager to add rows to it. The Calculation script in the SummaryTable creates a dependency on rows in the DetailTable such that adding/removing rows and changing activity durations effects a change in the SummaryTable.

    Note: I created this sample with Designer 8.2 and tested it with Acrobat 9.1.

  24. Penelope on June 9th, 2009

    Stefan,

    It worked! Eventhough I am using Livecycle 8.05. The SummaryTable can now calculate the sum for each activity. You got what I mean.

    Now one more thing, I noticed you use numeric fields for the Total and data is in integer/float format. My actual table has time for input and also for Total. How do I go around this? Addition of Total Duration in Time format? Note: Duration spans more than a day.

    Thanks a lot!

  25. Stefan Cameron on June 18th, 2009

    Penelope,

    Great! I’m glad I had understood your original problem.

    I didn’t bother with the time calculations since I didn’t know how complex they needed to be. All times can be represented by decimal numbers. For example, if all times are in hours, then there’s no need for actual time calculations, unless you want to display “25.5″ hours as “1 day, 1 hour and 30 minutes” or if you want users to enter times as “25:30″ (25hrs, 30min) instead of “25.5″.

    You’ll make things a lot simpler if you stick to decimals to represent time metrics but let me know if you need a few hints to do it the more complicated way.

  26. Penelope on June 19th, 2009

    You couldn’t be more right Stefan. I am actually making a form that has time input entered as “12:00″. In the DetailTable, one column is for TimeStart entered in “12:00″ and TimeEnd entered in “12:00″. The duration will be calculated between the two times by subtracting both time. I already got the subtraction but the result is in decimals 23.5 while I want the format still in “12:00″. Aint this complicated?

    To make it worse, in the SummaryTable the total duration for each specific activity must be added and the result is in “12:00″.

  27. Stefan Cameron on June 26th, 2009

    Penelope,

    Converting from decimal back to “12:00″ format isn’t difficult. If the difference was 23.5 and this represents hours, then “var h = floor(23.5);” is the number of hours and “var m = (23.5 – floor(23.5)) * 60;” is the number of minutes. Then you can just concatenate both results into a string: “var time = h + ‘:’ + m;”

  28. Penelope on June 29th, 2009

    Stefan,

    Does FormCalc support multiple lines code & variables?

    I have tried the code you gave me and put it under Calculate in FormCalc and an error occurred. What is wrong?

  29. Nidhi Jain on July 2nd, 2009

    Hi,

    I’ve a form in which a data connection is created thru a wsdl file. Now, although the response table contains 3 rows only one row(initial row count) is being displayed in the adobe pdf.

    Can you please tell me how to sort out the above problem.

    Thanks

  30. Ash on July 13th, 2009

    Hi Stefan,

    I have a dynamic form (repeatable) that has a TextField for users to input their Name. User can add multiple instances of the form. I want to be able to use the initial input and then prepopulate the Name TextField in all the additional instances that the user adds without the user having to input it manually everytime. Any suggestions?

    Thanks

  31. Stefan Cameron on July 13th, 2009

    Penelope,

    Yes, FormCalc supports variables and multiple lines of code. The code I gave you is in JavaScript. To get it to work, you have to set the Language property for the event to “JavaScript” (drop down list property on the upper right side of the Script Editor palette).

  32. Stefan Cameron on July 13th, 2009

    Nidhi Jain,

    This could be a number of things:

    1. The table row may not be repeatable (“Object palette > Bindings tab > Repeat Row for each Data Item”).

    2. The web service may not be returning multiple instances of the repeatable item.

    3. The row’s binding expression may not be using the right syntax (should end with “[*]” to indicate “all instances”).

    See if one of those could be the reason behind the issue.

  33. Stefan Cameron on July 17th, 2009

    Ash,

    When you add an instance, the Instance Manager‘s addInstance() method returns a reference to the new instance (a subform object that contains all of the fields within the new instance). You can then set properties of those fields in the new instance as you like.

    To accomplish what you would like to do, simply do

    // JavaScript:
    // add a new instance
    var newInst = _repeatableSubform.addInstance(0);
    // get value from first instance of 'myField' -- assuming there is a
    //  first instance that exists...
    newInst.myField.rawValue = repeatableSubform[0].myField.rawValue;
  34. Ash on July 20th, 2009

    Thanks Stefan.
    Alternatively, I achieved it by setting the (my)field property to global. Now I have another issue. I am trying to distribute and collect the filled forms but if the user creates multiple instances of the form (template) before submitting it, then as I try to compile it into the dataset, I get a message saying that some fields do not match with the template. If I ignore that and go ahead with compilation, then even though the returned form loads correctly, still I only see the values of first instance of the form in the summary. If I then export to CSV, I notice that fields of the second instance are repeated after that of first, on the same row, thus resulting in a long row of fields followed by a row of values under. What I would like to have is just one row of fields (that are in the original template) and then multiple rows of values under, for each instance that the user chose to create. Your help is greatly appreciated.
    My apologies if this is not the right forum for this query, kindly redirect.

  35. Stefan Cameron on July 29th, 2009

    Ash,

    I’m afraid I don’t quite follow what you’re trying to explain. Do you mean that when a user adds multiple instances of a subform and then submits the data, the submitted data doesn’t merge properly into your report form?

  36. Marni on August 5th, 2009

    Hi, I’m hoping you can help me. I’m new to Adobe form making but so far so good. I have one issue. I have a request on the form for a list of items with several columns of information. Name, vendor, sites, etc. When the form was created from a Word doc it automatically created the same number of rows to complete. If the user needs to have more rows how can I allow them to add more fields for this? Does this make sense? Thanks for your help.

  37. Ash on August 7th, 2009

    Stefan, that’s correct. The returned form’s data does not merge properly into the collection dataset. If I have say, 5 fields in the subform and user creates 3 instances before submitting, then I get 15 field/value pairs instead of 5 fields x 3 sets of values. To illustrate in a tabular format, I get 15 columns x 2 rows (including header row) instead of 5 columns x 4 rows (including header row). The dataset has only 5 fields defined so I get an error message stating that some fields of the returned form do not match with the template. Does that help? Thanks again for your replies.

  38. Stefan Cameron on August 13th, 2009

    Marni,

    I’m assuming that the rows created during the import from Word are duplicates (i.e. you have, say, 10 rows with the same columns/fields). What you would do to make the form dynamic is remove all but one row, make that row repeatable (as in my sample for this tutorial) and, perhaps, set an initial count of 10 rows to get 10 rows initially when the form is empty. Then you would add buttons to enable the user to add/remove rows (again, like the Add and Remove buttons in this tutorial). Finally, you should make sure that your form is saved/generated as a dynamic PDF; otherwise, dynamically adding/removing rows will not work.

  39. Stefan Cameron on August 18th, 2009

    Ash,

    Sorry for the delay. It sounds like there may be something wrong with the bindings in the form from which the data is being submitted.

    If you aren’t doing this already, you should try explicitly setting the field and subform bindings to ensure they are what you expect, rather than using “Normal” binding (“Object palette > Binding tab > Default Binding property”).

    If you want the following repeating data to be output:

    <group>
        <data1>value1<data1>
        <data2>value1<data2>
        <data3>value1<data3>
    </group>

    You would bind a repeatable subform to the “$.group[*]” elements (all instances of <group>) and you would bind the fields inside of it to “$.data1″, “$.data2″ and “$.data3″.

  40. Sean on August 18th, 2009

    Another gem, cheers Stefan!

  41. Geno on August 19th, 2009

    Read this if you can’t get the bloody row adding to work…

    http://forms.stefcameron.com/2006/07/24/previewing-as-dynamic-pdf/

    It may save you from going insane.

  42. Ash on August 19th, 2009

    Stefan, I am not quite sure if we are talking the same thing. I will try to use your table as example. Say, I want to distribute that as a form and collect the data from the returned forms in a dataset. So the dataset should look like a 4Col x 3Row table:

    ItemName Quantity Cost Total (Row1)
    Helmet 1 $45.00 $45.00 (Row2)
    Wheel 2 $225.00 $450.00 (Row3)

    When I compile the returned form though, I get 8 columns with 4 repeated column names and 2 rows with a warning that the reurned form has different fields than the template.
    As always, your help is much appreciated.

  43. Stefan Cameron on August 23rd, 2009

    Ash,

    It still sounds to me like there’s a binding expression issue that’s causing the data not to repeat properly.

    Try putting a button on your form with a Click event set to

    // JavaScript:
    console.println(xfa.datasets.data.saveXML("pretty"));

    Click it after you have filled your form and check the JavaScript Console in Acrobat. The form’s current data will be output there. Is it properly structured as repeating instances of a data group node? Compare that to the data submitted from the form (in the XML file): it should match…

  44. Jess on August 30th, 2009

    Hi,
    I have a form to do (I am not using expandable tables) and I have check boxes, Now when the check boxes are selected I want a field to appear with a dollar value in it (I used a java script to show and hide fields and to get the dollar value I have used a default value), but any java script for that would be a great help.
    And then I want the total at the bottom of the form, which I have done…BUT it is adding all the fields rather than just the visable fields which have been selected.
    Any help would be appreciated.
    Thanks!

  45. Jeff in Ohio on September 3rd, 2009

    Hello,

    I have an older form that was created in 7.2. I now need to update the static table in the middle of the form and add two new columns. Its a simple table with just a header row and 1 row of data(which is bound). Yet in designer 8.2, I cannot get “Insert – Columns to the Right/Left” to work. The delete column option works. But for some reason in design view, the table will not let me add any more columns to the existing table, yet lets me delete columns? Any help would be great.

    Thanks!

  46. Stefan Cameron on September 7th, 2009

    Jess,

    The easiest way to get a dollar sign to appear in a numeric field is to set a Display Pattern of “num.currency{}” on it using the “Object palette > Field tab > Patterns… button > Display tab”. This will ensure that whenever the field has a numeric value, a localized currency symbol will be displayed (but it won’t be part of the field’s value).

    As for doing selective summations, you’ll have to write a script that checks for a field’s presence property. If it’s “visible”, then add the field’s value into a variable. Finally, end the Calculate script with the variable’s value (assign the variable’s value to “$”).

  47. Stefan Cameron on September 11th, 2009

    Jeff in Ohio,

    If you can delete columns but cannot add them, the only thing I can think of is that Designer doesn’t think there’s enough room (enough width) in the insert direction to add another column. For instance, if your current table is as wide as the page, choosing the “Table > Insert > Column to the Right/Left” command will do nothing because there’s nowhere to put the inserted column within the layout.

    The menu command shouldn’t be enabled when columns can’t be inserted… I will report this issue to the team.

  48. Anthony on September 21st, 2009

    Hi Stefan,

    Firstly, amazing tutorial, even a newbee like me could figure it out! Thank you.

    Now on the table I’m creating, I have other object before and after the table. When the table gets too big, it starts overlapping the following objects. Is there a way to force following objects to push further down the page / automatically create a new page?

    Hope that makes sense?
    Many thanks again,

    Anthony

  49. Stefan Cameron on September 22nd, 2009

    Anthony,

    You’re welcome. I’m glad it helped!

    If your table is growing over-top of form objects below it, it must be in a positioned container (subform) along with the other objects. In order for all things to flow, they must all be in flowed containers themselves.

    To do it quickly while preserving the layout of the form objects that precede and follow the table, select all form objects that precede the table, right-click and choose “Wrap in Subform”. Do the same for the form objects that follow the table. Then, select the subform that contains the preceding subform, table and following subform and set the “Object palette > Subform tab > Content property” to “Flowed”.

  50. Roy Sena on September 28th, 2009

    Hi Stefan, First, thanks for maintaining this blog. It is a very useful resource.

    One of the fields in my dynamic table is an image field. I am dynamically assigning a URL value to the image field e.g.
    myImageField.value.image.href = “http://www.adobe.com/imageshome/pdfgift_home.gif”;

    The image field does not display in the dynamic form. myImageField.value.image.href only seems to work if the PDF is static.

    Any suggestion / workaround would help a lot

    Thanks and Best,
    Roy

  51. Sandeep Goli on September 30th, 2009

    Hello Stefan,

    I have a question with totals in table.

    I have a column which calculates price of items. I would like to get sub total page wise also, i would like to get the grand total at the end of the whole table after populating all the rows. I learn’t to calculate the grand total in this thread. But unable to calculate the same in page wise.

    Can you give me idea on how i can achieve this.

    Thank you.

  52. Stefan Cameron on October 2nd, 2009

    Roy Sena,

    See the update section on this post. It should explain why this isn’t working for you.

  53. Stefan Cameron on October 2nd, 2009

    Sandeep Goli,

    I found your question so interesting that I created another sample for this post, one that calculates page totals.

    I hope it answers your question.

  54. Sandeep Goli on October 2nd, 2009

    That was really great!

    This solved my problem completely. Thank you!

  55. Anthony on October 5th, 2009

    Hi Stefan,

    Thanks for the earlier help.

    I’ve got the expanding tables working well, looks great. I’m trying to post the date to a webserver through URL encoded Data, however only the final row of the expanding table is being recieved.

    Just wondering if you could throw a little light into this?

    Thanks again for your help.

    Anthony

  56. Vijee on October 9th, 2009

    Hi Stefan,

    I’m wondering if you can help me. I’m a newbee so please bear with me.

    I would like to create an interactive form in a multi-page format. I would like to display our fifty odd products, divided into 5 different categories. The client browses through these pages then selects those that he wants to buy.

    The interactive order form at the end of this pdfcatalogue/brochure should display the client’s choices along with the Total purchase order.

    In short, a little like a on-line catalogue and cart/basket that we see while buying online. Only thing being that when the client clicks on the object, or enters the quantity in the filed provided next to the image, this number should get enterred automatically in my order form.

    Please take a look at the brochure/order form I’ve created so far at:http://www.upperside.fr/vijee/mpls09ex/EXHIBITOR%20SPECIAL%20ORDERS2010.pdf
    It’s still raw, but I’ve got the subtotals, VAT & Totals fine, I just need to have the order form show only those items that are selected and not everything as is currently the case.

    I’m hoping that you can help me as to what resources I need to look up in order to be able to do this.

    Thanks for your help in advance.
    Vijee

  57. Stefan Cameron on October 12th, 2009

    Anthony,

    It sounds like you’re trying to do an HTTP submit of your table data. Perhaps those articles can help you out?

  58. Stefan Cameron on October 19th, 2009

    Vijee,

    I just tried accessing the link to provided but got a 404 error — perhaps you have already removed the PDF from the website or the spaces in the file name are causing some problems with accessing the URL.

    What you describe is definitely possible — it just requires a little bit of script to connect the catalog with the order form. I would imagine an entry in the order form would contain an item number so that you could easily find the order form entry that relates to a catalog entry so that when the user clicks on an item in the catalog, or updates the quantity, the pertaining order form item is added/updated/removed accordingly.

  59. Anthony on October 27th, 2009

    Hi Stefan,

    Thanks for the links. Unfortunately it’s not helped too much and I’ve been playing about for ages!

    Essentially I have got the submit working fine apart from when I try and submit the data in the expandable table, only the very last row (late entry) of data is sent through.

    Is this a problem with the way I have created the expandable table, or is it something in the way I am posting the form?

    Thanks again

    Anthony

  60. Stefan Cameron on November 2nd, 2009

    Anthony,

    Earlier, you mentioned posting the date via URL-encoded data.

    I’m wondering how you are trying to post/submit data to the web server.

    Have you set bindings on all table rows and fields that should be submitted? Any fields/rows with bindings set to “none” will not be submitted because their data will not be in the Data DOM, which is what gets submitted when you use a submit button…

  61. Anthony on November 3rd, 2009

    Hi Stefan,

    As far as I can see… as with your tutorial, column 1, ie. ItemIndex which indicated the row number is the only cell with the binding set to none.

    My issue is that when a new row is created by clicking add row, it seems to forget about all previous rows? Does that make sense?
    Could I show you the form, would that be easier?

    Thanks,

    Anthony

  62. Maria on November 6th, 2009

    Great tutorial! Really helped a lot.

    I have a few issues really and they are really odd ones too.
    First I couldn’t get numbering work correctly in the first column. I mean it works, but for some reason it doesn’t display the dot. I did copy you code exactly (this.parent.index + 1) + “.”;

    And I do know that it should work because I do have a background in JavaScript and Java programming, but it would not display a dot. It only displays the numbers.

    Also the Remove button doesn’t work, it gives me a following message:

    Script failed (language is formcalc; context is xfa[0].form[0].#subform[0].#subform[2].Button2[0])
    script=
    if(Table1._Row1.count > 1)
    Table._Row1.removeInstance(Table1._Row1.count – 1);
    Error: syntax error near token ‘Table1’ on line 3, column 10.

    And last but not the least. I tried copying a piece of code for removing a row from another form and it does work there. The code is follows:

    var nNumRow = 0;
    var nTableLength = Table1.nodes.length;
    for (var nCount = 0; nCount < nTableLength; nCount ++) {
    if ((Table1.nodes.item(nCount).className == “subform”) & (Table1.nodes.item(nCount).name !== “HeaderRow”)) {
    nNumRow = nNumRow + 1;
    }
    }
    nNumRow = nNumRow – 1;
    if (nNumRow < 1) {
    xfa.host.messageBox(“The minimum allowable number of rows is 1. You cannot remove any more rows.”, “Warning”, 3);
    }
    else {
    Table1.Row1.instanceManager.removeInstance(nNumRow);
    }

    I tried copying it into my form and it highlights the text past first semicolon (;) in the for loop:
    nCount < nTableLength; nCount ++) {
    in green as if it is a reference and not a piece of code. I don’t understand why and it is driving me insane. And of course it doesn’t work.
    I am probably just missing something, but it is driving me insane. Please help!
    Thank you so very much for your help in advance.

  63. Maria on November 8th, 2009

    Hi Stefan,

    Great tutorial thank you very much!

    I have an issue though. My minus button doesn’t work despite the fact that I used your script. Plus works, but for some reason removes gridlines around the first cell. Can you please help?

    Thank you in advance,

    Maria

  64. Stefan Cameron on November 8th, 2009

    Anthony,

    I don’t understand what you mean by “forget about all previous rows”. Can you expand on that, please?

  65. Stefan Cameron on November 8th, 2009

    Maria (Nov 6, 2009),

    No dot in the row number:

    My first guess is that you’re using a numeric field, rather than a text field, to display the row number and therefore the dot is being dropped because it’s not a valid digit (or you need it to be a numeric field but you haven’t set data and display patterns on it so that it can properly handle the dot in the number). If that’s not it, then perhaps the text field simply isn’t wide enough to display the number and the dot that follows it?

    Syntax error:

    I’m guessing this is simply because you’ve got a typo in your script where you’re missing a “1″ in “Table._Row1…” in the second line (assuming the table object’s name is “Table1″).

    Green highlight past the first semi-colon:

    This would be because you’re writing script in JavaScript however the event’s script language is set to FormCalc (the default). In FormCalc, semi-colons, as well as ‘//’, indicate the start of a single-line comment.

  66. Maria on November 8th, 2009

    Hi Stefan,

    I also have an unrelated question.

    I need to have a field within my form where a user can enter text, images and tables (this field will be a part of an application form for grants and researchers do like to incert some graphs and images in their proposals). But the most important I need to limit that text field to 8 pages, I need pages rather than characters, is it possible at all?

    Maybe you can point me towards some other great tutorial just like this one.

    Thank you so much in advance!

    Maria

  67. Stefan Cameron on November 8th, 2009

    Maria (Nov 8, 2009),

    I’m assuming you’re the same Maria that commented here on Nov 6, 2009, and that my response above will resolve your issues.

  68. Maria on November 8th, 2009

    Hi Stefan,

    Thank you so much for your reply!

    I am so new to PDF Forms and never had any official training, so sorry if my questions are stupid.

    I thought that TextField is text by default I can’t find anywher in the Object pane where I can change it from numeric to text, but the field is certainly wide enough to display the dot.

    Sorry I typed up the error message wrong I do have 1 in Table1 and it still doesn’t work:

    if (Table1._Row1.count > 1)
    Table1._Row1.removeInstance(Table1._Row1.count – 1);

    And lastly you are right it does say FormCalc in the top row, but how do I change it? it doesn’t let me to type over it at all.

    Thank you so much in advance.

  69. Maria on November 8th, 2009

    Hi Stefan,

    I was the same Maria. Thank you. And I also found where to change the language to JavaScript.

  70. Maria on November 8th, 2009

    Hi Stefan,

    I found out that all of my problems were because I had FormCalc instead of JavaScript in there. So now everything works. Thank you so much!!! You helped so much and your tutorial is the best, I am forwarding it to all of my collegues. If you do now how to limit TextFields by number of pages rather than characters that would be great.

    Thank you again!

  71. Anthony on November 11th, 2009

    Hi Stefan,

    Esentially when you post it to url it only displays one row of the table. ie. if i had entered data for 5 rows, 1, 2, 3, 4, 5 only the data in row 5 displays after the post.

  72. Susila on November 12th, 2009

    Hi Stefan,

    I have one table which is having 1 row. In this my 1st cell having the delete button. One add button is there in out of the table. I can able to add the rows dynamically while clicking the add button using your code.

    Now I got delete button in each row. So If I click any of the delete button the corresponding row should be deleted. For that what should I want to write the code on delete button.

    Please help me on this ASAP.

  73. Stefan Cameron on November 12th, 2009

    Maria,

    I’m glad I could help.

    About limiting a field to spanning 8 pages: I’m not sure this is possible. While there is a function you can call to determine the number of pages a form object spans (xfa.layout.pageSpan([form_obj])), you can only get meaningful information from it after the the form has been (re)rendered. Whenever a user types into a field, the form is re-rendered after they exit the field. At this point, if the field’s height is expandable, the field will be resized to fit the length of the text that was entered. Once rendered, you get the Layout:Ready event where you can use the xfa.layout.pageSpan() function however it’s too late: If too much text was entered, the field may already be spanning more than 8 pages. At this point, you could attempt to figure-out the height needed for 8 pages and set the field’s height (making it no longer expandable) but you’ll cut-off some of the text that was entered…

    So there’s no perfect solution. Perhaps the simplest thing to do is set a maximum height on the field so that it doesn’t extend beyond what should be about 8 pages.

  74. Stefan Cameron on November 19th, 2009

    Anthony,

    I’m wondering if your table’s repeating row binding is setup correctly. The way you describe it, it sounds like the repeating row isn’t bound to multiple records but rather is only bound to a single record and so the last set of data you enter is always the one submitted.

    A repeating form element that is bound to a repeating set of data will have a binding that looks like “groupElement[*]“. For example, if you had repeating address blocks where the grouping element was “address” and it contained an element named “street”, the repeating row (subform) would be bound to “address[*]” (all instances) and a field inside that row (subform) would be bound to “street”. This way, all address blocks would be displayed (submitted) and each instance of the row would have its specific street name.

    Select the row and check that the “Object palette > Binding tab > Normal Binding property” is properly set.

  75. Stefan Cameron on November 19th, 2009

    Susila,

    I figured that would be an FAQ on this post so I created a sample form.

  76. Anthony on November 30th, 2009

    Hi Stefan,

    I’m having an absolute nightmare with this!!! I’m soo tempted to give up!! I just can’t see what’s wrong. Is there any chance I can send you my form? I believe you should be able to see my email address?

    Best regards,

    Anthony

  77. Maria on December 2nd, 2009

    Hello Stefan,

    Thank you so much for answering my questions before. I posted the following question before:

    I need to have a field within my form where a user can enter text, images and tables (this field will be a part of an application form for grants and researchers do like to incert some graphs and images in their proposals). But the most important I need to limit that text field to 8 pages, I need pages rather than characters, is it possible at all?

    You did answer the 8 pages question, thank you very much. But what about a field wich will enable people to paste images, tables and graphs from Word/Excell into PDF? I am really strugling can’t find answers anywhere and no one seems to ask this same question. It is just I have to create a progress report form for researchers to fill in and they are really going to just copy paste from word or excel and they do have graphs and tables in their docs.

    Any kind of help will be highly appreciated, even if the answer will be “no you can’t do it” so I can just stop looking and know that it is impossible.

    Thank you so much once again,

    Maria

  78. Maria on December 2nd, 2009

    Hi Stefan,

    Another question I had is around responses file. Can I customise it to get data only from some fields from the distributed file, not all of them.

    Thank you,

    Maria

  79. Stefan Cameron on December 5th, 2009

    Maria,

    Unfortunately, the fields in XFA aren’t “rich media fields” that would support pasting of extended rich media types like images, tables, graphs, etc. They just support pasting rich text (text with formatting) at the most. Actually, it’s not an XFA limitation per se, it’s more a limitation of the application that is implementing XFA (Acrobat/Reader) since XFA does support extended content ().

    As for “response files”, I’m assuming you mean an XML data file submitted from a form that you’re importing into another form? If so, then yes, you can control what portion of that data you see simply by removing bindings to data nodes you don’t want.

  80. Maria on December 9th, 2009

    Thank you Stefan!

    Can you please point me towards a tutorial on Password protection. I have to protect my form so no one can go ahead and open it in Acrobat Pro or LiveCycle in order to change the fields in the form. I did manage to do that in following steps. I distributed my form, then I opened distributed file and in Form Properties I ticked “use a password to restrict printing and editing of the document and its security settings”. And also opened that same document in Acrobat Pro to tick Advanced –> Enable Usage Rights in Adobe Reader. That works just fine, however when I tryed to export my responce file into Excell it didn’t export properly. Excel file had just Name, Date received and Time received fields and no data fields. What am I doing wrong?

    Thank you again in advance!

    Maria

  81. Stefan Cameron on December 14th, 2009

    Maria,

    You should be able to apply password restrictions directly in Designer by using the “File menu > Form Properties… > PDF Security tab” settings before you distribute the form.

    Give this a try to see if it resolves your other issue.

  82. Maria on December 14th, 2009

    Hi Stefan,

    I’ve tried this but if I set the password before distributing I can’t export the responce file at all. In fact Export function is disabled all together.

    Thank you,

    Maria

  83. Stefan Cameron on December 18th, 2009

    Maria,

    Perhaps this is a limitation imposed by some security feature in Acrobat that prevents form data from being exported when the PDF is secured? I’m not sure, but this sounds like an Acrobat issue. Someone over at AcrobatUsers.com might be able to help.

  84. Todd on January 26th, 2010

    Hello Stefan,

    You have helped me a lot in the past I thank you.

    I have an issue were a Add Rows document is used for collecting data for some store closing projects. I am now getting the completed PDF’s back and when I transfer the data to a spreadsheet the added rows information is not showing up in the spreadsheet. We put the PDF’s out on a sharepoint site and had the techs pull the forms from there and just email the forms back to a central email address. Is there a way to get this information to show up? Thank you

  85. vince on January 28th, 2010

    I’m glad that I found your site! It’s now bookmarked for future reference.

    I’m creating a form where users can enter instructions. The table in the form has 1 row, a textfield, and two buttons. One of the buttons should add a row, and the other should delete a row.

    I was able to get the add row button to work, so that every row in my table has the fields stated above. However, the add row button seems to add the new row instance at the bottom of table. Is there a way so that the new row is placed directly below the old row? This way if a user forgot a step between row 3 and 4, they can just click the row 3′s add row button and a new row will be row 4, the old row4 will be row5.

  86. noir_pol on January 28th, 2010

    If the rows are dynamically created, how can I autopopulate them?

    I know how to autofill textfields using a dropdown list with a javascript. However, without knowing the name of the field, how can I fill them with values?

  87. Stefan Cameron on February 5th, 2010

    Todd,

    A few questions:
    - Was this an XFA-based PDF form that you designed using LC Designer?
    - Were the responses submitted (emailed) back as XML Data files?
    - What does the XML Data look like?
    - How, exactly, are you transferring it to a spreadsheet?

  88. Stefan Cameron on February 8th, 2010

    vince,

    New rows are always appended. If you want it to be inserted, you should use the insertInstance method, or addInstance then moveInstance methods of the Instance Manager.

  89. Stefan Cameron on February 8th, 2010

    noir_pol,

    I’m assuming you’re asking how to “find” the fields in the dynamically-generated table rows.

    For this, you simply need to use the repeatable row’s “all” property which will return a list of all instances of that row. Then, iterate over the instances using a for-loop:

    // JavaScript:
    var rows = myTable.myRow.all; // assuming there is at least 1 row
    for (var i = 0; i < rows.length; i++)
    {
        var row = rows.item(i);
        row.myField.rawValue = "asdf"; // assign "asdf" to field "myField" in row[i]
    }

    Feb 9, 2010: Fixed typo "rows.getItem(i);" to "rows.item(i);".

  90. Larissa Best on February 16th, 2010

    Hi Stefan,

    I’ve been reading through the posts here but cannot find a solution to my problem.

    I have a form which has a drop down list of currencies.
    I also have Numeric Fields where you can enter Fees.

    My question would be:
    Is there any way that depending on the Currency you have chosen in the first drop down list, the symbol behind the Number in the Numeric Field changes/adapts?

    I tried Concat but that does not work for some reason. I am guessing this is because it is a Numeric Field.

    Any ideas?

    Thanks,

    Larissa

  91. Stefan Cameron on February 23rd, 2010

    Larissa Best,

    This is actually quite simple to achieve using a combination of a Display Pattern and Locale set on the numeric field.

    The Display Pattern determines how the data assigned to the field will be displayed.

    For example, if you set the value to “123″, you’ll get “123″ by default. If you wanted to show a currency sign, you could set a Display Pattern of “num{($zzzz9.99)}” which would result in “$123.00″ being displayed when the value “123″ is set in the field. (The Display Pattern simply formats the value for display without actually modifying it or expecting the raw value to be in that specific format.)

    You can set the Display Pattern by clicking on the “Object palette > Field tab > Patterns…” button (as of Designer 8.1 or 8.2; prior to that, I believe the Display Pattern was an actual property on the Field tab).

    With the Display Pattern set, if you choose an alternate locale for your field, the currency symbol will change. If you set the locale to “en_GB”, you would get a Pound (£) symbol, for example.

    In light of these facts, if you set the value of each currency in your drop down list to the locale code for the currency, you could write a Change event script that checked the new selection and set the item’s bound value as the locale on the numeric field.

    See my sample form for a demo.

  92. Maria on February 24th, 2010

    Hi Stefan,

    how can I change the row count from numbers to letters. I.e. a, b, c, d, e

    Thank you so much in advance.

  93. Stefan Cameron on March 3rd, 2010

    Maria,

    One way would be to use the fact that the ASCII code for the letter “A” is 65.

    In my sample, the row number is based on the row’s index + 1. You could base it on

    // JavaScript:
    var rowNum = String.fromCharCode(index + 65);

    Of course, you would have to handle the case where you have more than 26 rows and loop back to “AA”, “AB”, “AC”, etc. You can determine that by using the modulus operator (%) which gives you the remainder of a division rather than the result: Base the first letter on the result and the second on the remainder, though this still won’t handle the case where the result is greater than 26, but you would have a whole lot of rows at that point…

    BTW, lowercase letters start at ASCII 97.

  94. Jerry W. McLeod on March 24th, 2010

    Stefan, I got through your add rows/remove rows tutorial this morning. I cant beleive I followed it through and only missed one instruction(repeat row property, just missed it thats all.) However, I caught it and it just works fine. I wish you had somthing that could help me with subforms, they are complicated especially for a novice like me, but i am really catching on to this Livecycle. I love it.

    One last simple question I hope. Is there any reason why when I preview a file that I am working on in LiveCycle, the fields wont accept any data so can see how it looks. What makes this happen. I dont think I had this problem with other LiveCycle files I was working on. Am I missing something here?

    Thanks for your help. Keep up the good work and keep the tutorials coming.

    Jerry McLeod

  95. Jerry W. McLeod on March 24th, 2010

    Stefan,

    Maybe I am losing my mind. I created a brand new LiveCycle form from scratch and placed two text fields on the form, hit the preview button and tried to put something in the field and it would not let me do it. I thought I was able to do that on previous forms that I created a couple of days ago. Like I said, maybe I am losing my mind. how can I see how it looks if I cant put any data information in the field?

    Jerry Mcleod

  96. Stefan Cameron on March 30th, 2010

    @Jerry W. McLeod,

    It sounds like the forms you’re creating might be static PDF forms. Have a look at my tutorial on Previewing in Dynamic PDF format.

    As for a lesson on subforms, you could try following my MAX 2007 tutorial which dealt with the theory and function of dynamic forms. The “class notes” are very detailed.

  97. paul jj on April 17th, 2010

    Hi there,
    I’m creating a quotation form and i have created the formula
    ((ItemQnty * ItemCost) / ItemPer) + ItemDelivery
    giving me a subtotal.
    When i run the form in preview and input the quantity, i receive the error box
    Script faild (language is formcalc; context is xfa[0].form[0].#subform[0].Header[0].Table1[0].Item[0].Total[0])
    script=
    ((ItemQnty * ItemCost) / ItemPer) + ItemDelivery

    Error arithmetic over/underflow.

    I receive this when i input a cost value, but when i fulfill the “Per” field the formula is fulfilled and the result is returned.

    Is there any way to turn off these error messages?
    Thanks

  98. paul jj on April 18th, 2010

    Hi again, I worked it out – i had to check that out of the three input fields, two of them were null or 0 first, and then tell it to return a null or 0 value. the problem i have now is to write some code that will perform the test on those two fields.
    I have managed to write
    if(ItemCost ne 0 & HasValue(ItemCost)) then
    ((ItemQnty * ItemCost) / ItemPer) + ItemDelivery
    else
    null
    endif
    and got it to work – how can i perform this test on the last input field “per”, i’m so new to code its untrue :) i need some direction on how the if function works i think.
    Thanks
    Paul

  99. paul jj on April 18th, 2010

    well well well – sorted it , can’t believe i did it so quick, thanks to this forum !!!

    if(ItemCost ne 0 & HasValue(ItemCost) & (ItemPer ne 0 & HasValue(ItemPer))) then
    ((ItemQnty * ItemCost) / ItemPer) + ItemDelivery

    else
    null
    endif

    thanks all!!!

  100. Maria on May 9th, 2010

    Hi Stefan,

    Can you please help. Is there a way to create a drill-down drop list in LiveCycle. I am designing a complex application form for researchers to fill in. In this form I ask them to define their research institutions, some applicants a lot of institutions, so initially I thought I should create expandable table with drop-down lists in the row, so they can choose one from the list and add as many as they like later. But then the list became enougmous, and I couldn’t find any way to make it a drill-down. Then I thought I should have a subform with all of those Institutions as check boxes, so that parent institution subform would have all of the child institutions in subforms. So I have one page of institutions and if you click on the institution another subform appears with the children institutions. I then wanted to have a summary table of all of the institutions as a table of read only text fields which grows once another check box is clicked. And I also have

    this.presence = “hidden”;

    script on exit on this subform with the ckeckboxes so it dissapers of the screen and is not printed later, it can be reopened by pressing the “Display” button. The hiding and the button works fine.

    I have a few problems with the whole thing. First of all once I come out of the subform it hides but when I display it again the check boxes are unticked, so for some reason it doesn’t same changes. And also I can’t get that summary talbe to work at all, despite the fact that I thought it would be quite easy.

    Can you help please? I thought of including more of my scripting, but it doesn’t work and I feel very dum about it.

  101. Stefan Cameron on May 16th, 2010

    @Maria,

    Sounds like you have a complex form… I’m having a hard time understanding at which point you lose those checkboxes. If you’re just hiding the subform(s) that contain(s) the checkboxes, they shouldn’t lose their values. Can you describe these subforms in greater detail, including what you’re expecting to still be checked when the user performs a certain action?

    For the summary table, I would’ve thought that every checkbox would’ve had a Click event which would check the (new) value of the checkbox. If it’s “1″, then add a row to the summary table with the associated institution name; if it’s “0″, remove the appropriate row from the table. Another way to do it would be to refresh the table (i.e. set the summary’s row instances to zero to remove all instances, then look for all checked checkboxes and add appropriate rows) when the user clicks on the button to hide the institution list subform (the one with all the checkboxes).

  102. Leon on September 27th, 2010

    I have found your blog to be very helpful! Thank you!

    I have a created a table that is bound to a SQL table via ODBC. When I preview the form, only the first row of the query result appears in my table. The data set varies from 1 to 10-15 rows (depending on the selected value of a dropdown list). I have been trying for 3 days (I am ashamed to say) to get all the expected data to display. I have set the table row to repeat…I just dont know what else to do.

    Im wondering if I need some sort of script to populate each row according to the expected number of rows.

    I appreciate any help you can provide.

    Thank you
    Leon

  103. Stefan Cameron on October 1st, 2010

    @Leon,

    Wonderful! I’m always happy to hear my blog is helping people out there make better forms!

    Yes, that’s correct: You need a script that will loop through all records available via the connection and add instances of table rows with pertaining data. I have a sample of that in my tutorial on displaying all records from an ODBC connection.

    If that doesn’t work, then I should ask whether you’re previewing your form with Acrobat or Reader. Seeing only the first record is often a sign that you’re using Reader instead of Acrobat and therefore you can’t use data connections unless you extend the PDF to allow data import in Reader.

  104. Kerry on October 15th, 2010

    Good afternoon,
    I have an issue I was hoping you could help me with. I have set up a form with two dynamic tables, the first table is always visible and based on a particular selection in a drop down box which resides in the 5th column of the first table, the second table presence is set to “visible”. The problem I am having is prefilling the data from column 1 of the first table. If the user selects the appropriate choice in lets say rows 1 and 5 of the first table, how do I prefill the data from column1 of rows 1 and 5 into column 1 of rows 1 and 2 of the second table. I’m trying not to be too wordy so I hope my explanation is sufficient.
    Thanks so much for running such a wonderful site!
    Kerry

  105. Jennifer Hawkes on October 21st, 2010

    I have created a travel expense tracking form. I have used your dynamic table to give users the ability to enter all their travel reimbursements. There are many fields, but the important ones for this questions are: expense type, payment type, total (which calculates a total based on the original charge * conversion rates).

    I also have a summary sheet (which is used by the controller’s office to process the reimbursement). The sheet needs to use IF statements to SUM values based on the their answers below. My current script works to conditionally sum the first row of the tracking expense chart; however, if I add additional rows, it will not evaluate those. I think I need some sort of array formula but I don’t know what that looks like. I have been using FormCalc because I know no JavaScript.

    if (form1.#subform[3].General_Expense.Item[*].expense_type == “51807 – Membership Dues/Fees” and form1.#subform[3].General_Expense.Item[*].payment_type <> “BMC Credit Card”) then Sum(form1.#subform[3].General_Expense.Item.total) endif

  106. Stefan Cameron on October 23rd, 2010

    @Kerry,

    If I understand you question correctly, you basically want to know how to access specific rows and columns in a table.

    In XFA, a table consists of subforms that form the table itself and the rows that it contains. Cells are made of fields or subforms inside each row.

    A dynamic table typically has a repeatable row, in which case you’re dealing with a repeatable subform with multiple instances.

    When a subform has multiple instances, each instance can be accessed using the “[n]” notation where “n” is the index of the instance you’re looking for.

    To access the 5th row in a table with the name “Table1″ which has a repeatable row “Item” in it, you would do this:

    // JavaScript:
    // note that subform instances are zero-based
    var row = Table1.resolveNode("Item[4]");

    Say each Item row has 3 columns which are fields named “Description”, “Quantity” and “UnitPrice”. To access the Quantity column (field) in the 3rd instance of the repeatable Item row in Table1, you would do this:

    // JavaScript:
    var row = Table1.resolveNode("Item[2]");
    row.Quantity.rawValue; // get the quantity column's value from the 3rd row
  107. Stefan Cameron on October 23rd, 2010

    @Jennifer Hawkes,

    If all you were doing is calculating the sum of a field that occurs in all instances of a repeatable subform (table row), then you could simply write:

    // FormCalc:
    TotalField = Sum(Table1.RepeatableRow[*].TheField)

    In the example you gave me, however, you need to make string comparisons to know which rows to sum and I don’t know if it’s possible to express that in a “one-liner” in FormCalc. If it were me, I would do this:

    // FormCalc:
    var allItems = form1.#subform[3].General_Expense.Item.all // get all instances of the Item row
    
    GrandTotal = 0 // reset "GrandTotal" field
    
    // loop through all item rows and add only those that matter to the GrandTotal field
    for i = 0 upto allItems.length - 1 do
        var item = allItems.item(i)
        if (item.expense_type == "51807 – Membership Dues/Fees" and item.payment_type <> "BMC Credit Card") then
            GrandTotal = GrandTotal + item.total
        endif
    endfor