全部文章

如何在 gpdf 表格中添加斑马条纹行?

传入 template.TableStripe 即可,gpdf 会自动给隔行涂上你指定的背景色,不用写循环、也不用逐格设置样式。

把问题换个说法

我有一个表格 — 发票、流水、日志 — 行数超过 5 行后眼睛容易跳行。Bootstrap 里的 .table-striped 就是隔行加灰底,我想在 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)    // 隔行底色

    page := doc.AddPage()
    page.AutoRow(func(r *template.RowBuilder) {
        r.Col(12, func(c *template.ColBuilder) {
            c.Text("Q1 销售汇总", template.FontSize(20), template.Bold())
            c.Spacer(document.Mm(4))

            c.Table(
                []string{"产品", "区域", "数量", "销售额"},
                [][]string{
                    {"Laptop Pro 15",  "北美",  "120", "¥1,058,400"},
                    {"Wireless Mouse", "欧洲",  "640", "¥130,560"},
                    {"USB-C Hub",      "亚太",  "410", "¥139,400"},
                    {"Monitor 27\"",   "北美",  "180", "¥489,600"},
                    {"Keyboard",       "欧洲",  "320", "¥174,080"},
                    {"Webcam HD",      "亚太",  "260", "¥159,120"},
                },
                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 行带底色,表头深蓝白字。这就是周一邮件里发出去的报表样式。

交替着色的原理

内部上,gpdf 用从 0 开始的下标 i 遍历主体行,只对 i%2 == 1 的行涂条纹色。表头是单独的切片,不参与计数。

主体行下标 (从 0 开始)视觉位置是否带条纹?
0第 1 行
1第 2 行
2第 3 行
3第 4 行
.........

这套奇偶规则跟 Bootstrap 一致。第一行干净,条纹是视觉"换气",白行—浅色行—白行,眼睛自然跳跃。

没有反转奇偶的开关(让奇数行带色)。如果非要反过来,可以在主体最前插一空行 — 但其实没人想要这种效果。

颜色怎么选

条纹的关键在于 不抢眼。一旦颜色和正文抢注意力,条纹就失去意义。

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),
)

细线 + 浅条纹 = 财务部打印预览的经典样式。边框颜色一定要比条纹更浅,这样条纹仍然是主信号、边框只是辅助。

只想要外边框、不要内部网格的话,把 WithTableCellBorder 换成 WithTableBorder

容易浪费十分钟的坑

  • 颜色取值范围搞错pdf.RGB(245, 245, 245) 会变成纯黑色块。构造函数要求 0.0–1.0,而不是 0–255。习惯 CSS 写法的话用 pdf.RGBHex(0xF5F5F5)
  • 想给表头加条纹TableStripe 不影响表头。要给表头加底色应该用 TableHeaderStyle(template.BgColor(...)),这是另一个选项。混淆这两个、然后纳闷"表头怎么没颜色",是最经典的初次踩坑。
  • 想要双色交替。gpdf 只接受一个条纹色,没有 white → gray → blue 三色循环。这不是功能限制,而是有意为之 — 三色斑马只会让读者更累。
  • 3 行的小表格也加条纹。斑马条纹至少需要 4–5 行才有效。2–3 行加上去,只会让人以为"某一格被选中"。短表格直接不要条纹。

相关菜谱

试试 gpdf

gpdf 是一个用纯 Go 写的 PDF 生成库,MIT 许可、零外部依赖、原生 TrueType 处理。

go get github.com/gpdf-dev/gpdf

⭐ 在 GitHub 加星 · 阅读文档