把 11 个模板里满篇的 × 换成一套连贯的虚构数据,让样张能看出排版效果。
虚构设定(跨模板统一):
- 数字逻辑 / 2025 秋 / 张远航 / 计算机科学与技术学院,教学日历、成绩构成
说明、试卷归档封面、试卷四份互相对得上
- 简历:张远航,1985.03,教授博导,论文/专利/项目/获奖全套虚构
- 年度考核:同一人的 2025 年度考核表,年度总结四段写满
- 执行大纲:刻意不套用上面那套(原件就是《信号与线性系统分析》的课,
强行改课程名会让章节体系、学时分配、思政案例全对不上)
假数据都留肉眼可辨标记:DOI 统一 10.9999/、专利号 ZL209999…、
软著 2024SR99999…、手机 138 0000 0000、邮箱 example.net。
签字/日期/评语栏仍然留空——编了就分不清该改哪儿。
修掉一个既有 bug(填充时才暴露):
年度考核登记表「出生年月」的值从来不显示,连字符都不在 PDF 里。
根因是 tabularray 的 cell{r}{c}={c=n} 里那个 c 是数据行的单元序号、
不是视觉列号,表头三处 c=2 要求该行吃 15 个视觉列而表只有 11 列,
超出部分静默丢弃。迷惑点:写 12 格丢值,写 9 格反而正常。
正解是表头不写 cell{},改用行内 \SetCell[c=n]{c},每行照常写满 11 格。
同时 R0 行原件本就装不下(前六字段 115.76mm,剩 42.20mm 要放
19.68mm 标签 + 17.22mm 值,但列宽被切成 15.31/1.38/25.51),
把标签折两行「出生/年月」解决,列宽一个没改。
README 同步:根 README 与 8 个模板 README 里「一律用 × 占位」的说法
已不成立,统一改为「示例内容全部虚构」,并说明哪些位置仍必须留空。
验证:12 个模板零 error,4 处基线警告未新增;干净副本重编页数一致;
PDF 正文 × 清零;真实信息零泄漏。
10 KiB
年度考核登记表 — 中国海洋大学 教职工年度考核登记表(LaTeX 版)
把学校下发的 Word 版《中国海洋大学教职工年度考核登记表》复刻为 LaTeX 模板,
版式与原 .docx 逐项对齐,表格里不含任何真人信息(姓名/职工号/出生年月/
单位/岗位全部是编的)。
样张填的是一份完整的虚构考核表:张远航(1985.03,信息科学与工程学部 计算机科学与技术学院,教授三级,中共党员),2025 年度,年度总结写了 思政 / 教学(176 学时)/ 科研(到账 320 万元)/ 人才培养四段。 之所以不写成满篇
×,是因为这张表表格密、字数多,光看叉号判断不出 行高会不会被内容撑开。虚构内容能直接看出「写这么多字正好排满 2 页」。
文件
| 文件 | 说明 |
|---|---|
年度考核登记表.tex |
主文件。填表只改第 1 节(基本信息)与 \khsummary(年度总结) |
ouckhtb.sty |
版式包。页面/字体/列宽/行高/全部尺寸都写在这里,附换算注释 |
编译
xelatex 年度考核登记表.tex
xelatex 年度考核登记表.tex # 跑两遍,第二遍取到正确页码
需要 XeLaTeX(用 fontspec + xeCJK),并安装:
ctex、geometry、fontspec、xeCJK、tabularray。
字体不需要安装 —— 全部来自仓库公共字体包 ../fonts/(由 ../fonts.tex 加载),
详见 ../fonts/README.md。不再依赖系统里的宋体/黑体/仿宋。
实测环境:TeX Live 2022 + tabularray 2022A。用 LuaLaTeX 理论上也行,但未验证。
产出 2 页、A4、正反面打印正好。
改内容
基本信息
\khtbyear{2025} % 表头“2025 年度”那一行
\newcommand{\khnum}{0000000} % 职工号
\newcommand{\khname}{{\fangsong 张远航}} % 姓名
\newcommand{\khsex}{{\fangsong 男}} % 性别
\newcommand{\khbirth}{{\fangsong 1985.03}} % 出生年月
\newcommand{\khdept}{{\fangsong 信息科学与工程学部}} % 单位(学部 / 学院)
\newcommand{\khsubdept}{{\fangsong 计算机科学与技术学院}} % 系(研究所、实验室、科室)
\newcommand{\khparty}{{\fangsong 中共党员}} % 政治面貌
\newcommand{\khtitle}{{\fangsong 教授}} % 现专业技术职务
\newcommand{\khpost}{{\fangsong 教授三级}} % 所聘岗位
上列值是样张实际用的虚构内容。职工号
0000000故意留着没编 —— 职工号位数各校各单位不等,编一个反而会误导「照这个位数填」。⚠️ 「出生年月」的标签不是写在
\khbirth里,而是单独的\khbirthlabel(默认出生\par 年月,折两行)。原因见下文第 0 条: 那一格只有 15.31mm,放不下 4 个 14pt 的字(要 19.68mm)。 想让标签恢复成一行「出生年月」,值就会重新被挤掉。
{\fangsong ...}不能去掉。 占位符×是 U+00D7,xeCJK 默认按 Unicode 区段把它判成西文,交给 fontspec 的西文字体(Termes/Times),而那儿的×宽度与汉字不一致,几个就能撑破整列。更好的做法:
../fonts.tex里已经全局加了\xeCJKDeclareCharClass{CJK}{"00D7},把×归入 CJK 字符类 —— 于是它自动按汉字全角宽度排,不必再包\fangsong也不会撑破。 这是本次字体改造顺带修掉的老 bug(原注释的修法从未真正生效过)。
年度总结
\newcommand{\khsummary}{%
第一段……\par
第二段……\par
第三段……}
段间用 \par(不要用空行 —— 空行在 \newcommand 参数里会被当成分段但不易数)。
首行自动缩进 2 字,末行自动带「本人签名 / 年 月 日」,都写在 ouckhtb.sty 里。
版式数据来源
所有尺寸都从 .docx 内部的 OOXML 数值换算,不使用目测:
twips → mm : mm = twips / 1440 × 25.4
twips → pt : pt = twips / 20 (1 pt = 1/72 in)
w:sz : 半磅值,÷ 2 即 pt
| 项 | docx 值 | LaTeX 值 |
|---|---|---|
| 纸张 | 11907 × 16840 twips | A4(210 × 297 mm) |
表宽 tblW |
8976 twips | 158.33 mm(11 列 + 边框) |
11 个 gridCol |
1087 283 1221 1047 284 1105 952 600 870 80 1447 | 见 ouckhtb.sty 第 3.1 节 |
| 正文字号 | w:sz=28 |
仿宋 14 pt / 行距 15.6 pt |
| 大标题 | w:sz=44,w:spacing=-14 |
黑体 22 pt / 字距 −0.7 pt |
行高 trHeight |
412 460 939 1261 1252 1009 556 1258 1258 | 7.27 / 8.11 / 16.56 / 22.24 / 22.08 / 17.80 / 9.81 / 22.19 / 22.19 mm |
页边距为什么不照抄 docx
docx 是左右各 30 mm 版心(150 mm),但表宽 158.33 mm 比它还宽 8.33 mm,
Word 是靠 tblPr/jc=center 把这张表“压”进页边距里的。
本模板把页边距改成 (210 − 158.33)/2 = 25.835 mm,使 \textwidth 恰好等于表宽:
- 表格天然居中,不需要
\leftskip/\centerline之类的偏移; - 表格在纸面上的绝对位置与 Word 完全一致(左右各 25.835 mm);
- 编译时不会刷
Overfull \hbox。
表外文字(标题、脚注)仍是水平居中,视觉上与 30 mm 版心没有差别。
排版时的坑(sty 里都有详细注释)
-
🔴 表头
cell{r}{c}={c=n}会静默丢内容 —— 已全部改成行内\SetCell。 这是本模板最难查的一个 bug:某个格子的值整格不显示,日志零 error 零 warning,光看日志和 PDF 页码完全发现不了。- 现象:「出生年月」的值一直是空白。用
××××.××占位时也是空白, 所以原版一直没人发现;换成真实内容才暴露。 - 根因:
cell{r}{c}里那个c是数据行的单元序号,不是视觉列号。 表头那三处c=2加起来要求该行吃掉 15 个视觉列,而表只有 11 列, 超出部分被静默丢弃 —— 丢的正好是最后一个值。 - 迷惑点:同一行写 12 格 → 丢值;写 10 格 / 9 格 → 反而显示 (空缺给了它余量)。所以「格子数对不对」在这里完全不能当判断依据。
- 正解:表头不写
cell{},合并直接标在被合并的那格上:\SetCell[c=2]{c} 职工号 & & 0000000 & ...,每行照常写满 11 格。 - 附带修的:这个表 R0 行本来就装不下 —— 前六个字段已占 115.76mm,
剩 42.20mm 要装「出生年月」标签(19.68mm)+ 值(17.22mm),
但列宽被
c9=15.31 / c10=1.38 / c11=25.51切死,标签占不住 c9 只能整体右移,值就被挤出去。处理是把标签折成两行「出生 / 年月」 (每行 9.84mm 放得下),值回到 c10-c11。列宽一个都没改。
- 现象:「出生年月」的值一直是空白。用
-
合并单元格不折行。 合并格的单元类型
{c}是 LR 模式, 格子里的文字比所跨各列合计更宽时,它不折行,而是把列撑宽、整表超出版心。 实测「系(研究所、实验室、科室)」把表从 448 pt 撑到 559 pt。 → 所以合并格里的文字一律包\khtbfit{跨度宽宏}{文字}。 单列的Q[c,m,wd=…]没有这个问题(超了只是溢出,列宽不变)。 -
合并格里的
\hsize没被重设。 span=10 的格子里\hsize仍是整页版心宽, 长文本会按 450 pt 折行、冲出格子。→ 长内容必须用定宽\parbox(\khtbcell)。 -
跨度声明写法:
cell{r}{c}={c=n}{c}与行内\SetCell[c=n]{c}都要用{c=n}{c}这一种。={c=n}、={n}{c}、={span=n}{c}都不认,最后那个 会报The key 'tblr-cell-span/span' is unknown。 ⚠️ 但如第 0 条所述,跨列请优先用行内\SetCell,表头cell{}有丢内容的风险。 -
colspec/row{}里不能放宏。 tabularray 在宏展开之外解析列类型, 会报Unexpandable command … inside column type。所以列宽只能字面写死。
另外两个容易忘的:
longtblr默认会把各列按\textwidth等比拉伸(tblr不会),必须写stretch=0;longtblr会在续页处印「表 0: (Continued)」,必须用\DefTblrTemplate把caption/capcont/conthead-text/contfoot-text四个模板全清。
与原 docx 的已知差异
| 位置 | docx | 本模板 | 说明 |
|---|---|---|---|
| 表头「×××× 年度」 | firstLine 缩进 2 字、未设居中 |
居中 | 更像原排版疏漏,按意图改居中。想还原就把 \khtbtitle 里的 \centering 换成 \hspace*{2\ccwd} |
| 「师德考核结果」首列 | 师师德考核结果 |
师德考核结果 |
docx 原文首字重复(WPS 竖排遗留),已按正常写法更正 |
| 「单位年度考核建议档次」首列 | 单单位年度考核建议档次 |
单位年度考核建议档次 |
同上 |
| 单元格内边距 | 左右各 108 twips(1.905 mm) | 0 | c10 只有 1.41 mm,比两倍内边距还窄,统一内边距会算出负宽。代价是文字可贴竖线,但全部单元格本就水平居中,观感一致 |
| 未勾选框 | Wingdings ¨(char 0x00A8) |
U+25A1 □ |
Wingdings 在 Linux/macOS 上不可靠。仓库里的仿宋、黑体、宋体都含 □;且 ../fonts.tex 已把 U+25A1 归入 CJK 类,不会再落到不含该字的西文字体上 |
| 电子签名图片 | 内嵌两张手写签名 JPEG | 无 | 模板不含真人信息 |
校验方法(想改版式时照这个验)
不要靠肉眼看 PDF。用矢量坐标对:
xelatex 年度考核登记表.tex
pdftocairo -svg 年度考核登记表.pdf pg.svg # 转成 SVG 取精确线条坐标
pdftotext -bbox 年度考核登记表.pdf - # 取每个字的 xMin/yMin/xMax/yMax
正确结果应当满足:
- 表格左边界 73.14 pt、右边界 520.91 pt(宽度 447.8 pt ≈ 157.96 mm);
- 表格所有横线都是 10 段(8 个网格列位置被合并掉,只剩 10 段可见);
- 页数为 2;
grep "Overfull\|too small" 年度考核登记表.log无输出。
当前状态:零 Overfull、零 Underfull、2 页、表宽 157.96 mm(目标 158.33 mm,
差 0.23%,为消除 0.45 pt 的 Overfull 累积误差而取整所致,肉眼不可辨)。