124 lines
3.3 KiB
Go
124 lines
3.3 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"flag"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
"text/template"
|
|
|
|
"github.com/jung-kurt/gofpdf"
|
|
)
|
|
|
|
var (
|
|
flagInputCsv = flag.String("csv", "", "CSV file (downloaded from Patreon)")
|
|
flagOutputPdf = flag.String("o", "out.pdf", "filename to output PDF to")
|
|
flagPortrait = flag.Bool("portrait", true, "portrait mode?")
|
|
flagUnitStr = flag.String("unitStr", "mm", "units to use for other measurements")
|
|
flagPaperType = flag.String("paper", "Letter", "paper size")
|
|
flagCols = flag.Int("cols", 3, "number of columns")
|
|
flagRows = flag.Int("row", 10, "number of rows")
|
|
flagSkipLabels = flag.Int("skip", 0, "skip labels (useful for printing on partially-printed label sheets")
|
|
flagOffsetX = flag.Float64("x", 6.5, "left margin")
|
|
flagOffsetY = flag.Float64("y", 12.7, "top margin")
|
|
flagLabelWidth = flag.Float64("w", 66.8, "label width")
|
|
flagLabelHeight = flag.Float64("h", 25.4, "label height")
|
|
flagGapX = flag.Float64("gapx", 3.4, "gap between columns")
|
|
flagGapY = flag.Float64("gapy", 0., "gap between rows")
|
|
flagDrawLines = flag.Bool("lines", false, "draw lines?")
|
|
flagFontSize = flag.Float64("fontsize", 10, "font size")
|
|
flagFontFamily = flag.String("fontfamily", "Arial", "font family")
|
|
flagFontStyle = flag.String("fontstyle", "", "font style (B for bold)")
|
|
flagTemplate = flag.String("template", "{{.Addressee}}\n{{.Street}}\n{{.City}}, {{.State}}\n{{.Zip}}, {{.Country}}\n", "mailing label template")
|
|
lineHeight = 4.0
|
|
)
|
|
|
|
func main() {
|
|
flag.Parse()
|
|
|
|
if *flagInputCsv == "" {
|
|
fmt.Println("Must specify input csv with -csv")
|
|
flag.Usage()
|
|
os.Exit(1)
|
|
}
|
|
|
|
pL := "P"
|
|
if !*flagPortrait {
|
|
pL = "L"
|
|
}
|
|
|
|
pdf := gofpdf.New(pL, *flagUnitStr, *flagPaperType, "")
|
|
pdf.SetFont(*flagFontFamily, *flagFontStyle, *flagFontSize)
|
|
data := LoadCSVFromFile(*flagInputCsv)
|
|
DoTheThing(pdf, data)
|
|
|
|
err := pdf.OutputFileAndClose(*flagOutputPdf)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
func DoTheThing(pdf *gofpdf.Fpdf, data CSV) {
|
|
tpl, err := template.New("mailing labels").Parse(*flagTemplate)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
tr := pdf.UnicodeTranslatorFromDescriptor("")
|
|
for i := 0; i < data.NumRecords(); {
|
|
AddGriddedPage(pdf)
|
|
|
|
for x := 0; x < *flagCols; x++ {
|
|
for y := 0; y < *flagRows; y++ {
|
|
if *flagSkipLabels > 0 {
|
|
*flagSkipLabels--
|
|
continue
|
|
}
|
|
for ; i < data.NumRecords() && data.PatreonEmptyAddress(i); i++ {
|
|
fmt.Printf("Warning: skipping empty addressee: %s\n", data.GetField(i, "Name"))
|
|
fmt.Printf("%v\n", data.Record(i))
|
|
}
|
|
if i >= data.NumRecords() {
|
|
return
|
|
}
|
|
|
|
lx := *flagOffsetX + (*flagLabelWidth + *flagGapX) * float64(x) + 4.
|
|
ly := *flagOffsetY + (*flagLabelHeight + *flagGapY) * float64(y) + 8.
|
|
|
|
var buf bytes.Buffer
|
|
err := tpl.Execute(&buf, data.Record(i))
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
DrawText(pdf, tr(buf.String()), lx, ly)
|
|
|
|
i++
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func AddGriddedPage(pdf *gofpdf.Fpdf) {
|
|
pdf.AddPage()
|
|
if !*flagDrawLines {
|
|
return
|
|
}
|
|
|
|
for x := 0; x < *flagCols; x++ {
|
|
for y := 0; y < *flagRows; y++ {
|
|
lx := *flagOffsetX + (*flagLabelWidth + *flagGapX) * float64(x)
|
|
ly := *flagOffsetY + (*flagLabelHeight + *flagGapY) * float64(y)
|
|
pdf.Rect(lx, ly, *flagLabelWidth, *flagLabelHeight, "D")
|
|
}
|
|
}
|
|
}
|
|
|
|
func DrawText(pdf *gofpdf.Fpdf, str string, x, y float64) {
|
|
lines := strings.Split(str, "\n")
|
|
for _, s := range lines {
|
|
pdf.Text(x, y, s)
|
|
y += lineHeight
|
|
}
|
|
} |