在报表分发、合同归档、机密数据共享等场景中,给 excel 文档添加水印是一种简单且实用的版权标识手段。水印既可以由图片构成,也可以由文字构成。对中文使用者来说,"机密"、"内部资料"、"严禁外传"等中文字样的水印更贴近实际业务。

安装
可以通过 nuget 将该库引入到项目中。
nuget 包管理器控制台
install-package freespire.xls
.net cli
dotnet add package freespire.xls
安装完成后,在代码中引入命名空间 spire.xls 即可使用。
两种水印方案对比
excel 的水印并不是真正的"水印"对象,本质上是通过页眉图片或工作表背景图片模拟出来的,因此两种方案在打印、视图、定位等方面表现差异明显。
| 对比项 | 页眉图片水印 | 背景图片水印 |
|---|---|---|
| 打印输出 | 随文档一同被打印 | 不出现在打印结果中 |
| 视图可见性 | 仅在"页面布局"或"分页预览"模式下可见,普通视图看不到 | 所有视图模式下都可见 |
| 位置控制 | 需要手动调整页眉区域的边距来让图片居中 | 自动铺满整个工作表数据区 |
| 视觉一致性 | 受分页影响,相邻页可能错位 | 整张工作表只显示同一张图片 |
页眉图片水印
优点:水印会出现在文档的最终打印输出中,适合必须打印归档的场景。
缺点:在 excel 的 "normal" 视图下不可见,只能在 "page layout" 或 "page break preview" 下看到;要把图片调到页面正中央,要小心调整图片上方和左侧的页边距。
背景图片水印
优点:水印图片覆盖整张工作表,呈现效果一致。
缺点:水印不会出现在打印输出中。
方案一:通过页眉添加图片水印
下述示例遍历文档中的所有工作表,并把同一张水印图片设置到页眉中央位置。
using spire.xls;
using system.drawing;
namespace addwatermarktoexcelusingheader
{
class program
{
static void main(string[] args)
{
// 创建 workbook 对象
workbook workbook = new workbook();
// 加载 excel 文档
workbook.loadfromfile(@"c:\users\administrator\desktop\input.xlsx");
// 加载水印图片
image image = image.fromfile(@"c:\users\administrator\desktop\confidential.png");
// 遍历文档中所有工作表
for (int i = 0; i < workbook.worksheets.count; i++)
{
// 获取指定工作表
worksheet worksheet = workbook.worksheets[i];
// 在页眉中央插入图片占位符
worksheet.pagesetup.centerheader = "&g";
// 将图片设置到页眉中央
worksheet.pagesetup.centerheaderimage = image;
}
// 保存结果文件
workbook.savetofile("addwatermark.xlsx", excelversion.version2016);
// 释放资源
workbook.dispose();
}
}
}注意:&g 是 excel 自身的页眉图片占位符,所有文本(如"机密"字样)应直接烘焙到图片中,而不是写在 centerheader 字符串 里。
方案二:将图片设置为工作表背景
下述示例把图片作为工作表的背景水印,适用于仅屏幕查看、需要强可见性的场景。
using spire.xls;
using system.drawing;
namespace addwatermarktoexcelusingbackground
{
class program
{
static void main(string[] args)
{
// 创建 workbook 对象
workbook workbook = new workbook();
// 加载 excel 文档
workbook.loadfromfile(@"c:\users\administrator\desktop\input.xlsx");
// 加载水印图片
bitmap bitmapimage = new bitmap(image.fromfile(@"c:\users\administrator\desktop\sample.png"));
// 遍历文档中所有工作表
for (int i = 0; i < workbook.worksheets.count; i++)
{
// 获取指定工作表
worksheet worksheet = workbook.worksheets[i];
// 将图片设置为该工作表的背景
worksheet.pagesetup.backgroundimage = bitmapimage;
}
// 保存结果文件
workbook.savetofile("addwatermark.xlsx", excelversion.version2016);
// 释放资源
workbook.dispose();
}
}
}中文文字水印的生成
实际业务里,水印常常是"机密资料"、"内部文件"等动态文字,没必要每次都由设计师提供 png。可以借助 system.drawing 在内存中绘制一张透明背景的中文水印图片,再交给方案一或方案二复用。
using system.drawing;
using system.drawing.drawing2d;
using system.drawing.imaging;
public static class chinesewatermarkhelper
{
/// <summary>
/// 生成中文文字水印图片(透明背景,倾斜 -30°)
/// </summary>
/// <param name="text">水印文本,如 "机密资料"</param>
/// <param name="width">画布宽度</param>
/// <param name="height">画布高度</param>
/// <returns>带有透明背景的 bitmap 对象</returns>
public static bitmap create(string text, int width, int height)
{
bitmap bmp = new bitmap(width, height, pixelformat.format32bppargb);
using (graphics g = graphics.fromimage(bmp))
{
g.clear(color.transparent);
g.smoothingmode = smoothingmode.antialias;
g.textrenderinghint = system.drawing.text.textrenderinghint.antialiasgridfit;
using (font font = new font("microsoft yahei", 60, fontstyle.bold))
using (solidbrush brush = new solidbrush(color.fromargb(60, color.red)))
{
// 计算文字尺寸并居中
sizef size = g.measurestring(text, font);
// 平移到画布中心,再旋转,使绘制出的文字位于中央
g.translatetransform(width / 2f, height / 2f);
g.rotatetransform(-30);
g.drawstring(text, font, brush, -size.width / 2f, -size.height / 2f);
}
}
return bmp;
}
}调用时,只需把生成的 bitmap 直接传给上面的两种方案即可:
// 生成中文文字水印图片
bitmap watermarkimage = chinesewatermarkhelper.create("机密资料", 800, 600);
// 用作工作表背景水印
workbook.worksheets[0].pagesetup.backgroundimage = watermarkimage;字体一致性建议
system.drawing 默认按系统已安装的字体渲染中文字符,在不同环境(例如 linux 服务器、容器化部署)下可能出现字体丢失、文字变成方块的情况。生产环境中建议:
- 将字体文件(如 msyh.ttc、simhei.ttf)打包到应用中;
- 通过 privatefontcollection 加载私有字体后再传入 font 构造函数;
- 或预先把所有可能用到的水印文本渲染成 png,作为静态资源随项目分发。
方案选型参考
| 场景 | 推荐方案 |
|---|---|
| 报表需要打印、归档,文档要长期留存 | 方案一:页眉图片水印 |
| 仅屏幕查看、内部演示,注重直观可见 | 方案二:背景图片水印 |
总结
免费 .net excel 库本身并不直接提供"水印"对象,而是借助页眉图片或工作表背景图片这两种机制实现。把任意一张 image/bitmap 交给 centerheaderimage 或 backgroundimage,就完成了水印的添加;再结合一段简短的中文文字绘图代码,就可以在不依赖外部素材的前提下,灵活生成"机密资料"、"内部文件"等贴合中文业务场景的水印。
实际项目里,建议把"图片生成 + 水印注入"封装成独立的工具方法,对外只暴露文件路径、水印文字、可见性等少量参数,这样在面对多业务线、多模板时复用成本最低。
以上就是c#实现为excel添加水印的两种方案对比的详细内容,更多关于c# excel添加水印的资料请关注代码网其它相关文章!
发表评论