-
Notifications
You must be signed in to change notification settings - Fork 102
/
Copy pathpdf_form_fill_fdf_merge.go
134 lines (115 loc) · 3.37 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
131
132
133
134
/*
* 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"
"github.com/unidoc/unipdf/v3/fdf"
"github.com/unidoc/unipdf/v3/model"
)
// 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)
}
// Enable debug-level logging.
common.SetLogger(common.NewConsoleLogger(common.LogLevelDebug))
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()
}
}
}
// Write out.
pdfWriter := model.NewPdfWriter()
if flatten {
pdfWriter.SetForms(nil)
} else {
pdfReader.AcroForm.ToPdfObject()
pdfWriter.SetForms(pdfReader.AcroForm)
}
for _, p := range pdfReader.PageList {
err := pdfWriter.AddPage(p)
if err != nil {
return err
}
}
fout, err := os.Create(outputPath)
if err != nil {
return err
}
defer fout.Close()
err = pdfWriter.Write(fout)
return err
}