WPS Office 粘贴截图时会生成 =DISPIMG("ID_xxx",1) 公式嵌入图片,这类图片在 Microsoft Excel 中无法正常显示。这个工具自动把所有公式图片提取为 Excel 原生浮动图片,精确匹配单元格尺寸,一个命令搞定。单文件 Python,零配置,打包成 exe 可直接分发。
ZipFile
lxml XML
ID → media
删除 DISPIMG
openpyxl
EMU 尺寸修正
_excel.xlsx
一、WPS 的 DISPIMG 是什么
WPS Office 里粘贴截图时,它不会像 Excel 那样直接插入浮动图片,而是在单元格内写入一个 =DISPIMG("ID_XXXXXXXX",1) 公式,图片数据存在 xlsx 包的 xl/media/ 目录中。这个公式是 WPS 私有的,Microsoft Excel 不识别——打开后要么显示公式文本,要么一片空白。
手动操作的替代方案是逐张另存再插入,耗时且容易出错。自动化处理的核心思路:解压 xlsx → 删除公式 → 匹配 media 文件 → 用 openpyxl 插入浮动图片 → 修正 XML 尺寸。
二、核心模块拆解
2.1 单元格尺寸计算
图片需要精确缩放到单元格大小。Excel 的列宽单位和行高单位不是像素,需要做转换:列宽单位 ≈ 默认字体数字 0 的宽度 + padding(Calibri 11pt 下 1 单位 ≈ 8px),行高 pt 转 px 用 96/72 换算。
def col_width_to_pixels(width, default_font='Calibri', default_size=11):
if width is None:
width = 8.43 # Excel 默认列宽
return int(width * 8 + 5)
def row_height_to_pixels(height):
if height is None:
height = 15 # Excel 默认行高
return int(height * 96 / 72)
2.2 ID 与文件匹配
DISPIMG 公式中的 ID(如 ID_A3F8B2C1)需要映射到 xl/media/ 下的实际图片文件。采用三级匹配策略:精确文件名匹配 → 部分包含匹配 → 剩余文件轮询兜底。确保每张公式图都能找到对应的 media 文件。
# 三级匹配策略
for img_id in all_ids:
if img_id in media_map: # ① 精确匹配
id_to_file[img_id] = media_map[img_id]
else:
for name, fp in media_map.items():
if img_id in name: # ② 包含匹配
id_to_file[img_id] = fp
break
2.3 EMU 尺寸修正
openpyxl 插入的浮动图片在 drawing XML 中用 EMU(English Metric Units)表示尺寸,但 openpyxl 设置的像素尺寸在重新打包后会丢失精度。工具在最后一步直接解析 XML,将像素转换为 EMU(1px = 9525 EMU)写入 <a:ext> 节点,确保在 Excel 中打开时图片大小完全正确。
# 像素 → EMU 写入 drawing XML
ext.set('cx', str(target_w * 9525))
ext.set('cy', str(target_h * 9525))
三、进度条:打包 exe 后的刚需
大文件可能包含上百张图片,如果没有进度反馈,用户会以为程序卡死了。实现了一个零依赖的 ProgressBar 类,输出到 stderr,不干扰主逻辑。
📥 解压文件... 100.0%
📋 表格 100.0% (8/8)
DISPIMG 公式: 156 个 | media 文件: 152 个
匹配: 156/156
📥 插入图片... 65.4%
🖼️ 插入图片 95/156
✅ 完成!156 个图片已转为浮动图片 → report_excel.xlsx
按回车键退出...
7 个阶段按权重分配进度:解压 5%、扫描 10%、清理 10%、打包 5%、插入图片 50%(最慢,有独立子进度条)、修正尺寸 15%、保存 5%。总体进度条 + 嵌套子进度条,用户能清楚看到当前跑到哪一步。
四、用法
4.1 命令行
# 直接指定文件
python wps_convert.py input.xlsx
# 指定输出路径
python wps_convert.py input.xlsx output.xlsx
# 双击 exe,弹出文件选择框
wps_convert.exe
4.2 依赖
首次运行自动安装 lxml、Pillow、openpyxl,无需手动 pip install。打包 exe 后跳过自动安装。
五、打包分发
PyInstaller 单文件打包,目标用户无需安装 Python:
# PowerShell 一条命令
pyinstaller --onefile --icon=03.ico \
--hidden-import=lxml --hidden-import=lxml.etree \
--hidden-import=PIL --hidden-import=openpyxl \
--name wps_convert wps_convert.py
--key 字节码加密,如果你之前用的是旧版打包命令,需要去掉 --key 参数,否则直接报错。
六、总结
一个解决实际办公痛点的小工具:WPS 公式图片在 Excel 中不显示 → 自动提取为浮动图片。核心约 400 行 Python,解压 xlsx 包、解析 XML、匹配 media 文件、用 openpyxl 重新插入浮动图片、后处理修正 EMU 尺寸。加上进度条和错误捕获,打包后可直接分发给同事使用。
核心收获:xlsx 本质上是一个 zip 包,理解了 Open XML 格式,很多 Excel 自动化问题都能迎刃而解。