benoitkugler / pdf

Golang high level PDF model
MIT License
22 stars 3 forks source link

Fill checkboxes in PDF #10

Closed Chroq closed 4 months ago

Chroq commented 5 months ago

Hi,

I'm trying to fill a PDF with checkbox but I don't find the way to check them. I've found FDFText, FDFChoices and FDFName but no one seems to fit. Am I wrong ?

Thank you for your help

benoitkugler commented 5 months ago

Hi Christophe,

Checkbox in PDF forms are a bit tricky : the spec defines one value for the "not checked" state (/Off), but not for the checked one. It is the field dictionary which declares what key should be used to check the box. Thus, you have to first find what key the field is expecting, and then use FDFName(key) as the value for your field.

In f552815 I've added a convenience method on the FormFieldDict object to retrieve this key. For instance, you could use :

fields := doc.Catalog.AcroForm.Flatten()
checkKey := fields["the name of your field"].Field.CheckKey()
value := FDFName(checkKey)
// use 'value' in a FDFField

Let me know if this is helpful.

Chroq commented 4 months ago

Hello Benoit,

Thank you for the snippet and sorry for the delay. I have integrated it into my code, but I still can't get the checkboxes to work.

func (f Filler) Fill(values map[string]any) error {
    originalFields := f.Templater.Document.Catalog.AcroForm.Flatten()
    fields := make([]formfill.FDFField, 0, len(values))
    for key, value := range values {
        f := formfill.Values{}
        switch as := value.(type) {
        case string:
            f.V = formfill.FDFText(as)
        case []string:
            f.V = formfill.FDFChoices(as)
        case bool:
            checkKey := originalFields[key].Field.CheckKey()
            f.V = formfill.FDFName(checkKey)
        default:
            return referrors.NewInternal(context.TODO(), "invalid type for value")
        }

        fields = append(fields, formfill.FDFField{
            Values: f,
            T:      key,
        })
    }

Did I miss something ?

Chroq commented 4 months ago

I don't know if it's relevant or not, but I'm working on the french sick leave form we discuss previously. CERFA_SL.pdf

benoitkugler commented 4 months ago

Hum.. it is a trickier than I initially thought, because the PDF you use define several widgets for each checkbox (which is strange to me, but not forbidden by the spec and supported by readers). Thus, I can't really provide the CheckKey() method : in 0dded61, I've replaced it by AppearanceKeys() which supports more situations (but is also less precise). You should use it to detect the 'check key' before filling the form. In your case, it seems the key is always the same (/Oui).

Chroq commented 4 months ago

Hi Benoit,

First of all, thank you very much for your support, it is greatly appreciated. I was on vacation, so please accept my apologies for the delay.

Everything works great! I'll find a way to gracefully handle the AppearanceKeys, but as you mentioned, it always seems to be set to "/Oui".

I'm closing this issue since everything is working well now.

Thank you!