Stefan Cameron on Forms
Building intelligent forms using Adobe LiveCycle Designer

Archive for August, 2006

Bug: Cannot Override Calculations

Description

The XFA language supports fields which are calculated yet still overridable by the person filling the form. For instance, you may have an invoice on which you calculate the tax associated with a purchase using a calculated field yet, for customers from other countries, you would like to allow them to override the calculated tax amount and enter the correct amount themselves.

To do this, you would use the Object palette’s Value tab and set the field’s Type property to Calculated – User Can Override. You could even go as far as specifying an Override Message which would appear if the user attempted to override the field’s calculated value.

In theory, when the user attempts to override the field’s calculated value, either the Override Message or, if none was specified, an Acrobat default message appears warning that the field is calculated and gives the user the option to continue with the override or to cancel. If the user proceeds with the override, subsequent calculations use the override value instead of the original calculated value regardless of subsequent changes to other fields which the overridden field’s calculations were dependent on.

Unfortunately, there’s a bug in Acrobat that causes the overridden value to be discarded. It manifests itself in a couple of different ways:

  1. Dynamic PDF: Not only will the value specified by the user (the override) not be retained but the Override Message (if specified) won’t be displayed. The behavior is simply to let the user type-in a value but then throw it away and run the calculation again without any warning.
  2. Static PDF: In this case, the Override Message (if specified) is displayed and the user has the option to discard their change or proceed with the override but the specified value is discarded regardless of what they choose to do and the calculation is run again.

Workaround

You could use two fields and a check box where the first field is simply “Calculated – Read Only” and the second field is the override value and is invisible until the check box is checked.

All calculations which depend on the calculated field in question would need to verify the value of the “override” check box: If it’s unchecked, calculations would use the value from the first field which itself may be calculated. If it’s checked, they would use the value from the second field which contains the override value.

Checking the check box would cause the first (calculated) field to become invisible and the second (override) field to become visible. You could even display an Override Message when the check box gets checked and use the

xfa.host.response("Question", "Title", "Default Value")

statement to give the user the option to cancel the override (the return value is null if the user picked the Cancel button).

Fix

Please refer to the Bug List for updated information on the version(s) affected by this bug as well as if and when it was/will be fixed.


Posted by Stefan Cameron on August 29th, 2006
Filed under Acrobat,Bugs

The Bug List Goes Live!

Some of you may have noticed the new Bug List side bar module on my blog recently. I’m excited to launch this new section of my blog tonight and I hope that it’ll add even more value to your visits here as well as to your experience using Designer and Acrobat to design and develop your electronic forms.

Look for a few kick-off posts in the coming days about some bugs that fellow readers and users have reported as well as some that I’ve come across myself while making the various samples I’ve already posted to this blog. Of course, there shouldn’t be any in the features I worked on… 😉

My hope for this new section is that it’ll serve as a reference for things to watch-out for in the versions of Designer and/or Acrobat that you may be using as well as what to do in order to get around them.


Posted by Stefan Cameron on August 25th, 2006
Filed under Bugs

Complex Validations

A couple of days ago, Michael Ramirez asked me how to do complex validations on forms. He asked how one could have a validation as follows: Given 3 text fields A, B and C and a check box E, A is mandatory only if B and C are filled or if E is checked. I thought this would make a great little sample of both complex validation scripts and what I like to call the “Two Button Submit” technique.

Download Sample [pdf]

Minimum Requirements: Designer 7.x, Acrobat 7.x.

The Plan

First, let’s figure-out what the plan is before we start scripting. The idea is to place these fields on a new form along with a submit button such that the user cannot submit the form unless the validation rules succeed. Since Field A isn’t always mandatory, we can’t default it to be User Entered — Required by using the Value tab in the Object palette. We’ll need a way to make it required only when Fields B & C are filled or when Field E is checked. Furthermore, we don’t want the form’s data to be submitted unless these rules are met.

The easiest solution that comes to mind is one that’s passive as the user is entering data into the fields but aggressive at the point when they try to submit it by putting the validation script on the submit button’s Click event. The catch here is that there’s no way of stopping the submission process once the Click event has fired so regardless of whether your validation succeeds or fails, the form is going to be submitted. That’s where the “Two Button Submit” technique comes-in to save the day.

“Two Button Submit” Technique

Thankfully, there’s a scripting method called execEvent that lets you programmatically cause an event to be executed on a field. With this in mind, you place a regular (non-submit type) button on the form, make it visible and set its caption to read something like, “Submit”. Then you place the actual submit button (could be email, HTTP or even print) on the form and make it invisible. Please note: make it invisible, not hidden or else the execEvent call on it will fail because Acrobat won’t know it exists in the XFA Scripting Model. For this example, let’s call it “EmailSubmitButton”.

Now that both buttons are on the form, in the regular (fake submit) button’s Click event, put the following script (FormCalc or JavaScript works just the same):

EmailSubmitButton.execEvent("click");

With that script, when you click on the fake submit button, you’ll cause the Click event on the actual submit button to fire and the fake submit button will, to the user, behave just like a normal submit button.

The advantage of this is that you now control if and when the real submit button’s Click event is executed and therefore if and when the form is submitted.

If you were to add the following JavaScript statement before the execEvent line:

if (FieldA.rawValue != null && FieldA.rawValue.length > 0)

the form wouldn’t submit unless Field A was filled.

Validations Prior to Submitting

Using the “Two Button Submit” technique, we can now perform any kind of validations — really simple to very complex — we want and have total control over if and when the form may be submitted.

Given our example of fields A, B, C and E, we can do something like this:

var bCanSubmit = true;

