LoginSignup
0
1

GOとMySQLでPDFを編集

Posted at

はじめに

こちらのページの記事が面白かった
DBのレコード拾ってPDFの文言変えて遊んでみたので備忘録
test DBに下記のようなusersテーブルを作っておく

+------+--------+--------+------------+
| id   | name   | price  | date       |
+------+--------+--------+------------+
| 0001 | hoge   | 1000   | 2023-06-01 |
| 0002 | huga   | 2000   | 2023-07-01 |
| 0003 | wawawa | 500    | 2023-08-01 |
| 0004 | aheahe | 999    | 2023-06-30 |
| 0005 | aaa    | 100000 | 2023-07-31 |
+------+--------+--------+------------+

コード

こんな感じ

test.go
package main

import (
	"database/sql"
	"fmt"
	"strings"
	"regexp"
	"github.com/dustin/go-humanize"
	"github.com/signintech/gopdf"
	_ "github.com/go-sql-driver/mysql"
)

//レコード格納用の構造体
var (
	id   string
	name string
	price int
	date string
)

func main() {
	//ログイン情報取得
	var n string
	fmt.Println("DBのユーザ名を入力してください")
	fmt.Scan(&n)
	var m string
	fmt.Println("パスワードを入力してください")
	fmt.Scan(&m)
	//ログイン情報生成
	con := n + ":" + m + "@tcp(127.0.0.1:3306)/test"
	//検査
	db, err := sql.Open("mysql", con)
	defer db.Close()
	//設定誤りあれば出力
	if err != nil {
		fmt.Println("設定誤りを検知しました 下記参照し管理者に問い合わせてください")
		fmt.Println(err.Error())
	}
	//DB応答確認
	err = db.Ping()
	if err != nil {
		fmt.Println("ユーザ名かパスワードが間違っています")
		return
	} else {
		//成功したら入力を受け付け
		var n string
		fmt.Println("IDを入力してください")
		fmt.Scan(&n)
		//インジェクション対策(のつもり)
		if regexp.MustCompile(`^[0-9]{4}$`).MatchString(n) == false {
			fmt.Println("不正な入力値です")
			return
		}
		//入力値からクエリ生成
		sql, err := db.Query("SELECT * FROM users WHERE id = '" + n + "'")
		if err != nil {
			fmt.Println(err.Error())
			return
		}
		defer sql.Close()
		//各レコードを格納(と言っても1つしか出てこないけど)
		for sql.Next() {
			err = sql.Scan(&id, &name, &price, &date)
			if err != nil {
				panic(err.Error())
			}
		}
		//金額をカンマ区切りにする
		price := humanize.Comma(int64(price))
		//日付をハイフンで分割
		date := strings.Split(date, "-")
		//obj作成
		pdf := gopdf.GoPdf{}
		//サイズ指定
		A4 := *gopdf.PageSizeA4
		//横向き
		A4Yoko := gopdf.Rect{W: A4.H, H: A4.W}
		pdf.Start(gopdf.Config{PageSize: A4Yoko})
		pdf.AddPage()
		//インポート対象のファイルパス,ページ,PDFのボックス
		template := pdf.ImportPage("./template.pdf", 1, "/MediaBox")
		pageH := 1080 * (A4Yoko.W / 1920)
		pdf.UseImportedTemplate(template, 0, 0, A4Yoko.W, pageH)
		//ttfファイルを取込
		err = pdf.AddTTFFont("ipaexg", "./ipaexg.ttf")
		if err != nil {
			panic(err)
		}
		//DBから取得した氏名、日付、金額を挿入
		pdf.SetFont("ipaexg", "", 28)
		drawText(&pdf, 300, 150, name)
		pdf.SetFont("ipaexg", "", 15)
		drawText(&pdf, 570, 100, date[0])
		drawText(&pdf, 635, 100, date[1])
		drawText(&pdf, 676, 100, date[2])
		pdf.SetFont("ipaexg", "", 28)
		drawText(&pdf, 280, 200, "¥ " + price + "-")
		//IDでPDF命名すると誰宛の領収書かわかりやすい
		pdf.WritePdf("/tmp/" + id + ".pdf")
		fmt.Println(id + "の領収書を生成しました")
	}
}

func drawText(pdf *gopdf.GoPdf, x float64, y float64, s string) {
	pdf.SetX(x)
	pdf.SetY(y)
	pdf.Cell(nil, s)
}

コマンドラインからDBのユーザ名とパスワードとusersのID入れてクエリ叩いて結果を挿入する感じ
ID入力時に正規表現で引っかけてチェックしてるからクエリ実行時のエラーチェックはいらんかも

結果

うまいこと行ったっぽい
sheet.jpeg
pdf.Cell()が文字列型しか扱えないのがちょっと不便かな

参考文献

https://news.mynavi.jp/techplus/article/gogogo-16/
https://www.chuken-engineer.com/entry/2021/09/24/162120#6%E3%83%87%E3%83%BC%E3%82%BF%E3%82%92%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8BSELECT
請求書ひな型
https://kujirahand.com/blog/index.php?%E3%82%BC%E3%83%AD%E3%81%8B%E3%82%89%E3%81%AF%E3%81%98%E3%82%81%E3%82%8BGo%E8%A8%80%E8%AA%9E%E3%81%AE%E7%B4%A0%E6%9D%90

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1