查看: 268|回复: 3

Python Spire.XLS给Excel加水印的三种实现方式

[复制链接]
发表于 2 小时前 | 显示全部楼层 |阅读模式
Excel本身没有类似Word的原生水印命令,但合同台账、内部报表和外发文件经常需要“CONFIDENTIAL”“草稿”或公司Logo这类标记。借助Spire.XLS for Python,可以在不依赖本地Microsoft Excel的情况下,通过工作表背景、页眉页脚图片和文本框三种对象实现接近水印的效果。三种方式在屏幕显示和打印输出上的行为不同,下面按代码实现逐一说明。

环境准备

安装Spire.XLS:
  1. pip install Spire.XLS
复制代码

脚本中导入模块:
  1. from spire.xls import *
  2. from spire.xls.common import *
复制代码

方法一:工作表背景图片,适合屏幕显示

工作表背景通过PageSetup.BackgoundImage属性设置,注意该属性在API中保留了Backgound的拼写。图片文件先用Stream包装为流对象,再赋给属性。示例把指定图片设为第一张工作表的背景:
  1. from spire.xls import *
  2. from spire.xls.common import *
  3. inputFile = "/示例文档.xlsx"
  4. inputFile_Img = "/背景图.png"
  5. outputFile = "/BackgroundWatermark_out.xlsx"
  6. workbook = Workbook()
  7. workbook.LoadFromFile(inputFile)
  8. sheet = workbook.Worksheets[0]
  9. # 将图片设置为工作表背景
  10. image = Stream(inputFile_Img)
  11. sheet.PageSetup.BackgoundImage = image
  12. workbook.SaveToFile(outputFile, ExcelVersion.Version2013)
  13. workbook.Dispose()
复制代码

这段代码的关键步骤是:LoadFromFile()加载工作簿,Worksheets[0]取第一张工作表,Stream(inputFile_Img)读取图片,BackgoundImage赋值完成背景设置,最后按ExcelVersion.Version2013保存并调用Dispose()释放资源。背景图会显示在单元格数据后方,适合品牌底纹或装饰性标记;但它默认只出现在Excel屏幕视图中,不会进入打印结果和导出的PDF。

方法二:页眉页脚图片,适合打印和PDF

需要让水印随打印页或PDF输出时,应使用页眉页脚图片。Spire.XLS提供LeftHeaderImage、CenterFooterImage等属性;设置图片后,还必须在对应的页眉或页脚文本属性中写入&G占位符,图片才会显示。顺序是先设置图片,再设置&G。
  1. from spire.xls import *
  2. from spire.xls.common import *
  3. inputFile = "/示例文档.xlsx"
  4. inputFile_Img = "/Logo1.png"
  5. outputFile = "/HeaderFooterWatermark.xlsx"
  6. workbook = Workbook()
  7. workbook.LoadFromFile(inputFile)
  8. sheet = workbook.Worksheets[0]
  9. # 设置页眉图片
  10. image = Stream(inputFile_Img)
  11. sheet.PageSetup.LeftHeaderImage = image
  12. sheet.PageSetup.LeftHeader = "&G"
  13. # 设置页脚图片
  14. sheet.PageSetup.CenterFooterImage = image
  15. sheet.PageSetup.CenterFooter = "&G"
  16. # 切换到页面布局视图,方便预览
  17. sheet.ViewMode = ViewMode.Layout
  18. workbook.SaveToFile(outputFile, ExcelVersion.Version2010)
  19. workbook.Dispose()
复制代码

示例把同一张图片放到左侧页眉和居中页脚,并把ViewMode设为ViewMode.Layout,方便在页面布局视图中预览。页眉页脚内容会随打印页面输出,因此适合打印水印和导出PDF。如果希望图片位于页面中央而不是页眉页脚边缘,应提前制作带透明通道、主体居中的图片,再添加到页眉或页脚中。

方法三:文本框文字水印

