今回はGo言語でPDFを扱ってみます。既に領収書のひな形がある場合を想定してします。既存のPDFを読み込んで、そこに新たなテキストを書き込んでみましょう。前編の今回はgopdfのセットアップと簡単な使い方を確認してみましょう。

  • Go言語PDFを書き込んだところ

    Go言語PDFを書き込んだところ

gopdfを使おう

Go言語向けのPDFライブラリには、gopdfのほかにgofpdfなどいろいろなものがあります。それでも、最も利用されているのがgopdfです。日本語フォントに対応しており美しい日本語のPDFを生成できます。タイの会社が開発しているそうで、マルチバイト言語の対応がしっかりしているので安心です。

一番簡単なgopdfの使い方

まずは、一番簡単なサンプルで使い方を確認してみましょう。なお、本稿では、go1.16を利用してプログラムを実行する手順を紹介します。go1.16ではモジュール対応モード (module-aware mode)がデフォルトでonに設定されているため、これまで従来のGOPATHモードを使ってきた方はプロジェクトを始める手順に変更があります。その点も含めて手順を確認しながら作業していきましょう。

最初に適当なフォルダで、コマンドライン(WindowsならPowerShell、macOSならターミナル)を開いて、以下のコマンドを実行して、makepdfモジュールを作成します。

go mod init makepdf

すると、go.mod というファイルが作成されます。そして、このファイルをテキストファイルなどで開いて、gopdfを利用する旨(2行目の一行)を追記します。

module makepdf
require github.com/signintech/gopdf v0.9.15

その後、以下のコマンドを実行して、gopdfモジュールのインストールを行います。

go mod download github.com/signintech/gopdf

なお、モジュールをダウンロードしたのち、以下のコマンドを実行して、go.sumファイルを生成する必要があります。

go mod tidy

それから、今回PDFに日本語フォントを使います。そこで、今回は無料で自由に使えるIPAexフォントを使うことにします。こちらからIPAexフォント(IPAexゴシック)をダウンロードしましょう。

フォントを解凍したら、プログラムと同じフォルダにフォントファイル「ipaexg.ttf」をコピーしましょう。これから「makepdf.go」というプログラムを作成します。すると、フォルダ構成は以下のようになります。

  • プロジェクトの様子

    プロジェクトの様子

以下はメインプログラム「makepdf.go」の内容です。PDFにテキストを書き込み、「hello.pdf」という名前で保存するプログラムです。

package main

import (
    "github.com/signintech/gopdf"
)

func main() {
    // gopdf のオブジェクトを作成 --- (*1)
    pdf := gopdf.GoPdf{}
    // A4のページを作る --- (*2)
    pdf.Start(gopdf.Config{PageSize: *gopdf.PageSizeA4})
    // TTFフォントを取り込む --- (*3)
    err := pdf.AddTTFFont("ipaexg", "./ipaexg.ttf"    )
    if err != nil {
        panic(err)
    }
    err = pdf.SetFont("ipaexg", "", 26) // フォントサイズを選択
    if err != nil {
        panic(err)
    }
    // 文字を書き込む --- (*4)
    pdf.AddPage()
    pdf.SetX(80)
    pdf.SetY(130)
    pdf.Cell(nil, "洞察力があればすぐに怒ることはない")
    pdf.SetX(80)
    pdf.SetY(180)
    pdf.Cell(nil, "過ちを見過ごす人は美しい")
    // PDFをファイルに書き出す --- (*5)
    pdf.WritePdf("hello.pdf")
}

プログラムを実行してみましょう。コマンドラインから以下のコマンドを実行すると、Goのプログラムが実行されて「hello.pdf」というPDFファイルが作成されます。

go run .

作成されたPDFを見ると、次のように格言が二行書き込まれています。

  • 作成されたPDF

    作成されたPDF

プログラムを確認してみましょう。(*1)ではgopdfのオブジェクトを作成します。そして、(*2)では作成するPDFの用紙サイズをA4にセットします。

(*3)ではTTFフォントを取り込みます。ここではAddTTFFontメソッドを使ってカレントフォルダにあるTTFフォントファイル「ipaexg.ttf」をipaexgという名前で使う事を指定します。その後、SetFontメソッドを使って、その後利用するフォントとサイズを指定します。

(*4)の部分で文字を書き込みます。SetXとSetYメソッドを使ってテキストを書き込む座標を指定して、Cellメソッドでテキストを書き込みます。なお、PDFの座標系は左下が(0, 0)となるのが普通ですが、gopdfではプログラマーに馴染みやすいよう、左上が(0, 0)となるように配慮されています。