if ( (IsSpecified(FieldB) && IsSpecified(FieldC)) ||
    IsChecked(FieldE) )
{
  if (!IsSpecified(FieldA))
  {
    xfa.host.messageBox("Please fill Field A.");
    bCanSubmit = false;
  }
}

if (bCanSubmit)
  EmailSubmitButton1.execEvent("click"); // submit the form

This will prevent the form from being submitted if Field A isn’t filled when Fields B & C are filled or Check Box E is checked.


Posted by Stefan Cameron on August 24th, 2006
Filed under Scripting

Invalid Flashing Fields 2.0

A colleague of mine here at Adobe pointed-out today that the use of the AcroForm Document object’s getField method wasn’t necessary in the script I used for my original Invalid Flashing Fields sample.

There’s an alternative which uses xfa.form.resolveNode in the app.setInterval script. xfa.form.resolveNode takes a SOM Expression and returns a reference to an XFA node. What’s more is that this API call can be made from within the context of the AcroForm Scripting Object Model.

The app.setInterval script therefore changes from this:

moFlashTimerID = app.setInterval(
  "var f =  this.getField('" +
    GetAcroFormFieldName(oField) + "');  " +
  "if (color.equal(f.fillColor, color.red))" +
    "{ f.fillColor = [" + moAcroFieldFillColor.toString() + "]; }" +
  "else" +
    "{ f.fillColor = color.red; }",
500);

to this:

moFlashTimerID = app.setInterval(
  "var f =  xfa.form.resolveNode('" +
    oField.somExpression + "');  " +
  "if (f.ui.oneOfChild.border.fill.color.value == '255,0,0')" +
    "{ f.ui.oneOfChild.border.fill.color.value = '232,232,232'; }" +
  "else" +
    "{ f.ui.oneOfChild.border.fill.color.value = '255,0,0'; }",
500);

Also note the changes in the way the color values are compared and assigned (whereby the newer version uses more familiar XFA script rather than the AcroForm script from the first version).

Since the use of the AcroForm Scripting Object Model should always be secondary to using the XFA Scripting Object Model (because AcroForm objects are, after all, in a separate Object Model which may change separately from the XFA Scripting Object Model), I wanted to highlight this alternative which makes more extensive use of the XFA Scripting Object Model than the first version did.

Download Sample [pdf]

Minimum Requirements: Designer 7.1, Acrobat 7.0.5.


Posted by Stefan Cameron on August 15th, 2006
Filed under AcroForm Objects,Scripting,Tutorials

Importing Data in Acrobat

Data is central to every form. Some forms simply collect data while others use pre-collected data to do various things to forms, such as pre-populate names, phone numbers, addresses, affect the layout of a form or various other things.

Using pre-collected data to affect a form as described above involves importing data into a form via the host application (assuming a server isn’t part of the picture). This time around, I want to talk specifically about importing data using Acrobat.

As you all know, Adobe distributes the Reader application for free. Because of this, you can save the forms you design in Designer as PDF and anyone with the free Reader application can fill your form and submit its data electronically.

The catch is when your PDF form requires data to be imported. Unless the host application is Acrobat Professional or Acrobat Standard, a regular PDF form cannot import data — no matter if it comes from an XML Data file or from a data connection to an ODBC or WSDL data source. Acrobat Pro/Std comes with all the tools you need to import data into a form and permits data to be automatically imported via an ODBC or WSDL connection. PDF forms opened in Reader (or Elements for that matter), on the other hand, aren’t privy to that functionality by default.

Side note: In Reader 7.0.5, there was a bug that resulted in Reader having the ability to import data into non-Reader-Extended (more on Reader Extensions below) forms. That bug was fixed in Reader 7.0.7 such that Reader can no longer, by default, import data into a PDF form.

The general rule is that PDF forms opened in Reader must be individually extended using Adobe LiveCycle Reader Extensions in order to enable the use of special hidden features such as Data Import, Digital Signatures, Local Save, Commenting and more. The only exception is if you own a licensed copy of Acrobat Pro 7.x which allows you to send a PDF out for review via email — which will enable Commenting capabilities in Reader for that PDF — or version 8.x in which you now have access to a new feature called “Enable Usage Rights in Adobe Reader“, available under the “Advanced“ menu. Using this new version 8.x command enables the Local Save and Digital Signature features in Reader for a particular PDF form. That said, before you start enabling all your forms, you should note that use of these Acrobat Pro features is subject to certain restrictions as detailed in your license agreement which you should be aware of.

Important: Local Save is not equivalent to Data Import. Local Save simply gives the user the ability to save a copy of a PDF form, along with any filled data, using the free Reader such that the form may be closed and re-opened at a later date in order to be completed. Therefore, you cannot use the “Enable Usage Rights in Adobe Reader“ feature in Acrobat Pro to enable Data Import features in the free Reader.

Another option is to use Adobe LiveCycle Forms to deploy your forms. Using this server product, you can pre-populate forms with data on the server prior to deploying them to the client application (on the user’s system). Using this option, you don’t need to reader-extend a PDF form which imports data because the data is imported and merged into the PDF form on the server and then deployed to the client application (any version of Acrobat/Reader on the user’s system), which, in turn, doesn’t need to import any data.

To summarize, here’s a little table that illustrates the conditions under which you can import data into a PDF form in Acrobat:

Version PDF Form With Reader Extensions With LiveCycle Forms
Reader no yes yes
Elements no yes yes
Standard yes yes yes
Professional yes yes yes

Sep 12, 2008 — Added information about “Enabling Usage Rights in Adobe Reader” feature


Posted by Stefan Cameron on August 12th, 2006
Filed under Acrobat