如果水印只是“机密”“草稿”等文字,不必准备图片,可用TextBoxes.AddTextBox()创建文本框,再用.Text写入内容。AddTextBox()的四个参数依次是行索引、列索引、高度和宽度,用来确定文本框的位置和尺寸。
  1. from spire.xls import *
  2. from spire.xls.common import *
  3. inputFile = "/示例文档.xlsx"
  4. outputFile = "/TextWatermark.xlsx"
  5. workbook = Workbook()
  6. workbook.LoadFromFile(inputFile)
  7. ws = workbook.Worksheets[0]
  8. # 添加文本框,参数依次为行索引、列索引、高度和宽度
  9. textbox = ws.TextBoxes.AddTextBox(9, 2, 35, 120)
  10. textbox.Text = "水印示例"
  11. # 设置文本框旋转角度
  12. textbox.Rotation = 45
  13. # 设置文本框内文字的字体和颜色
  14. font = workbook.CreateFont()
  15. font.Color = Color.get_Red() # 字体颜色
  16. font.Size = 14 # 字号大小
  17. richText = textbox.RichText
  18. rt = RichText(richText)
  19. rt.SetFont(0, len(textbox.Text) - 1, font) # 应用到所有字符
  20. # 隐藏边框
  21. textbox.Line.Weight = 0
  22. # 将文本框的填充背景设为不可见
  23. textbox.Fill.Visible = False
  24. workbook.SaveToFile(outputFile, ExcelVersion.Version2010)
  25. workbook.Dispose()
复制代码

这段代码添加文本框后,通过Rotation = 45设置旋转角度,创建字体并设置为红色、14号字,再通过RichText.SetFont(0, len(textbox.Text) - 1, font)把字体应用到全部字符;Line.Weight = 0用于隐藏边框,Fill.Visible = False让文本框填充背景不可见。文本框位于单元格内容上方,屏幕可见,也会随工作表打印或导出。若想更接近传统水印,可以调大字号、使用浅色字体并保留倾斜角度,以减少对表格内容的遮挡。

三种方式如何选择

按输出目标选择即可:整表品牌底纹、只需屏幕显示,用工作表背景图片;需要打印或PDF保留图片水印,用页眉页脚图片;只需“机密”“草稿”等文字标记且不想准备图片,用文本框。三者也可以组合使用,例如在工作表中加“草稿”文本框,同时在打印页脚放公司Logo。需要注意:工作表背景屏幕可见但不打印;页眉页脚图片需在页面布局视图查看,且打印可见;文本框在屏幕和打印输出中都可见。

批量处理:为每张工作表添加水印

一个工作簿包含多张工作表时,可以遍历workbook.Worksheets集合,在循环内执行同样的设置,最后统一保存一次,避免反复调用SaveToFile()。以文字水印为例:
  1. from spire.xls import *
  2. from spire.xls.common import *
  3. inputFile = "Sample.xlsx"
  4. outputFile = "TextWatermark_Batch_out.xlsx"
  5. workbook = Workbook()
  6. workbook.LoadFromFile(inputFile)
  7. # 遍历工作簿中的每张工作表
  8. for sheet in workbook.Worksheets:
  9.     textbox = sheet.TextBoxes.AddTextBox(9, 2, 25, 100)
  10.     textbox.Text = "机密"
  11. workbook.SaveToFile(outputFile, ExcelVersion.Version2010)
  12. workbook.Dispose()
复制代码

与单张工作表处理相比,这段代码主要增加了for循环。若要批量添加背景图片或页眉页脚图片,把循环中的文本框设置替换为对应的PageSetup属性即可;如果还要处理多个Excel文件,可以在外层再增加文件遍历逻辑。

实用技巧与注意事项

1. 图片水印优先使用带Alpha透明通道的PNG文件,透明区域不会遮挡表格数据;纯白背景的JPG图片可能覆盖部分内容。
2. 根据输出场景选择方法:PageSetup.BackgoundImage设置的背景图片不会随工作表打印,需要生成带水印PDF时应优先考虑页眉页脚图片或文本框。
3. 批量处理多张工作表时遍历workbook.Worksheets集合;处理多个工作簿时再外层套文件循环。
4. Spire.XLS免费版在处理行数和功能方面存在一定限制,大型工作簿或复杂排版需要评估是否使用商业许可。
5. 保存文件后调用Dispose()释放资源,批量处理多个工作簿时也应及时释放对象,避免资源持续占用。

