Accessibility
Adobe
Sign in Privacy My Adobe

Community Publishing

Created:
2010-12-19
Last Updated:
2011-01-20
by
User Level:
Intermediate/Advanced
Products:
Acrobat SDK
Acrobat
Reader


Need more tips and tutorials?


Correcting PDF Form Field Appearances after Saving with Preview on the Mac

Question: Why are the contents of form fields not visible after saving a PDF using Preview on the Mac?

For PDF forms that have been filled-in and saved using the Preview application on a Mac, why does data in form fields only appear while the field has the focus, and disappear when the field loses the focus?

Answer:

This problem was addressed in a (Nov 2009) blog post by Acrobat Technical Evangelist Joel Geraci: http://blogs.adobe.com/pdfdevjunkie/2009/11/script_to_fix_mac_osx_previewa.html

In short, the Preview application on the Mac (as of version 5.0.3) corrupts PDF forms in a number of ways. Preview does not correctly create form field appearances, causing data in fields not to be shown at all, or shown incorrectly. It is often useful to be able to view and print the form even though the fields are corrupted. Fortunately, there is a solution.

Joel provided a handy script that loops through the fields in a document and toggles the multiline property of text fields, causing Acrobat to regenerate the field appearances. The script has several limitations, including only dealing with text fields and not allowing use with Adobe Reader.

Expanding on Joel's efforts, I created a similar script that handles the other form field types, including radio button, check box, combo box, and list box fields. All form field types get corrupted by Preview, not just text fields. Only text fields have a multiline property, so I chose a property that all field types share, one that can be safely toggled without affecting the field values. It was also important to choose a property that Reader is able to modify. One such property is the field border color. Multiple fields with the same name can have different border colors, so the script processes each field widget individually.

There is no need to deal with digital signature fields since Preview is not able to interact with them. In fact it corrupts the form by removing digital signatures altogether. Since buttons do not represent data (when used with Preview, at least), there is no need to deal with them either and we can save a bit of time by excluding them from the processing.

The Script

The code below demonstrates looping through the form fields in a PDF and toggling the border color, as well as creating a custom menu item that calls the function that does the work. I have included explanatory comments in an effort to make it easy to understand.

/*
Folder-level JavaScript file: preview_fix.js
Purpose: Correct field appearances corrupted by the Preview application on the Mac
Author: George Johnson, acroscript@gmail.com, inspired by a similar script by Joel Geraci
Version: 1.0.0
Date last edited: 2010/12/18
Compatible with Acrobat/Reader 6-10
*/

// Add a menu item to the end of the File menu
app.addMenuItem({
    cName: "AS_correctFieldAppearances",
    cUser: "Fix Field Appearances",
    cParent: "File",
    cExec: "COM_ACROSCRIPT.correctFieldAppearances(this);",
    cEnable: "event.rc = (app.doc && numFields && (typeof xfa === \"undefined\"));"
});

// Create namespace to prevent potential name conflicts
var COM_ACROSCRIPT = {};

// This function does the work
COM_ACROSCRIPT.correctFieldAppearances = function (doc) {

    var i, j,
    f_name, f, fp, nWidgets, fw, cc,
    c1 = color.blue, c2 = color.yellow;  // These can be any color, as long as they are different

    // Suspend redrawing field appearances until the end of this script
    doc.delay = true;

    // Loop through all of the fields in the document
    for (i = 0; i < doc.numFields; i += 1) {

        // Get the name of the current field
        f_name = doc.getNthFieldName(i);

        // Get a reference to the current field
        f = doc.getField(f_name);

        switch (f.type) {

        case "button"    : break;  // No need to process buttons
        case "signature" : break;  // Digital signatures will not be present if saved with Preview

        default :  // text, checkbox, radiobutton, combobox, listbox

            // Get the page numbers on which the current field's widgets reside
            // typeof = number (for single widget) or object (array, more than one widget with the same name)
            fp = doc.getField(f_name).page;

            // Determine the number of widgets for the current field
            nWidgets = (typeof fp === "number") ? 1 : fp.length;

            // Loop through the current field's widgets
            for (j = 0; j < nWidgets; j += 1) {

                // Get a reference to the current widget
                fw = doc.getField(f_name + "." + j);

                // Save the current widget's border color
                cc = fw.strokeColor;

                // Set the current widget's stroke color to a temporary color,
                // either c1 or c2. Choose c2 if the current color equals c1
                fw.strokeColor = color.equal(cc, c1) ? c2 : c1;

                // Set the widget stroke color back to the original border color
                fw.strokeColor = cc;
            }

            break;
        }
    }

    // Allow Acrobat/Reader to redraw the field appearances
    doc.delay = false;

    app.alert("All fields have been processed.", 3, 0);
}  // That's all, folks!
		

