
Cuando alguien rellena un formulario PDF y lo guarda, los valores introducidos residen dentro de las estructuras de campos del documento, no como texto plano que se pueda buscar o copiar de forma masiva. En un formulario con treinta o cuarenta campos, la transcripción manual se convierte en un cuello de botella. El problema de fondo es que cada tipo de campo almacena su valor de forma distinta: un cuadro de texto expone una cadena, una casilla de verificación informa un valor booleano, un cuadro combinado separa las opciones de la selección y un botón de opción almacena el elemento elegido. No existe una única llamada uniforme del tipo "dame el valor".
Este artículo explica cómo extraer los valores de los campos de formulario de un PDF con Spire.PDF for JavaScript. La biblioteca se ejecuta sobre WebAssembly en el navegador, por lo que el documento se analiza localmente a través de un sistema de archivos virtual, sin ida y vuelta al servidor. Verá cómo recorrer la colección de campos, despachar según el tipo de cada campo y leer la propiedad correcta para cuadros de texto, cuadros de lista, cuadros combinados, botones de opción y casillas de verificación.
Para la configuración del proyecto, consulte Integrar Spire.PDF for JavaScript en un proyecto de React. El código siguiente supone que Spire.PDF está instalado y que el módulo WASM está inicializado.
Tipos de campos de un vistazo
Antes de sumergirse en la implementación, conviene trazar cómo expone su valor cada tipo de campo. Spire.PDF for JavaScript representa los campos de formulario como clases de widget, y la propiedad que contiene el valor actual difiere de un tipo a otro:
| Tipo de campo | Clase de widget | Propiedad a leer | Notas |
|---|---|---|---|
| Cuadro de texto | PdfTextBoxFieldWidget |
Text |
Devuelve directamente la cadena introducida. |
| Cuadro de lista | PdfListBoxWidgetFieldWidget |
SelectedValue |
Values es la lista completa de opciones, no la elección del usuario. |
| Cuadro combinado | PdfComboBoxWidgetFieldWidget |
SelectedValue |
El mismo modelo de doble propiedad que el cuadro de lista. |
| Botón de opción | PdfRadioButtonListFieldWidget |
Value |
Proporciona la cadena del elemento seleccionado en un solo paso. |
| Casilla de verificación | PdfCheckBoxWidgetFieldWidget |
Checked |
Estado booleano. Value es undefined; no la use. |
El patrón es claro: no existe una única propiedad universal. La lógica de extracción debe comprobar el tipo de cada campo y leer la propiedad correspondiente, que es exactamente lo que implementa la sección siguiente.
Recorrer los campos y leer según el tipo
El flujo de trabajo principal tiene tres pasos: cargar el PDF, obtener su formulario como un PdfFormWidget y luego recorrer la colección FieldsWidget y ramificar según la clase de cada campo con instanceof. En cada rama, lea la propiedad específica del tipo y añada el resultado a una cadena de informe. Como el despacho cubre todos los tipos admitidos, no necesita saber de antemano qué campos contiene el documento: los campos no reconocidos simplemente caen en una etiqueta predeterminada.
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;
Cuando el bucle termina, la cadena de informe contiene una línea por campo con su nombre, tipo y valor actual. El archivo se escribe en el sistema de archivos virtual y luego se descarga como un archivo de texto:

La cadena de instanceof es el corazón del enfoque. Cada rama sabe exactamente qué propiedad debe leer, por lo que la salida es correcta sin importar cuántos tipos de campo mezcle el documento. Las tres secciones siguientes abordan los escollos que surgen cuando la propiedad de valor de un campo no es la que podría esperarse.
Casillas de verificación: Checked frente a Value
Un error común al leer campos de casilla de verificación es recurrir a una propiedad Value. El widget de casilla de verificación —PdfCheckBoxWidgetFieldWidget— no expone Value en absoluto; intentar leerla devuelve undefined. Internamente, una casilla de verificación registra su estado mediante valores de exportación: Off cuando no está marcada, y Yes o una cadena de exportación personalizada cuando está marcada. Una cadena sin procesar no puede indicar de forma fiable si la casilla está seleccionada, por lo que la superficie de la API omite deliberadamente Value y ofrece Checked en su lugar.
La solución es sencilla: use siempre la propiedad booleana Checked:
// Check the state with Checked, not Value
const checked = field.Checked;
Esta devuelve true cuando la casilla está marcada y false en caso contrario, lo que le proporciona un booleano limpio para la lógica posterior sin necesidad de analizar cadenas.
Cuadros de lista y cuadros combinados: SelectedValue frente a Values
Los cuadros de lista y los cuadros combinados comparten un modelo de datos de dos partes que desconcierta a muchos desarrolladores. Tanto PdfListBoxWidgetFieldWidget como PdfComboBoxWidgetFieldWidget exponen una colección Values y una cadena SelectedValue, y es fácil suponer que Values contiene la entrada del usuario. No es así.
Values es el conjunto completo de opciones disponibles. Cada elemento de la colección es un objeto PdfListWidgetItem, por lo que debe desenvolverlo con .Value para obtener el texto de la opción. Recorrer Values le indica lo que el usuario podría haber elegido, no lo que eligió realmente. La selección real del usuario está en SelectedValue como una cadena simple.
Use SelectedValue para el valor actual, y recorra Values solo cuando necesite enumerar las opciones disponibles:
// 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);
}
Es esencial no confundir estas dos propiedades: tratar Values como la respuesta le da la lista de opciones en lugar del resultado rellenado, y ambas raramente tienen la misma longitud.
Manejo de PDF cifrados
La extracción de formularios comienza con la apertura del documento. Si el PDF está protegido con contraseña, llamar a LoadFromFile solo con el nombre del archivo genera un error —"Can not open an encrypted document. The password is invalid."— y no se devuelve ningún objeto de documento. Nunca se llega a los campos del formulario.
La solución es pasar la contraseña de apertura como segundo argumento:
doc.LoadFromFile(inputFileName, 'spire123');
Una vez que el documento se abre correctamente, el resto del flujo de extracción —crear el PdfFormWidget, recorrer los campos y despachar según el tipo— funciona exactamente igual que con un archivo sin cifrar. La contraseña solo controla la carga inicial; no cambia la forma en que se leen los valores de los campos.
Véase también
- Integrar Spire.PDF for JavaScript en un proyecto de React: configuración, instalación e inicialización de WASM
- Rellenar campos de formulario PDF con Spire.PDF for JavaScript: escribir valores en los campos del formulario mediante programación
- Importar y exportar datos de formularios PDF con Spire.PDF for JavaScript: serializar los datos del formulario en archivos FDF/XFDF
Si desea eliminar el mensaje de evaluación del documento resultante, o deshacerse de las limitaciones de funciones, contacte con ventas para obtener una licencia temporal válida durante 30 días.