また、gopdfではデフォルトのサイズはPoint(pt)で指定するようになっています。Startメソッドで用紙サイズなどを指定する際に、以下のように記述すると単位をmmに変更することもできます。

//595.28pt, 841.89pt = A4
pdf.Start(gopdf.Config{
    Unit: "mm", 
    PageSize: gopdf.Rect{W: 210.0, H: 297.0}})

罫線を引いてみよう

続いて、上記のプログラムを改良して罫線を引いてみましょう。また罫線に合わせて文字も書き込んでみます。下記のプログラムを上記と同じ「makepdf.go」に書き込みましょう。

package main

import (
    "github.com/signintech/gopdf"
)

func main() {
    // gopdf のセットアップ --- (*1)
    pdf := gopdf.GoPdf{}
    pdf.Start(gopdf.Config{PageSize: *gopdf.PageSizeA4})
    // ページサイズの取得 --- (*2)
    pw := gopdf.PageSizeA4.W
    ph := gopdf.PageSizeA4.H
    ww := 40.0
    // TTFフォントを取り込む --- (*3)
    err := pdf.AddTTFFont("ipaexg", "./ipaexg.ttf"    )
    if err != nil {
        panic(err)
    }
    err = pdf.SetFont("ipaexg", "", int(ww)) // フォントサイズを選択
    if err != nil {
        panic(err)
    }
    pdf.AddPage()
    // 繰り返し罫線を描画する --- (*4)
    for i := 1; i < int(ph/ww); i++ {
        if i%10 == 0 {
            pdf.SetLineWidth(0.8)
            pdf.SetStrokeColor(50, 50, 100    )
        } else {
            pdf.SetLineWidth(0.3)
            pdf.SetStrokeColor(100, 100, 130)
        }
        x, y := float64(i)*ww, float64(i)*ww
        pdf.Line(x, 0, x, ph)
        pdf.Line(0, y, pw, y)
    }
    // 文字を分割して1文字ずつ罫線に書き込む --- (*5)
    text := []rune("洞察力があればすぐに怒ることはない。" +
        "過ちを見過ごす人は美しい。")
    cx, cy := int(pw/ww), int(ph/ww)
    for i := 0; i < cx*cy; i++ {
        pdf.SetX(float64(i%cx) * ww)
        pdf.SetY(float64(int(i/cx)) * ww)
        pdf.SetFillColor(100+uint8(i%100), 100, 100+uint8(i%50))
        pdf.Cell(nil, string(text[i%len(text)]))
    }
    // PDFをファイルに書き出す --- (*6)
    pdf.WritePdf("keisen.pdf")
 }

そして同じように「go run .」とコマンドラインで実行しましょう。すると、「keisen.pdf」というPDFファイルが作成されます。

  • PDFを書き込んだところ

    PDFを書き込んだところ

プログラムを確認してみましょう。(*1)ではgopdfをA4サイズにセットアップします。(*2)ではA4のページサイズを取得します。ここでは、デフォルトのPoint(pt)が単位です。また、変数wwに40ptを指定して罫線のサイズを指定します。(*3)ではTTFフォントを取り込み、フォントサイズを指定します。

(*4)で罫線を描画します。罫線を描画するには、Lineメソッドを使います。線の太さはSetLineWidthで、線の色はSetStrokeColorで指定します。

そして、(*5)では文字を1文字ずつに分割して、for文を使って1文字ずつ枠の中に描画します。最後、(*6)ではファイルでPDFを書き込みます。

まとめ

以上、今回はgopdfを利用してPDFを生成してみました。gopdfは用紙サイズも最初から定義されており、指定する単位も選べるようになっています。そして、なにより日本語が何も考えなくても使えるというのは良い点です。次回はいよいよひな形となる領収書に書き込みをしてみます。お楽しみに。

自由型プログラマー。くじらはんどにて、プログラミングの楽しさを伝える活動をしている。代表作に、日本語プログラミング言語「なでしこ」 、テキスト音楽「サクラ」など。2001年オンラインソフト大賞入賞、2004年度未踏ユース スーパークリエータ認定、2010年 OSS貢献者章受賞。技術書も多く執筆している。直近では、「シゴトがはかどる Python自動処理の教科書(マイナビ出版)」「すぐに使える!業務で実践できる! PythonによるAI・機械学習・深層学習アプリのつくり方 TensorFlow2対応(ソシム)」「マンガでざっくり学ぶPython(マイナビ出版)」など。