总结

Excel没有原生的水印功能,但Spire.XLS for Python可以通过三种对象实现类似效果:用sheet.PageSetup.BackgoundImage = image设置屏幕背景;用LeftHeaderImage、CenterFooterImage配合&G生成打印和PDF图片水印;用TextBoxes.AddTextBox()加.Text生成文字水印。实际使用时按水印内容和输出方式选择,并结合循环完成多工作表、多工作簿的批量标记。
回复

使用道具 举报

发表于 2 小时前 | 显示全部楼层

Re: Python Spire.XLS给Excel加水印的三种实现方式

感谢分享,三种方式区分得挺清楚。总结一下适用场景:工作表背景用 BackgoundImage 设置,只影响屏幕视图,打印和导出 PDF 不会带上,适合品牌底纹;页眉页脚图片能随打印页面和 PDF 输出,但一定要先设图片再在对应文本属性里写 &G 占位符,而且想让水印居中就得提前把图片主体做居中并带透明通道;文本框方式适合“机密”“草稿”这类纯文字水印,旋转角度、字体颜色字号、隐藏边框和填充都通过对象属性控制,灵活性最高。 有两点想提醒:一是 BackgoundImage 这个拼写是 API 保留的,写成 BackgroundImage 会直接报错,容易踩坑;二是帖子末尾 RichText.SetFont 那行似乎被截断了,字符范围参数没写完,建议补全,方便照着敲的人直接运行。另外图片流和 workbook 用完后及时释放,批量处理多个文件时能少占不少资源。
回复 支持 反对

使用道具 举报

发表于 2 小时前 | 显示全部楼层

Re: Python Spire.XLS给Excel加水印的三种实现方式

感谢楼主整理,三种方式按屏幕显示、打印输出、纯文字标记来分类,思路很清楚,比单纯贴代码实用多了。 几个我自己踩过的坑正好和帖子里说的一致:BackgoundImage 这个属性名少了字母 a,第一次写的时候按 Background 拼然后一直报错,看到楼主特意提醒才反应过来;页眉页脚那个 &G 占位符也是,只设图片不写占位符的话完全没反应,而且必须先设图片再设文本,顺序反了也不行。 背景图默认不进打印和导出 PDF 这点也值得多说一句,不少人第一反应是“我屏幕上明明有水印,怎么转 PDF 就没了”,其实这是背景图本身的定位决定的,做外发文件还是得走页眉页脚那条路。 文本框方式对“机密”“草稿”这种纯文字确实最省事,补两个小提醒:文本框的位置和大小是固定值,后面如果调行高列宽或者插入删除了行列,水印位置会歪,最好最后再加水印;另外 45 度旋转的文本框记得设成不遮挡单元格编辑,不然下面的单元格点起来会有点别扭。 最后方法三的代码好像被截断了,RichText.SetFont 那行只到 len(te 就断了,方便的话麻烦楼主补一下完整写法,想照着跑一遍。
回复 支持 反对

使用道具 举报

发表于 2 小时前 | 显示全部楼层

Re: Python Spire.XLS给Excel加水印的三种实现方式

感谢分享,三种方式讲得很清楚,尤其把屏幕显示和打印输出的差异点出来很实用。方法一背景图只影响屏幕、不进打印和PDF;方法二页眉页脚配合 &G 占位符才能随打印和PDF输出;方法三用文本框加旋转、透明填充来做文字水印,按场景选型就很明确了。 另外注意到方法三的代码在最后 RichText.SetFont 那一行好像被截断了,后面保存和释放资源的部分没显示全,方便的话可以补一下完整代码,特别是把字体应用到所有字符那段,对想直接复制使用的朋友会更有帮助。 还有个小疑问想请教:方法二里同一个图片流同时赋给 LeftHeaderImage 和 CenterFooterImage,首帖中是复用了同一个 image 变量,实际使用时是否需要分别创建 Stream 对象?有点拿不准,想确认一下。再次感谢,已经收藏了。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-11-6 05:31 , Processed in 0.025050 second(s), 28 queries , Gzip On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部