-
Notifications
You must be signed in to change notification settings - Fork 104
/
Copy pathpdf_form_fill_fdf_merge.go
130 lines (112 loc) · 3.45 KB
/
pdf_form_fill_fdf_merge.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/*
* Merge form data from FDF file to output PDF - flattened.
*
* Run as: go run pdf_form_fill_fdf_merge.go template.pdf input.fdf output.pdf
*/
package main
import (
"fmt"
"os"
"github.com/unidoc/unipdf/v3/annotator"
"github.com/unidoc/unipdf/v3/common/license"
"github.com/unidoc/unipdf/v3/fdf"
"github.com/unidoc/unipdf/v3/model"
)
func init() {
// Make sure to load your metered License API key prior to using the library.
// If you need a key, you can No Sign up and create a free one at https://cloud.unidoc.io
err := license.SetMeteredKey(os.Getenv(`UNIDOC_LICENSE_API_KEY`))
if err != nil {
panic(err)
}
}
// Example of merging fdf data into a form.
func main() {
if len(os.Args) < 4 {
fmt.Printf("Merge in form data from FDF to output PDF - flattened\n")
fmt.Printf("Usage: go run pdf_form_fill_fdf_merge.go template.pdf input.fdf output.pdf\n")
os.Exit(1)
}
templatePath := os.Args[1]
fdfPath := os.Args[2]
outputPath := os.Args[3]
flatten := false
err := fdfMerge(templatePath, fdfPath, outputPath, flatten)
if err != nil {
fmt.Printf("Error: %v\n", err)
os.Exit(1)
}
fmt.Printf("Success, output written to %s\n", outputPath)
}
// fdfMerge loads template PDF in `templatePath` and FDF form data from `fdfPath` and fills into the fields,
// flattens (if flatten specified) and outputs as a PDF to `outputPath`.
func fdfMerge(templatePath, fdfPath, outputPath string, flatten bool) error {
fdfData, err := fdf.LoadFromPath(fdfPath)
if err != nil {
return err
}
f, err := os.Open(templatePath)
if err != nil {
return err
}
defer f.Close()
pdfReader, err := model.NewPdfReader(f)
if err != nil {
return err
}
// Populate the form data.
err = pdfReader.AcroForm.Fill(fdfData)
if err != nil {
return err
}
// Flatten form.
if flatten {
fieldAppearance := annotator.FieldAppearance{OnlyIfMissing: true, RegenerateTextFields: true}
// NOTE: To customize certain styles try:
// style := fieldAppearance.Style()
// style.CheckmarkGlyph = "a22"
// style.AutoFontSizeFraction = 0.70
// fieldAppearance.SetStyle(style)
//
// or for specifying a full set of appearance styles:
// fieldAppearance.SetStyle(annotator.AppearanceStyle{
// CheckmarkGlyph: "a22",
// AutoFontSizeFraction: 0.70,
// FillColor: model.NewPdfColorDeviceGray(0.8),
// BorderColor: model.NewPdfColorDeviceRGB(1, 0, 0),
// BorderSize: 2.0,
// AllowMK: false,
// })
err = pdfReader.FlattenFields(true, fieldAppearance)
if err != nil {
return err
}
} else {
fieldAppearance := annotator.FieldAppearance{OnlyIfMissing: true, RegenerateTextFields: true}
for _, field := range pdfReader.AcroForm.AllFields() {
for _, wa := range field.Annotations {
// appgen generates the appearance based on the form/field/annotation and other settings
// based on the implementation (for example may only generate appearance if none set).
apDict, err := fieldAppearance.GenerateAppearanceDict(pdfReader.AcroForm, field, wa)
if err != nil {
return err
}
wa.AP = apDict
// Force update of the widget appearance.
_ = wa.ToPdfObject()
}
}
}
// Don't copy AcroForm when flattening.
opt := &model.ReaderToWriterOpts{
SkipAcroForm: flatten,
}
// Generate a PdfWriter instance from existing PdfReader.
pdfWriter, err := pdfReader.ToWriter(opt)
if err != nil {
return err
}
// Write to file.
err = pdfWriter.WriteToFile(outputPath)
return err
}