gpdf でテーブルに縞模様(ゼブラ)の行を入れるには?
template.TableStripe を渡すだけ。gpdf が偶数行に背景色を塗ってくれる。行ループも手動スタイル指定も不要。
質問を言い換えると
請求書、取引履歴、ログ — 5 行を超えるテーブルを描くと、目線が次の行を見失う。Bootstrap で言う .table-striped、つまり 1 行おきにグレーが乗る縞模様を gpdf でも入れたい。行ループは書きたくない。
結論
c.Table(header, rows, template.TableStripe(pdf.RGBHex(0xF5F5F5)))
これだけ。gpdf が交互配色を担当する。ヘッダーは縞の対象外で、ボディ行のみが対象。1 行目はそのまま、2 行目に色、3 行目そのまま、4 行目に色、と続く。
動くコード
package main
import (
"log"
"os"
"github.com/gpdf-dev/gpdf"
"github.com/gpdf-dev/gpdf/document"
"github.com/gpdf-dev/gpdf/pdf"
"github.com/gpdf-dev/gpdf/template"
)
func main() {
doc := gpdf.NewDocument(
gpdf.WithPageSize(gpdf.A4),
gpdf.WithMargins(document.UniformEdges(document.Mm(20))),
)
brand := pdf.RGBHex(0x1A237E) // ヘッダー背景
stripe := pdf.RGBHex(0xF5F5F5) // 1 行おきの縞
page := doc.AddPage()
page.AutoRow(func(r *template.RowBuilder) {
r.Col(12, func(c *template.ColBuilder) {
c.Text("第 1 四半期 売上", template.FontSize(20), template.Bold())
c.Spacer(document.Mm(4))
c.Table(
[]string{"商品", "地域", "数量", "売上"},
[][]string{
{"Laptop Pro 15", "国内", "120", "¥15,580,000"},
{"Wireless Mouse", "EU", "640", "¥1,920,000"},
{"USB-C Hub", "APAC", "410", "¥2,050,000"},
{"Monitor 27\"", "国内", "180", "¥7,200,000"},
{"Keyboard", "EU", "320", "¥2,560,000"},
{"Webcam HD", "APAC", "260", "¥2,340,000"},
},
template.ColumnWidths(40, 20, 15, 25),
template.TableHeaderStyle(
template.TextColor(pdf.White),
template.BgColor(brand),
),
template.TableStripe(stripe),
)
})
})
data, err := doc.Generate()
if err != nil {
log.Fatal(err)
}
if err := os.WriteFile("sales.pdf", data, 0o644); err != nil {
log.Fatal(err)
}
}
go run main.go。ボディ 6 行のうち 3 行に色が入り、ヘッダーは紺地に白文字。月曜の朝に Slack に貼られる、あの形。
交互配色の仕組み
内部では、ボディ行を i (0 始まり) で走査し、i%2 == 1 の行に縞色を塗っている。ヘッダーは別スライスなのでカウント対象外。
| ボディ行インデックス (0 始まり) | 見た目 | 縞? |
|---|---|---|
| 0 | 1 行目 | なし |
| 1 | 2 行目 | あり |
| 2 | 3 行目 | なし |
| 3 | 4 行目 | あり |
| ... | ... | ... |
Bootstrap と同じパリティ。1 行目はクリーンで、縞は視覚的な「休符」として効く。白の行を読み、次は薄く色がついた行、また白、と目が跳ねる。
パリティを反転させる(奇数行ではなく偶数行に色を入れる)オプションはない。どうしても反転したいなら body の先頭に空行を足す手はあるが、まずやらない。誰も望んでいない見た目になる。
色の選び方
縞の本質は 目立たせないこと。文字と競う色を選んだ瞬間、縞は機能しない。
pdf.RGBHex(0xF5F5F5) // 柔らかい暖色グレー。Bootstrap 既定値の近辺
pdf.RGBHex(0xFAFAFA) // さらに薄く、小さい文字ではほぼ気づかない
pdf.RGBHex(0xEEF2FF) // ブランド色のごく薄い派生 (ヘッダーが同系統色なら良い)
pdf.Gray(0.96) // グレースケール。PDF/A 出力で数バイト削れる
彩度の高い色は避ける。彩度 60% の青は「この行は選択中・重要」というシグナルになり、視線を逐一止めてしまう。それは縞模様の目的(行をまたぐ視線移動を助ける)と逆方向だ。
ダークテーマ(社内向けスライド型レポートなどで稀にある)なら、0x1A1A1A のページに pdf.RGBHex(0x202020)。コントラスト差を低く抑えるのは同じ。
罫線と組み合わせる
短いテーブルなら縞だけで十分。会計帳票のような密度の高い表では WithTableCellBorder でセル間にヘアラインを引くと締まる:
hairline := template.Border(
template.BorderWidth(document.Pt(0.5)),
template.BorderColor(pdf.Gray(0.85)),
)
c.Table(header, rows,
template.ColumnWidths(40, 20, 15, 25),
template.TableHeaderStyle(
template.TextColor(pdf.White),
template.BgColor(brand),
),
template.TableStripe(pdf.RGBHex(0xF5F5F5)),
template.WithTableCellBorder(hairline),
)
ヘアライン + 薄い縞 = 経理が出してくる Excel 印刷プレビューの定番フォーマット。罫線は縞より薄くする。縞が主役で罫線は補助、の順序を崩さない。
外枠だけ欲しければ WithTableCellBorder の代わりに WithTableBorder を使う。
10 分溶かす落とし穴
- 色の値域を間違える。
pdf.RGB(245, 245, 245)は真っ黒になる。コンストラクタは 0.0〜1.0 を要求する。CSS 感覚で書きたいならpdf.RGBHex(0xF5F5F5)を使う。 - ヘッダーに縞をかけようとする。
TableStripeはヘッダーに触れない。ヘッダーに色を入れたいならTableHeaderStyle(template.BgColor(...))で別物。これを混同して「ヘッダーに色が乗らない」と数十分悩むのはあるあるだ。 - 2 色交互にしたい。gpdf は縞色を 1 つしか取らない。
white → gray → blueの 3 色ローテーションは仕様にない。実装すれば書けるが、読みづらいだけなので入れていない。 - 3 行のテーブルに縞を入れる。縞模様は 4〜5 行以上ないと効果が出ない。2〜3 行だと「1 セルだけ選択された」ように見える。素直に縞なしにする。
関連レシピ
- テーブルの列幅をカスタマイズするには? —
ColumnWidthsの詳細。 - gpdf にカスタム TrueType フォントを登録するには? — 縞テーブルをブランドフォントで描く。
- Go で 50 行未満の請求書 PDF — ヘッダー、縞、合計行を入れた実用テーブル。
gpdf を使ってみる
gpdf は Go の PDF 生成ライブラリ。MIT、ゼロ依存、純 Go の TrueType 処理。
go get github.com/gpdf-dev/gpdf