Installation and Use

To create a folder-level JavaScript file that contains this code, copy and paste the script to a text editor. Save the file with an extension of ".js" and give it any name you like, such as "preview_fix.js". Alternatively, you can include the code in an existing folder-level JavaScript file. You will then need to install the file in the appropriate folder on your system, as Thom Parker discusses in the following tutorial: http://acrobatusers.com/tutorials/2006/folder_level_scripts

I would suggest installing it in the user JavaScript folder that is given by running this line of code in the Acrobat JavaScript interactive console:

// Show the path to the user JavaScript folder
app.getPath("user", "javascript");
		

Here is what it returns for me on various operating systems and versions of Acrobat:

Windows XP, Acrobat 9: /C/Documents and Setting/George/Application Data/Acrobat 9.0/JavaScripts

Mac OS 10.6.5, Acrobat 9: /Macintosh HD/Users/george/Library/Application Support/Adobe/Acrobat/9.0_x86/JavaScripts

Windows Vista, Acrobat 10: /C/Users/George/AppData/Roaming/Adobe/Acrobat/10.0/JavaScripts

Windows 7, Acrobat 9: /C/Users/George/AppData/Roaming/Adobe/Acrobat/9.0/JavaScripts

Once all open documents are closed and Acrobat or Reader is restarted, there will be a new menu item at "File > Fix Field Appearances". This menu item will become active when the document that is currently being viewed has at least one form field of any type, including a button.

Discussion

Because Preview is the default PDF viewer for a majority of Mac users, the problem it causes for PDF forms has become increasingly prevalent. You can quickly tell in Acrobat or Reader if a PDF has been saved with Preview by checking the producer property by selecting: File > Properties > Description > PDF Producer. If saved by Preview, it will show something like: Mac OS X 10.6.5 Quartz PDFContent 

It is important to understand that this script does not correct all of the corruption that Preview causes. No script is able to do that. It simply makes the data in the fields become visible when the form is viewed and printed in Acrobat or Reader. Corrupted forms that are processed by this script can be safely viewed, printed, and the form data can be exported with Acrobat, but the forms should not be used interactively thereafter. The form related corruption caused by Preview is extensive and includes radio buttons getting converted to check boxes, removal of digital signature fields, removal of field actions such as JavaScripts, and altering a number of other field properties such as "Allow user to enter custom text" with combo boxes. 

This script can be used with Adobe Reader. There is no need to prevent Reader users from recreating the field appearances and viewing or printing the form. In fact, this approach may be most useful for Reader users since there is no other quick and easy solution. Users of Acrobat can achieve the same result by simply exporting the form data to a file and re-importing the data back into the form, but Reader users do not have this option. Reader will not be able to save the form after it has been processed by the script, since saving with Preview also removes any usage rights that may have been present.

This script is nondestructive and can safely be used on forms that have not been saved with Preview, which is one reason I did not include code that attempts to detect if the document was modified by Preview. If a non-Preview-corrupted form is processed with the script, no lasting changes to the document are made apart from setting the document's dirty flag to true, so no harm is done. XFA forms, those created with LiveCycle Designer, are not processed by the script. Preview is not able to view XFA forms, and because the code used will not work with XFA forms, they are excluded.

Advantages of this script include:

  • Processes fields of all types (processing buttons and digital signatures is unnecessary)
  • Works with Acrobat and Reader, versions 6-10
  • Maintains field values
  • It's Free!

Please post comments if you have any questions or have suggestions for improving the script.

About the contributor

I have been working with PDF forms professionally ever since they were first available with Acrobat 3 and have been programming with JavaScript in Acrobat since it was added to Acrobat 3 in early 1998. Over the years, I have enjoyed learning and helping others in the various Acrobat related forums.

Creative Commons License
This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License