golang实现pdf中自动换行的表格

需要用到的库:jung-kurt/gofpdf

由于CellFormat方法不支持\n换行,会被变成乱码,MultiCell方法会自动将坐标定位到下一行。所以需要自己实现坐标的计算变换。通过Rect方法画出单元格,MultiCell方法在格内自动换行写字,在计算坐标重复写单元格,最终组成一行。

参考ExampleFpdf_Rect()

  1. 实现自动换行的表格
go 复制代码
import "github.com/jung-kurt/gofpdf"


type pdfLine struct {
	pdf      *gofpdf.Fpdf
	h        float64	// 需要的行高
	x        float64	// 记录开始时坐标
	y        float64	// 记录开始时坐标
	style    string		// 风格  F仅填充 D仅边框 或者DF两个都要
	alignStr string		// 对其方式 LCR为水平的左、中、右,TMBA为垂直的上、中、下、基准线
	fontH    float64	// 字体高度
	cells    []pdfCell	// 
}

type pdfCell struct {
	w      float64	// 宽度
	h      float64	// 行高
	txtStr string	// 文本
	lines  int		// 判断文本会占几行
}

func (s *pdfLine) addLine(style string, alignStr string, cells ...pdfCell) {
	s.style = style
	s.alignStr = alignStr
	_, _, _, mbottom := s.pdf.GetMargins() // 获取当前页面边距
	_, pageh := s.pdf.GetPageSize()        // 获取当前页面尺寸
	x, y := s.pdf.GetXY()                  // 获取当前位置
	// 页面剩余行高不够时 开启新一页
	if s.pdf.GetY()+s.h > pageh-mbottom {
		s.pdf.AddPage()
		y = s.pdf.GetY()
	}
	s.x = x
	s.y = y
	_, s.fontH = s.pdf.GetFontSize()
	// 记录需要的最高行高
	for _, cell := range cells {
		lines := s.pdf.SplitText(cell.txtStr, cell.w)
		h := float64(len(lines)) * cell.h
		if s.h < h {
			s.h = h
		}
		cell.lines = len(lines)
		s.cells = append(s.cells, cell)
	}
	s.write()
}

// 写入
func (s *pdfLine) write() {
	x := s.x
	y := s.y
	// 手动记录并移动坐标
	for _, c := range s.cells {
		usedH := float64(c.lines) * s.fontH
		margin := (s.h - usedH) / 2.0
		s.pdf.Rect(x, s.y, c.w, s.h, s.style)
		s.pdf.SetXY(x, y+margin) // 保持单元格内的文字有边距
		s.pdf.MultiCell(c.w, s.fontH, c.txtStr, "", s.alignStr, false)
		x += c.w
		s.pdf.SetXY(x, y)
	}
	// 坐标重置为下一行的当前位置
	s.pdf.SetXY(s.x, s.y+s.h)
	// 重置变量
	s.cells = nil
	s.h = 0
}

// 使用  生成一个每行4列的表格
func main() {
	pdf := gofpdf.New("P", "mm", "A4", "")
	pdf.AddPage()
	pdf.AddUTF8Font("NotoSansSC-Regular", "", "src/font/NotoSansSC-Regular.ttf")
	pdf.SetFont("NotoSansSC-Regular", "", 12)
	myPdf := pdfLine{pdf: pdf}

	width, _ := pdf.GetPageSize()		// 页面宽度
	left, _, right, _ := pdf.GetMargins()	// 左右边距
	usable := width - left - right	// 可用的页面宽度
	_,h := pdf.GetFontSize()	// 字体高度
	tableH := h + 2	// 行高  多出2mm的边距
	tableWidth := usable / 4	// 每个单元个的宽度
	pdf.SetFillColor(233, 233, 233)
	// 表头
	myPdf.addLine("FD", "CM", []pdfCell{
			{w: tableWidth, h: tableH, txtStr: "表头1"},
			{w: tableWidth, h: tableH, txtStr: "表头2"},
			{w: tableWidth, h: tableH, txtStr: "表头3"},
			{w: tableWidth, h: tableH, txtStr: "表头4"},
		}...)
	// 内容
	myPdf.addLine("", "CM", []pdfCell{
			{w: tableWidth, h: tableH, txtStr: "内容1"},
			{w: tableWidth, h: tableH, txtStr: "假设这里是很长很长的内容,你可以自己替换一下"},
			{w: tableWidth, h: tableH, txtStr: "内容3"},
			{w: tableWidth, h: tableH, txtStr: "内容4"},
		}...)
}
  1. 创建页面、指定字体
go 复制代码
	// 添加页面
	pdf.AddPage()
	// 加载字体
	pdf.AddUTF8Font("NotoSansSC-Regular", "", "src/font/NotoSansSC-Regular.ttf")
	// 设置字体
	pdf.SetFont("NotoSansSC-Regular", "", 12)

加载字体时,会将前面New方法指定的目录和AddUTF8Font方法指定的目录文件拼在一起。

  1. 其他常用写入方法
go 复制代码
	// 简单单元格,接收参数为 1.单元格长度  2.行高  3.文本
	pdf.Cell(cellWeight, h, "my text")
	// 自动换行的单元格,调用这个方法之左边会回到下一行的开头
	pdf.MultiCell(0, h, "假设这是一个很长的单元格")
	// 设置填充颜色
	pdf.SetFillColor(233, 233, 233)
	// 指定格式的单元格  参数 1.单元格长度 2.行高 3.文本 4.边框形式(1全边框、或者LTRB分别代表左上右下) 5.单元格
	// 写入之后的坐标(1为下一行开头,2当前坐标的下一行) 6.对其方式(LCR为水平的左、中、右,TMBA为垂直的上、中、
	// 下、基准线) 7.是否填充当前格子 8.连接 9.连接url
	pdf.CellFormat(tableWidth, tableH, "总成本", "1", 0, "M", true, 0, "")
	// 插入图片 参数分别为  1图片位置 2x坐标 3y坐标 4图片宽度 5图片高度
	pdf.ImageOptions("src/font/logo.png", width-right-25, 5, 25, 0, false, opt, 0, "")
相关推荐
AI糊涂是福1 小时前
MATLAB语言教程:从入门到精通的全面指南
开发语言·matlab·信息可视化
jz_ddk2 小时前
[学习] C语言多维指针探讨(代码示例)
linux·c语言·开发语言·学习·算法
ac.char3 小时前
github.com/lib/pq 数据库链接完整示例方式
数据库·postgresql·golang
He_k4 小时前
‘js@https://registry.npmmirror.com/JS/-/JS-0.1.0.tgz‘ is not in this registry
开发语言·javascript·ecmascript
星夜9824 小时前
C++回顾 Day6
开发语言·数据结构·c++·算法
UpUpUp……6 小时前
C++复习
开发语言·c++·笔记
艾莉丝努力练剑7 小时前
深入详解编译与链接:翻译环境和运行环境,翻译环境:预编译+编译+汇编+链接,运行环境
c语言·开发语言·汇编·学习
开发者工具分享8 小时前
Lua 的速度为什么比 Python 快
开发语言·python·lua
蔗理苦9 小时前
2025-05-28 Python&深度学习8——优化器
开发语言·pytorch·python·深度学习·优化器
格子衫-20039 小时前
Java八股-Java优缺点,跨平台,jdk、jre、jvm关系,解释和编译
java·开发语言·jvm