表格筛选导出(xlsx → 图片 / Excel / CSV / Markdown / Word)
把本地 Excel 表格按条件筛选出来,用最合适的形式交付:图片、Excel 文件、CSV、
Markdown、Word,或者几个一起出。
何时使用
- "把这两个表分别截图给我""Excel 转成图片""表格截图发我""名单截图"
- "把 4 个班分别截图给我""按班级分开截图""每个班一张"
- "把表格里 XX 列符合 YY 的数据筛出来,给我一份 Excel / 转成 Word / 导出 CSV"
- "这个表的 xxx 班单独给我一份"
- 任何"筛选 + 换一种形式交付"的需求
⚠️ 第 0 步:先判断要不要问,不是每次都问
该问才问,命令说全了就直接干 —— 别把确认做成机械流程,那会拖慢用户。
判断规则
| 情况 | 怎么做 |
|---|---|
| 命令已经说全(文件 + 条件 + 形式 + 组合方式都有) | 直接执行,不要问。 最多在动手时说一句"我按 X 做" |
| 缺 1 项(比如只说了文件和条件,没说形式) | 只问缺的那一项,不要把三问成套抛出去 |
| 缺 2 项以上 | 才把缺的一起问 |
| 用户说"你看着办 / 随便 / 老规矩" | 按默认执行:图片、每个条件各一张、附一张汇总 |
| 用户说"就这么做" | 直接做,不要再复述确认 |
什么算"说全了"(四要素)
- 文件——哪个/哪些表
- 条件——筛哪一列、哪些值(不说就 = 全表)
- 形式——要图片 / Excel / CSV / Word / Markdown / 对话里列出
- 组合方式——合并成一张,还是每个条件各一份
例:"把桌面那个名单表按班级拆开,每个班给我一份 Excel" → 四要素齐了,直接做。
例:"把名单表按班级筛一下" → 缺"形式"和"组合方式",只问这两项。
缺项时才用的问法
> 要什么形式?图片 / Excel / CSV / Word 都行。
> 另外,这几个班是合并成一份,还是每班各一份?
呈现形式对照
| 用户要的 | 参数 | 产出 |
|---|---|---|
| 图片(PNG) | --format png(默认) |
每条件一张 PNG,宽度统一,图上标源文件名 |
| Excel 文件 | --format xlsx |
一个 xlsx,每个条件一个工作表(--summary 时多一张汇总表) |
| CSV | --format csv |
每个条件一个 csv(UTF-8-SIG,Excel 打开不乱码) |
| Word | --format docx |
一个 docx,分节 + 带边框表格;需要 pip install python-docx |
| Markdown | --format md |
一个 .md,分节 + 表格 |
| 多个都要 | --format png,xlsx |
逗号分隔,一次全出 |
| 对话里直接列出 | 不用跑脚本 | 把筛选结果整理成表格直接回复 |
> ⚠️ 要表格文件(Excel / CSV / Word)也要做 —— 这是本技能的正式能力,不是"转图片的副产物"。
> 图片只是其中一种形式。
执行回执
命令有歧义时,动手前用 3~5 行复述清楚,让用户一眼看出有没有理解偏:
【执行回执】
文件:两个测评名单表(共 2 个)
筛选:班级 ∈ B240211、B240212、Z250711、Z250712
形式:图片 + Excel;每个班各一张图、各一个工作表
其他:附汇总;组内序号重编为 1..N
预计:图片 N 张、Excel 1 个
命令已经很明确时,回执可省略,或压缩成一句话。
图片上必须标注源文件名
手机看图时看不到文件名,所以每张图都要标出它来自哪个文件。
脚本已内置:标题下方第一行灰字即 数据来源:<原 xlsx 文件名>,
也可用 --source-label 覆盖。不要关掉这个标注。
表头缺失 / 表头对不上时:先出「列对照确认图」再动手
两类高频坑:
- 表里根本没有表头 —— 第一行就是数据,只能靠内容判断(全是
B240211这种 → 班级;全是张三→ 姓名) - 表头是书面语,和用户口语对不上 —— 表头叫「是否是党员」,用户说「党员」
> 核心原则:推断可以自动做,但列的含义必须让用户点头,绝不静默按猜测跑全量。
> 猜错的代价是把一整轮结果全废掉,问一句的成本是一次确认。
判断与动作
| 情况 | 脚本行为 | 你该做的 |
|---|---|---|
| 表头完整,用户描述精确命中 | 直接跑 | 直接交付 |
| 表头完整,推断命中("党员" → "是否是党员") | 跑,并打印 [列匹配] 说明对照关系 |
在回执里带上这个映射,让用户能纠错 |
| 表头完整,但能对上多列 | 停下(退出码 2)+ 出确认图 + 列出候选 | 把候选与确认图给用户,让他指定 |
| 表里没有表头(自动探测也发现第 1 行是数据) | 列名自动编号为 列1…列N + 推断含义 + 停下(退出码 2)+ 出确认图 |
把确认图给用户核对;确认后加 --yes 重跑 |
| 用户想主动核对列 | --confirm → 只出确认图,不导出 |
把图给用户 |
确认图是两张(脚本自动生成)
| 图 | 内容 |
|---|---|
xxx_列对照确认.png |
列位置 / 表格里的列名 / 推断含义 / 样本值(前 6 条)/ 去重数 |
xxx_数据预览_前8行.png |
原表前 8 行,原样呈现 |
为什么一定要带样本值:只说"第 3 列是姓名"用户无法判断,
给出"张三、李四、王五"他立刻能确认。这就是"把表头和下面几行数据一起给用户看"的意思。
自动推断能认出的列类型
班级/编号、姓名、性别、是/否、状态、联系电话、身份证号、邮箱、日期、地址、
序号、编号(学号?)、分类项、层级/次数、数字、唯一标识、未识别。
没把握的会带 ?(如 是/否?、未识别?)—— 这类正是要请用户重点看的:
数据只能看出"是/否",但看不出它到底是"是否党员"还是"是否住校"。
指定列的三种写法(从宽松到精确)
| 写法 | 例子 | 说明 |
|---|---|---|
| 口语列名 | --col 班级 |
自动匹配,落到 所在班级 会打印 [列匹配] 说明 |
| 列号 | --col 列5 / --col 5 |
无表头时最可靠,不依赖推断 |
| 真实列名 | --col 是否是党员 |
最精确,零歧义 |
无表头表的完整流程
# 第 1 次:先出确认图(脚本会自动停下,退出码 2)
"$PY" "$S" "无表头名单.xlsx" --split-by 班级 --out "$O"
# → 生成 列对照确认图 + 数据预览图,并打印每列的推断结果
# 用户核对无误后:加 --yes 直接导出
"$PY" "$S" "无表头名单.xlsx" --no-header --yes \
--col 班级 --in "B240211,Z250711" --split-by 班级 --summary --out "$O"
> 连 --no-header 都不用写:脚本自动探测发现第 1 行不像表头(含手机号/班级编号/日期等数据特征)
> 时会自动按无表头处理并提示。想强制把第 1 行当表头,用 --header-row 1。
对不上时的判断顺序
- 先看样本值猜含义(全班都是
B240211这种 → 班级) - 有疑虑就先出确认图问一句(
--confirm) - 绝不在没核对的情况下按猜测跑全量
任务完成后:有新信息才引导固化
用户的工作往往是固化重复的(固定带几个班、固定管几个部门)。
但不是每次都要问 —— 只有这次出现了"值得下次复用的新信息"才值得开口。
先判断:这次有新信息吗?
| 情况 | 做法 |
|---|---|
| 出现了新的固定值(第一次见到的班级/部门/校区) | ✅ 可以问 |
| 用户表达了新的固定偏好("以后都要按班拆发出 Excel") | ✅ 可以问 |
| 重复性的老活,这次没有任何新东西 | ❌ 不问,安静干完活 |
| 一次性值(某天的日期、临时名单) | ❌ 不问 |
| 用户语气明显是一次性的、或已拒绝过同类提议 | ❌ 不问 |
| 用户说过"这个可能会变" | ❌ 不问 |
问的时候:引导他说出"记哪些"
不要只做 yes/no 确认:
> 这次的 4 个班是固定的吗?固定的话我记下来,以后你说"我那 4 个班"我就直接用。
> 另外如果还有别的一直不变的习惯(比如每次都只看得要某几列、都要先出一份 Excel),
> 一起告诉我,我来整理好。
然后自己完成写入(不让用户动手)
按内容性质分开放 —— 写错地方会出事:
| 内容性质 | 例子 | 写到哪儿 |
|---|---|---|
| 个人/工作数据常量 | 我带的班级、我管的部门、所在校区、常用筛选值 | 记忆文件:跨项目 → ~/.workbuddy/MEMORY.md;只在某项目 → <项目>/.workbuddy/memory/MEMORY.md |
| 通用流程习惯/偏好 | "图片都要标源文件名"、"拆分后要重编序号"、"默认出 Excel 不出图" | 写进本 SKILL.md,它是行为规范,跟着技能走 |
> ⚠️ 绝对不要把个人数据写进 SKILL.md:本技能会被分享 / 发布到技能市场,
> 个人班级号、名单、部门名称会跟着泄露,而且对别人毫无用处。
> SKILL.md 只放"怎么做"的通用规则,不放"我的数据"。
最后告知
写完说一句"记在哪儿了、记了什么",便于用户日后修正。
下次用到时
识别"我那 4 个班""我带的班""老规矩"这类指代 → 从记忆取值 →
在交付时复述全量值("按记忆中的 4 个班:B240212、B240211、Z250712、Z250711")让用户确认。
运行环境
需要一个装了 openpyxl + Pillow 的 Python 解释器(脚本本身纯 Python,不依赖其它东西)。
只有导 Word 时才额外需要 python-docx(脚本按需导入,不用 Word 就不需要)。
- 先用下面这段探测,挑一个能 import 成功的解释器,赋给
PY:
for p in "D:/python/python.exe" "$(command -v python)" "$(command -v python3)"; do
[ -n "$p" ] && "$p" -c "import openpyxl, PIL" 2>/dev/null && { echo "可用: $p"; break; }
done
- 若都不行,安装依赖:
"$PY" -m pip install openpyxl pillow python-docx - 注意:WorkBuddy 托管的
~/.workbuddy/binaries/python/...环境默认没有这些库,
除非先手动装过,否则不要用它跑本脚本。 - 中文字体脚本会自动探测(Windows 微软雅黑 / 黑体 / 宋体,macOS 苹方,Linux Noto CJK),
找不到时按报错提示在脚本顶部加一行本机字体路径即可。
装完先自检(推荐)
"$PY" <skill_dir>/scripts/selftest.py
会依次检查 7 项:依赖、中文字体、折行正确性(6 档列宽逐格校验"零溢出、零丢字")、
分页正确性(不丢行/不重复)、缩放不重叠、列识别(语义推断 + 口语列名匹配 + 歧义不自动拍板)、
端到端跑一次 5 种格式导出并核对产物。全部通过会打印 ✅ 全部通过,退出码 0。
新机器 / 同事装完后跑一次,能立刻确认环境是否可用。
用法
"$PY" <skill_dir>/scripts/table_export.py "<xlsx路径>" ["<xlsx2>" ...] \
[--format png,xlsx,csv,md,docx] [--out "<输出目录>"] [--name "前缀[,前缀2]"] \
[--col 班级 --in "B240212,B240211"] [--split-by 班级] [--summary] \
[--sort-by 班级,学号] [--cols "学号,姓名,班级"] [--drop-cols 序号] \
[--renumber] [--include-empty] [--max-height 3200] [--rows-per-page 400] \
[--sheet Sheet0] [--header-row auto] [--no-header] [--confirm] [--yes] \
[--title "自定义标题"] [--source-label "源文件名"] \
[--max-col-width 300] [--scale 1.0]
参数速查
| 参数 | 作用 |
|---|---|
--format |
输出格式,逗号分隔:png(默认)/ xlsx / csv / md / docx,可多个 |
--col 班级 --in "值1,值2" |
按列筛选行(精确匹配),省略 = 全量 |
--split-by 班级 |
按列分组:图片模式每组一张图;Excel 模式每组一个工作表;CSV 模式每组一个文件 |
--summary |
额外生成汇总(图片模式 = 汇总图 _00汇总.png;xlsx 模式 = 汇总工作表) |
--sort-by 班级,学号 |
排序键(可多列,数字列按数值比);不写则保持原表顺序 |
--cols "学号,姓名,班级" |
只输出这些列并按给定顺序排列 —— 手机阅读最实用的一招 |
--drop-cols 备注 |
剔除指定列 |
--renumber |
分组后把"序号"列重编为该组内的 1..N(拆分后原序号会跳号) |
--include-empty |
没有数据的分组也出(图片标注"(本组无数据)";表格写一行提示) |
--name |
输出文件名前缀;多文件时用逗号一一对应,如 --name "未完成,未参与" |
--rows-per-page |
单张图片最多多少行(硬上限,默认 400);实际按 --max-height 分页 |
--max-height |
单张图片最大高度(px),默认 3200,超过自动分页;0 = 不限高(出一张长图) |
--scale |
整体缩放(字号+间距),手机阅读建议 1.5(图宽约 1100px,不被拉伸) |
--date-prefix |
输出文件名加日期前缀,如 20260914_未完成_B240211.png |
--keep-empty-cols |
默认自动剔除全空列;要保留时加这个 |
--source-label |
图片上标注的源文件名,默认自动取 xlsx 文件名 |
--no-header |
整表没有表头(第 1 行就是数据),列名自动编号为 列1…列N 并推断含义 |
--confirm |
只出"列对照确认图 + 数据预览图",不导出 —— 用来先核对列 |
--yes |
列名有歧义 / 无表头时,不再停下确认,直接采用(用于用户已核对过的情况) |
--header-row |
表头在第几行;auto(默认,自动探测)/ none(同 --no-header)/ 具体行号 |
> 多文件一次调用:把多个 xlsx 都写在前面,配合 --name "前缀1,前缀2"。
>
> 列名(--col/--split-by/--cols/--sort-by)都支持三种写法:口语名(班级)、
> 列号(列5 或 5)、表里真实列名。口语名对不上时脚本会自动匹配并在 [列匹配] 里说明。
列宽与完整性:为什么不会"显示不全"
最常被问到的问题:Excel 里某些列被拖得很窄,转成图片会不会显示不全?
不会。脚本完全不读 Excel 的列宽设置(column_dimensions),
而是按单元格里的实际文字、用字体的真实像素宽度重新算列宽。实测对照:
| Excel 里我把列拖成 | 出图后的列宽 | 结果 |
|---|---|---|
| 姓名列 width=2(只剩一条) | 112px | 完整显示 |
| 班级列 width=1 | 80px | 完整显示 |
| 性别列 width=3 | 48px | 完整显示 |
| 序号列 width=40(拉得很宽) | 48px | 不浪费空间 |
| 地址列很窄但内容 30 字 | 300px 上限 + 折行 | 一个字不丢 |
保证不丢内容的 5 条机制:
- 列宽 = 该列所有单元格中最宽的那个(表头也参与),范围是
46px ~ --max-col-width。 - 超过上限的内容折行(不是截断),行高按行数自动撑开。
- 单元格里的手动换行(Excel 里 Alt+Enter 产生的
\n)原样保留为多行。 - 超长英文/学号放不下时逐字符切开,宁可换行也不丢字、也不溢出到隔壁列。
- 分组出图时所有图共用一套列宽(按筛选后的全量数据算)→ 每张图宽度一致、成套整齐。
出图前会自动体检,有问题直接打印提示([提示] 开头):
- 哪些列内容超长被压到上限、会自动折行变高(内容不丢,只是图变高)
- 本图多少列、多宽:宽了建议
--cols精简列;窄了(<1000px)提醒加--scale,否则手机上被拉伸变糊
> 想改列宽行为:--max-col-width N 调单列上限;--scale 1.5 整体放大字号与图片。
长表怎么给手机看:自动分页 + 清晰度
问题:几百行出一整张图,高度上万像素 → 微信会压缩到看不清,滑动也找不到位置。
默认行为(不用管):单张图高度上限 3200px,超了就自动分页:
[图片] 未完成_B240211_第1页共3页.png 1125x3180 第1/3页
[图片] 未完成_B240211_第2页共3页.png 1125x3180 第2/3页
[图片] 未完成_B240211_第3页共3页.png 1125x1168 第3/3页
└ 该组 190 条已按高度分成 3 张(每张≤3200px,手机上不用放大也能看清)
每张图上有 3 处标注,单拿一张出来也知道是什么、第几张、覆盖哪几条:
| 位置 | 内容 |
|---|---|
| 标题下方蓝条 | 第 2/3 页 · 本页第 84–166 条(全部共 190 条) |
| 图底部灰条 | 第 2 / 3 页 · 后面还有 1 张(最后一张显示"已是最后一张") |
| 文件名 | xxx_第2页共3页.png |
而且每页都会重复表名、数据来源、筛选条件、表头 —— 这是刻意的,防止一叠图发过去后归不了位。
两种交付,二选一:
| 要什么 | 参数 |
|---|---|
| 拆成多张(推荐,手机上最清楚) | 默认就是,什么都不用加 |
| 一整张高质量长图 | --max-height 0 --scale 1.5(不放大就会被压糊) |
清晰度:别忘了 --scale
手机屏幕一般 1080px 宽。出图只有 700~800px 宽时,手机看会被拉伸变糊。
脚本会在图宽不足 1000px 时主动提醒:
[提示] 本图宽 788px,手机屏幕一般 1080px 宽、会被拉伸变糊;
发给手机看建议加 --scale 1.5 提高清晰度
--scale 1.5 会让字号、行高、列宽、边距整体放大 1.5 倍 → 图宽约 1100px,手机上正好。
代价是每页行数变少、页数变多(正常权衡)。
给手机的推荐命令:
--split-by 班级 --summary --renumber --scale 1.5
相关参数:
| 参数 | 说明 |
|---|---|
--max-height N |
单张图最大高度,默认 3200;0 = 不限高,出一张长图 |
--rows-per-page N |
单张最多行数(硬上限),默认 400;实际以 --max-height 为准 |
--scale N |
整体缩放,字号+所有间距同步放大。手机阅读建议 1.5 |
> ⚠️ --scale 放大时,--max-col-width 也同步等比放大,所以列宽表现一致,不用手动调。
输出约定(各格式)
- 默认输出目录
<xlsx 同目录>/<文件名>_导出/;批量时建议统一指定--out。 - 图片:分组时所有图共用一套列宽 → 宽度完全一致,高度按行数不同。
图内层级:大标题(表名 · 组名)→数据来源:xxx.xlsx→ 原表导出说明 → 筛选/分组 → 本组人数。 - Excel:一个文件、多个工作表(
汇总在最前,然后每个分组一张);表头加粗浅蓝底、
冻结首行、列宽自适应。 - CSV:每个分组一个文件,UTF-8-SIG 编码(Excel 双击打开不乱码)。
- Word:一个 docx,每个分组一个小标题 + 一张带边框表格,中文字体设为微软雅黑。
- Markdown:一个 .md,
#标题 +>数据来源 + 每个分组##分节 + 标准表格。 - 排序 / 序号重编 / 空列剔除 / 列筛选,所有格式口径一致(同一份数据、同一套处理)。
- 某组无数据时,汇报必须主动说明"X 班无数据",不要闷不做声;
需要成套时加--include-empty。
典型用法(示例)
两个名单表,只筛 4 个班,每班一张图 + 一份多工作表的 Excel:
PY="D:/python/python.exe" # 换成能 import openpyxl, PIL 的解释器
S="<skill_dir>/scripts/table_export.py"
O="./导出"
V="B240211,B240212,Z250711,Z250712" # ← 换成你自己的班级号
"$PY" "$S" "./表1.xlsx" "./表2.xlsx" \
--col 班级 --in "$V" --split-by 班级 --summary --renumber \
--format png,xlsx --name "表1,表2" --out "$O"
只要 Excel、不要图片:--format xlsx
只要 Word:--format docx
手机上看得多、列又长:加 --cols "学号,姓名,班级,联系电话"
汇报模板(跑完给用户看的)
别只丢文件名,按这个格式给结论:
| 产物 | 内容 |
|---|---|
| 图片 6 张 | 每班一张;表1_B240211.png(3人)… |
| Excel 1 个 | 2 个汇总表 + 6 个分组工作表 |
| Word 1 个 | 6 节、6 张表格 |
- ⚠️ 表2 里 B240212、Z250711 无数据,所以不是 8 张
- 🔍 用了口语列名时说明对照关系("你说的『党员』对应表里的『是否是党员』"),让用户能纠错
- 输出目录:
./导出/ - 💡 只在有新信息时才问:这几个班固定吗?要不要记下来。
分享 / 安装给别人用
本 skill 是纯本地文件夹(SKILL.md + scripts/),可以直接复制分享:
- 打包发送:把整个
table-filter-export/目录压缩成 zip 发出去。 - 对方安装(任选其一):
- 解压到C:\Users\<用户名>\.workbuddy\skills\(用户级),
或{项目目录}\.workbuddy\skills\(项目级),重启 WorkBuddy 生效;
- 或在对话框里说「导入技能」/ 把SKILL.md拖进对话让 AI 自动安装;
- 想公开给所有人用(含手机端),走 SkillHub 技能市场发布。 - 对方的前置条件:有 Python,且
pip install openpyxl pillow(导 Word 再加python-docx)。
脚本行为(关键约定)
- 自动探测表头:找到第一行首列等于"序号"的行作为表头;该行之前的非空行渲染为图片顶部灰色说明文字。
- 自动过滤全空行;表头下方只要有任意非空单元格就计入数据行,因此人数统计准确。
- 自动剔除全空列(可用
--keep-empty-cols关闭)。 - 图片列宽只按内容算,不读 Excel 列宽;本次要渲染的全部数据共用一套列宽,
单列上限--max-col-width(默认 300px),超宽文本折行并撑高,绝不截断内容。 - 图片宽度取「表格宽」与「标题/说明文字宽」的较大者 —— 否则窄表(如 2 列汇总图)会把标题裁掉。
- 表头也折行:长表头(如"联系电话(家长)")在列宽受限时自动换行,不会溢出到相邻列。
- 排序/重编/筛选在所有格式上口径一致(共用同一份处理逻辑)。
- 按高度自动分页:单张默认不超过 3200px(
--max-height),超了自动拆;
每张带「第 N/M 页 · 本页第 a–b 条」顶部蓝条 + 底部「后面还有几张」提示 + 文件名页码,
且每页都重复表名/数据来源/筛选条件/表头,单拿一张也知道是什么。 --scale是整体缩放:字号与所有间距(行高、边距、列宽上限)同步放大。
只放大字号会导致文字上下重叠 —— 这是必须一起改的地方。- 值类型规范化:
None→ 空、日期 →YYYY-MM-DD(不再出现00:00:00)、
浮点整数(学号)→ 去小数点、\t→ 空格。 - 中文字体自动探测;PNG 用
optimize=True。 - 表头探测三级兜底:① 找首列等于"序号"的行 → ② 找前 6 行里最像表头的一行
(有表头常见词、且不含手机号/班级编号/日期等数据特征、且不与下方数据重复)
→ ③ 都不像就按无表头处理(列名自动编成列1…列N)并提示,而不是硬把第 1 行当表头。 - 列名匹配有歧义时停下(退出码 2)而不是自己拍板:只有"唯一命中且明显领先
(≥85 分且比第二名高 ≥12 分)"才自动采用;否则生成确认图让用户确认。
完全对不上的列名同样不猜。
常用参数建议
| 场景 | 建议 |
|---|---|
| 按班/按组出图 | --split-by 班级 --summary --renumber --format png |
| 要能继续编辑的 | --format xlsx(每班一个工作表) |
| 要发给别人看、手机上读 | --format png --cols "学号,姓名,班级,联系电话" |
| 要正式文档 | --format docx(分节 + 表格) |
| 要导入别的系统 | --format csv |
| 图片 + Excel 各一份 | --format png,xlsx |
| 某组数据很多(几百行) | 默认 --max-height 3200 自动分页,每张都标了"第几张",不用管 |
| 发给手机看 | 加 --scale 1.5(图宽约 1100px,不被拉伸变糊) |
| 要一整张长图 | --max-height 0 --scale 1.5(不放大必被微信压糊) |
| 全量一整张大截图 | 不加 --split-by |
| 表里没有表头 | --no-header(首次会停下出确认图,核对后加 --yes 重跑) |
| 表头对不上 / 想先核对列 | --confirm(只出确认图,不导出) |
| 列名吃不准、想用列号 | --col 列5(无表头时最可靠) |
注意
- 只读取 xlsx,不修改原文件;输出全部写到独立目录。
- 若文件名含
《》、空格、中文,命令中路径必须加双引号。 - 坑 1(已踩过):这类由业务系统导出的 xlsx,
dimension信息不可靠。
openpyxl.load_workbook(read_only=True)会让max_row/max_column返回 1、iter_rows只吐第一行,
导致解析出 0 条数据。必须用普通模式(脚本已处理,勿改回)。 - 坑 2(已踩过):
--renumber必须在"判断是否空组占位行"之后执行,否则会把占位文字覆盖成序号。 - 坑 3:Word 表格的中文字体必须同时设置
w:ascii/w:hAnsi/w:eastAsia,只设font.name中文会变宋体。 - 坑 4(已踩过,会崩):单元格里有手动换行(Alt+Enter 的
\n)时,
PIL.ImageDraw.textlength会抛can't measure length of multiline text,
整次导出直接失败。cell_text()已统一处理换行符,wrap()会先按\n分段。 - 坑 5(已踩过,会溢出):逐字符切超长单词时用
cur[:cut]而非cur[:cut-1]——
写错会切出比列宽多 1 个字符的行,溢出到隔壁列。压力测试(列宽上限 46/60/80/120/200/300)已覆盖。 - 坑 6:导出 Excel 时数据单元格要设
wrap_text=True,否则单元格里原有的换行在 Excel 中不显示;
Word 里\n要用run.add_break(),直接写进run.text不换行。 - 坑 7(已踩过,会重叠):
--scale只放大字号、不放大行高/边距的话,文字会上下重叠。
正确做法是set_scale()里把PAD / CELL_PAD_X / LINE_H / MIN_COL_W / PAGE_BAR_H / BOTTOM_BAR_H
一起按比例刷新,render 里的间距字面量一律走px()换算。 - 坑 8(已踩过,会遮标题):分页页码别做成右上角浮层,长标题会被它盖住;
改成标题下方的独立信息条 + 图底部提示条,互不干扰。 - 坑 9(已踩过,会选错列):列名口语匹配的"领先幅度"不能省。表头同时有
「是否是党员」和「政治面貌(党员/群众)」时,前者 96 分、后者 90 分 ——
只看最高分就会自动选错。必须要求领先 ≥12 分才敢自动采用,否则让用户确认。 - 坑 10(已踩过,会误判表头):
looks_like_header必须先把"数据特征"排除掉再判断。
否则一个没有表头、且每行班级都不同的表,第 1 行(B240211 / 张三 / 男 / 138…)会被
当成表头,第一行数据直接消失。判据:出现手机号/身份证/班级编号/日期格式 → 一定是数据行。 - 坑 11(已踩过,会降级):长数字编号的判定要用"长度优先"。13 位学号列只要出现
一行重复,按"唯一率 > 0.9"就会降级成普通"数字";改成"长度 ≥8 位即判编号"更稳。 - 本机特有:Git Bash 缺
ls/grep/dirname/tail,文件操作用 Python 或 PowerShell 代替。