Populating list boxes

| 4 Comments

One of the Reader 9 enhancements was a new API call to populate list boxes: field.setItems(). The motivation for the new API is to provide better performance for populating lists.

Prior to Reader 9, the standard way to populate a list box is to call:

field.addItem(displayValue [, boundValue])

for each item in the list.  The new API looks like:

field.setItems(itemListString [, numColumns])

The first parameter is a comma-separated list of values, the second parameter is an integer telling the field how many columns are in the data (defaults to one).  The second parameter is designed for future extensibility if we choose to some day implement a multi-column list box.

Examples

A call to populate a listbox with currencies might look like:

Currency.setItems(
  "US Dollar,Canadian Dollar,Euro,United Kingdom Pounds");

Or if there were a bound value, it would look like:

Currency.setItems("US Dollar,USD,Canadian Dollar,CAD,Euro,EUR,United Kingdom Pounds,GBP", 2);

Prior to Reader 9, this second variation would have been coded as:

Currency.clearItems();
Currency.addItem("US Dollar", "USD");
Currency.addItem("Canadian Dollar", "CAD");
Currency.addItem("Euro", "EUR");
Currency.addItem("United Kingdom Pounds", "GBP");

Alternative

There is a 3rd method for populating listboxes: binding them to data.  Designer allows you to point your field at a location in your instance data where list box contents will be stored.  While this method has very good performance, it has the disadvantages that a) your data is not always in the correct format for binding, b) the listbox gets populated from data only during the initial data load.

Performance

If you are using listboxes only casually you probably will not notice the difference in performance between the two methods. But if you are using listboxes intensively, the new method is a life-saver.

I have attached a form where I compare the old performance to the new. On my laptop, I populate a listbox with 500 items in 125 milliseconds using addItem() calls, and in 16 milliseconds using setItems(). Neither of these numbers may seem significant, but we have customers with forms containing many list boxes with many, many entries where the difference in performance is critical.

Compatibility

If you are designing a form to use this new API, be sure and set your target version (in Form Properties/Default) to "Acrobat and Adobe Reader 9.0 or later".  Unless you do this, calls to setItems() will not work -- even though you might open the form in Reader 9.

4 Comments

Thank you for the post. I am new to building forms in pdfs and your site is a great resource.

Question. How do you deal with data entries that contain commas when using setItems()?

The whole list is quoted, not the individual list items. So, commas within the data cause the those items to be broken into multiple items.

Example: "My Company Name ,Inc." would become 2 items "My Company Name " and "Inc."

Can an escape char be used?

I tried the \ char with no success.

John:

When you put a backslash in a literal string, it escapes the next character. e.g. the literal: "quote\"char" will yield the string quote"char.
But you need the backslash to be preserved for the call to setItems. This means you have to double it: "My Company Name\\, inc". That way the API receives the string:
My Company Name\, inc

Good luck
John

The double-backslash worked.

I can't thank you enough for the quick response. It was unexpected, but truly appreciated.

Thank you.

I have multiple listboxes that need to be populated with the same data. The data is static and will not change once the pdf is released.

I want to avoid hard coding each listbox as there are up to 120 on this form. There will be up to 20 different sets of data lists with a range of 5-600 items that will populate the listboxes. My hope was to create a variable for each set of data that would contain the comma delimited string, then reference that variable using setItems(myDelList, 1).

I have not figured out how to make a variable global and access(path to) it from within the listbox. I have to assume there is a way as I have seen posts on this topic, but I have just failed to achieve it.

Another idea... Would it be better/possible to hard code the list in one listbox, then have other listboxes using the same date reference that first box?

The pdf must populate offline and without the use of external files, so data must be hard-coded in the pdf itself.

Two Questions:
What is the best method for populating the listboxes with hundreds of items if the data is static and the data is repeated in several listboxes?

Will Acrobat handle this amount of data?

Leave a comment

About this Entry

This page contains a single entry by John Brinkman published on January 30, 2009 8:16 AM.

Position a Subform at Page Bottom was the previous entry in this blog.

Scope of JavaScript Objects is the next entry in this blog.

Find recent content on the main index or look in the archives to find all content.