ccnmtl / fdfgen

port of PDF fdfgen library for filling in PDF forms to Python
BSD 3-Clause "New" or "Revised" License
171 stars 35 forks source link

Hierarchical fields #39

Open muesliflyer opened 6 years ago

muesliflyer commented 6 years ago

I needed to fill forms (e.g., US tax forms) with hierarchical fields (e.g., person1.address.city). This doesn't seem to be supported in fdfgen. So I modified the handle_data_strings function to handle inputs such as this:

{'person1': {
    'address': {
        'city': 'NewYork',
        'zip':  '12345'
    }
}}
def handle_data_strings(fdf_data_strings, fields_hidden, fields_readonly,
                        checkbox_checked_name):
    if isinstance(fdf_data_strings, dict):
        fdf_data_strings = fdf_data_strings.items()

    for (key, value) in fdf_data_strings:
        if value is True:
            value = b'/V' + FDFIdentifier(checkbox_checked_name).value
        elif value is False:
            value = b'/V' + FDFIdentifier('Off').value
        elif isinstance(value, FDFIdentifier):
            value = b'/V' + value.value
        elif isinstance(value, list) or isinstance(value, tuple) or isinstance(value, dict):
            value = \
                b'/Kids[\n' \
                + b''.join(handle_data_strings(value, fields_hidden, fields_readonly,
                                               checkbox_checked_name)) \
                + b']'
        else:
            value = b'/V' + b''.join([b'(', smart_encode_str(value), b')'])

        yield b''.join([
            b'<<',
            b'/T(',
            smart_encode_str(key),
            b')',
            value,
            handle_hidden(key, fields_hidden),
            b'',
            handle_readonly(key, fields_readonly),
            b'>>\n',
        ])

I tested it only briefly. So no guarantees. Feel free to integrate it into the code base. An alternative is to use the somewhat simpler (IMHO) xfdf form data format (also supported by pdftk).

<?xml version="1.0" encoding="UTF-8"?>
<xfdf xmlns="http://ns.adobe.com/xfdf/" xml:space="preserve">
<fields>
<field name="person1">
    <field name="address">
        <field name="city">
            <value>NewYork</value>
        </field>
        <field name="zip">
            <value>12345</value>
        </field>
    </field>
</field>
</fields>
</xfdf>

I wrote a simple hand-coded Python function to generate that and used pdftk to fill the form. I can share the function is anyone is interested.

muesliflyer commented 6 years ago

Here is the function that generates the xfdf format: generateXFDF.py