Extract PDF Form Field Values Using JavaScript in React

A form-based PDF keeps its whole value in what was filled in, but once the file is filed away or handed over, that data is locked inside the layout. To find out what a field holds you have to open a reader and copy it out one by one; with a few dozen fields, transcribing by hand is slow and easy to get wrong. Before those values can be validated, imported into a database, or used to track an order, the program has to be able to read them out first.

This article shows how to extract form field values from an existing PDF with Spire.PDF for JavaScript: walk the field collection, determine each field's type, then read the current value of each text box, list box, combo box, radio button, and check box by type. Spire.PDF for JavaScript is built on WebAssembly and opens and parses documents in the browser, so the whole read happens locally. Files are read and written through a virtual file system (VFS), with no backend involved.

This article covers one core feature:

For installation and project configuration, see Integrate Spire.PDF for JavaScript in a React Project. The examples below assume Spire.PDF is installed and the WebAssembly module is initialized.


Extract All Form Field Values

Spire.PDF for JavaScript provides PdfFormWidget to take over the form fields already present in a document; FieldsWidget is its field collection, and fields can be pulled out one by one by index. The value properties are not uniform across field types: a text box keeps its value on Text, a check box is judged by Checked, list boxes and combo boxes split into an option collection and a selected value, and a radio button is read straight from Value. So once a field is in hand, dispatch on its type and then read the matching value, writing the type name into the result alongside it — you never need to know in advance which fields the document contains.

function App() {
  const getAllFieldValues = async () => {
    // Get the Spire.PDF WASM module
    const pdfModule = window.wasmModule?.spirepdf;

    // Check that the module is ready
    if (!pdfModule) {
      alert('Spire.PDF is not ready yet');
      return;
    }

    // Load the PDF file to be read into the VFS
    const inputFileName = 'ApplicationForm.pdf';
    await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}/data/`);

    // Create a PdfDocument object and load the PDF document
    const doc = new pdfModule.PdfDocument();
    doc.LoadFromFile(inputFileName);

    // Build a PdfFormWidget from the document's form handle; FieldsWidget is its field collection
    const formWidget = new pdfModule.PdfFormWidget(doc.Form.H);
    const fields = formWidget.FieldsWidget;

    let report = '';

    // Walk the field collection, check each type, and read the matching value
    for (let i = 0; i < fields.Count; i++) {
      const field = fields.get_Item({ index: i });

      // Both the type name and the value are filled in by the type dispatch
      let type = 'Unknown';
      let value = '(Unrecognized field type)';

      if (field instanceof pdfModule.PdfTextBoxFieldWidget) {
        // Text box field: read Text directly
        type = 'TextBox';
        value = field.Text;
      } else if (field instanceof pdfModule.PdfListBoxWidgetFieldWidget) {
        // List box field: Values holds every option, SelectedValue is the current one
        const options = [];
        for (let j = 0; j < field.Values.Count; j++) {
          options.push(field.Values.get_Item(j).Value);
        }
        type = 'ListBox';
        value = `Selected ${field.SelectedValue}, options ${options.join(', ')}`;
      } else if (field instanceof pdfModule.PdfComboBoxWidgetFieldWidget) {
        // Combo box field: like a list box, it has an option collection and a selected value
        const options = [];
        for (let j = 0; j < field.Values.Count; j++) {
          options.push(field.Values.get_Item(j).Value);
        }
        type = 'ComboBox';
        value = `Selected ${field.SelectedValue}, options ${options.join(', ')}`;
      } else if (field instanceof pdfModule.PdfRadioButtonListFieldWidget) {
        // Radio button field: Value is the selected item
        type = 'RadioButton';
        value = `Selected ${field.Value}`;
      } else if (field instanceof pdfModule.PdfCheckBoxWidgetFieldWidget) {
        // Check box field: Checked gives the state, not Value
        type = 'CheckBox';
        value = field.Checked ? 'Checked' : 'Not checked';
      }

      report += `Field "${field.Name}" (${type}): ${value}\n`;
    }

    const outputFileName = 'AllFieldValues.txt';
    window.dotnetRuntime.Module.FS.writeFile(outputFileName, report);
    doc.Close();

    // Read the generated file from the VFS and trigger the download
    const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
    const blob = new Blob([fileArray], { type: 'text/plain' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = outputFileName;
    a.click();
    URL.revokeObjectURL(url);
  };

  return (
    <div style={{ textAlign: 'center', height: '300px' }}>
      <h1>Extract Form Field Values</h1>
      <button onClick={getAllFieldValues}>
        Extract values
      </button>
    </div>
  );
}

export default App;

The values collected by walking every form field:

The values collected by walking every form field


FAQ

A check box's Value doesn't give you its state

Cause: The check box widget (PdfCheckBoxWidgetFieldWidget) has no Value property — reading it gets you undefined. A check box tracks its state through export values: Off when it is not ticked, Yes or a custom export value when it is. A string value cannot tell you whether the box is checked.

Solution: Use Checked for the state:

// Check the state with Checked, not Value
const checked = field.Checked;

Should a list box or combo box be read with SelectedValue or Values

Cause: For these two fields Values is the full option set — walking it gives you every choice, and each entry is a PdfListWidgetItem whose .Value is the option text, so the item has to be unwrapped one more time; the item the user actually selected lives on SelectedValue. Treat Values as the value and what you get is not the filled-in result.

Solution: Read SelectedValue for the current value; walk Values only when you need to show the available range:

// The text of the currently selected item
const selected = field.SelectedValue;

// Every available option
const options = [];
for (let j = 0; j < field.Values.Count; j++) {
  options.push(field.Values.get_Item(j).Value);
}

Loading an encrypted PDF throws "Can not open an encrypted document. The password is invalid."

Cause: Reading a form means the document has to open first; when the document is password-protected, LoadFromFile without the password throws during loading, and no empty document comes back.

Solution: Pass the open password as the second argument to LoadFromFile:

doc.LoadFromFile(inputFileName, 'spire123');

Get a Free License

If you want to remove the evaluation message from the result document, or to get rid of the feature limitations, contact sales for a temporary license valid for 30 days.