PHPWord icon indicating copy to clipboard operation
PHPWord copied to clipboard

Added the possibility to read FormFields from Word2007 documents

Open vincentKool opened this issue 3 years ago • 3 comments

Description

PHPWord had the option to create and write FormFields (checkbox, textinput and dropdown). This pull requests add the functionality to read those fields into the PHPWord model

Bugfixes

This Pull request fixes Bug #2281

Checklist:

  • [X] I have run composer run-script check --timeout=0 and no errors were reported
  • [X] The new code is covered by unit tests (check build/coverage for coverage report)
  • [ ] I have updated the documentation to describe the changes

vincentKool avatar Aug 20 '22 21:08 vincentKool

I've tested this and can confirm it works, hoping this will get merged so I don't have to use a fork 🙂

For anyone who wants to get all the form fields in a document, I've came up with this recursive solution:

/**
 * @param PhpWord $phpWord
 * @return FormField[]
 */
function getFormFields(PhpWord $phpWord)
{
    $fields = [];
    foreach($phpWord->getSections() as $section) {
        $fields = array_merge($fields, getFormFieldsRecursive($section));
    }
    return $fields;
}

/**
 * @param AbstractElement $element
 * @return FormField[]
 */
function getFormFieldsRecursive(AbstractElement $element)
{
    if ($element instanceof AbstractContainer) {
        $fields = [];
        foreach($element->getElements() as $nestedElement) {
            $fields = array_merge($fields, getFormFieldsRecursive($nestedElement));
        }
        return $fields;
    }

    if ($element instanceof Table) {
        $fields = [];
        foreach ($element->getRows() as $row) {
            foreach ($row->getCells() as $cell) {
                $fields = array_merge($fields, getFormFieldsRecursive($cell));
            }
        }
        return $fields;
    }

    if ($element instanceof FormField) {
        return [
            $element->getName() => $element,
        ];
    }

    return [];
}

$phpWord = IOFactory::createReader()->load('/path/to/file');

$fields = getFormFields($phpWord);

$fields['first_name']->setValue('Kuba');
$fields['date']->setValue(Carbon::now()->format('Y-m-d'));

IOFactory::createWriter($phpWord)->save('/path/to/generated-file');

KKSzymanowski avatar Dec 10 '23 14:12 KKSzymanowski

Hi

I was looking for something to ger the form fields from word, but the above @KKSzymanowski does not seem to work doc_with_form.docx

Attached word have a textbox, combo and a checkbox, but none is detected

What did I miss ?

rabol avatar Jan 29 '24 13:01 rabol

After this comment I was messing around with these text fields and decided I'm gonna use PHPWord in a very limited scope. The issue was after I saved the file with fields filled out the formatting was all out of whack.

I only use the XMLReader from PHPWord to open the Word file easier than manually. Here's the complete class used to read all available form fields and then fill them out with values. Not the cleanest thing I wrote but I'm glad it worked at all because I was under time pressure to deliver this.

https://gist.github.com/KKSzymanowski/acf892616805aed9900289b9bb1ede6d

Keep in mind I only used that for text form fields, may need extending to work for checkboxes or comboboxes.

I use it like this:

$fileName = (new FormFieldHelper($templatePath))
    ->setFieldValues($variables)
    ->save(storage_path($path));

$variables is an array where keys are the form field names and values are the actual values we want assigned to them.

To get the field names without setting the values I use:

(new FormFieldHelper($templatePath))->getFieldNames();

KKSzymanowski avatar Jan 29 '24 13:01 KKSzymanowski