C# 实现 Word 加盖骑缝章效果

2024-01-25 19:04

本文主要是介绍C# 实现 Word 加盖骑缝章效果,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 

目录

实现效果

范例运行环境

Office DCOM 配置

设计实现

创建stamp图章类 

电子章图片的计算与定位

旋转图片方法

总结 


实现效果

在OA的自动化处理系统中,通过审批的最终节点,可能会对WORD文件加盖电子章,比如定位带有指定文字的Range周围加盖电子章,骑缝章,甚至水印图片。比如如下效果图:

54f76cb8e6914b3092a5e991c3a83ae1.png

 cd92a2943a0d460dba329084920e7f9c.png

范例运行环境

操作系统: Windows Server 2019 DataCenter

操作系统上安装 Office Word 2016 ,客户端使用的 Office Word 2019

.net版本: .netFramework4.7.1 或以上

开发工具:VS2019  C#

Office DCOM 配置

请参考我的文章《C# 读取Word表格到DataSet》有对Office DCOM详细配置介绍,这里不再赘述。 

设计实现

创建stamp图章类 

导出WORD文件可以传入多个图章类(如果需要的话),图章类主要包括实现如下设置:

1、可设置三种图片(标准的盖章图片、骑缝章图片、水印图片)

2、标准的盖章图片是否显示,不显示则可以只显示骑缝章或水印图片,这个可以模拟多次盖骑缝章的效果

3、定位盖章文字,可以设置一下 x、y的偏移量,以校准指定的模板文件,达到最佳重叠效果。

4、可设置各种章的翻转角度(可随机选取)

示例代码如下: 

public class stamp{public string stampImageFilename = "";  //盖章图片public string stampImageFilename2 = "";  //骑缝章图片public string stampImageFilename3 = "";  //水印章图片public bool stampImageVisible = true;  //主章是否可显示public string findWord = "";   //查找盖章定位文字public int findWordOffsetX = 0; //查找盖章文字后,章的定位偏移量public int findWordOffsetY = 0; //查找盖章文字后,章的定位偏移量public int stamp2X = 0; //骑缝章偏移量public int stamp2Y = 0; //骑缝章偏移量public int roteAngle = 0; //骑缝章翻转角度,12点方向为0度,顺时针计算角度public bool roteReFix = false; //骑缝章翻转角度重新计算适应图片(多见于对角线)public bool randomRoteAngle = false; //骑缝章是否按指定角度的最大随机值提取public int stampImageWidth = 0; //章宽度public int stampImageHeight = 0; //章高度public string stamp2Direction = "right";  //骑缝章盖章方向 默认right ,包括 left/top/bottompublic int stampAngle = 0; //骑缝章翻转角度,12点方向为0度,顺时针计算角度public bool randomStampAngle = false; //骑缝章是否按指定角度的最大随机值提取public int stamp3X = 0; //水印章每页Xpublic int stamp3Y = 0; //水印章每页Ypublic int stamp3Angle = 0; //水印章翻转角度,12点方向为0度,顺时针计算角度}

电子章图片的计算与定位

可以创建多个图章类添加 ArrayList 中进行方法传递, 初始值为public ArrayList Stamps = null;

创建方法  public string setWordStamps(string _filename,ArrayList Stamps)

实现的功能大致如下:

1、主章根据提供查找的关键字,如 “盖章处:”、“盖章:”,然后添加图片重叠在文字的上方周围

2、骑缝章根据页数进行分割计算,每页分隔宽度不小于 1 像素

3、骑缝章可选择“盖”在页面的上下左右位置,如果多个位置方向都需要“盖”,则传递多个 stamp 图章类

4、章可以随机和指定旋转角度

示例代码如下:

public string setWordStamps(string _filename,ArrayList Stamps){Object Nothing =System.Reflection.Missing.Value;string _file="",_path=Path.GetDirectoryName(_filename)+"\\tempbfile\\",_ext="";_file=Path.GetFileNameWithoutExtension(_filename);_ext=Path.GetExtension(_filename);string _validfilename=Guid.NewGuid().ToString()+_ext;string _lastfile=_path+_validfilename;string _pdfFile = _path + Guid.NewGuid().ToString() + ".pdf";System.IO.File.Copy(_filename,_lastfile,true);if(!File.Exists(_lastfile)){return "";}//取得Word文件保存路径object filename=_lastfile;//创建一个名为WordApp的组件对象Word.Application WordApp=new Word.Application();//创建一个名为WordDoc的文档对象WordApp.DisplayAlerts=Word.WdAlertLevel.wdAlertsNone;Word.Document WordDoc=WordApp.Documents.Open(ref filename,ref Nothing,ref Nothing,ref Nothing,ref Nothing,ref Nothing,ref Nothing,ref Nothing,ref Nothing,ref Nothing,ref Nothing,ref Nothing,ref Nothing,ref Nothing,ref Nothing,ref Nothing);WordDoc.SpellingChecked = false;WordDoc.ShowSpellingErrors = false;WordDoc.ActiveWindow.View.Type = Word.WdViewType.wdNormalView;//遍历stamp图章类foreach (stamp Stamp in Stamps){bool isfirst = true;int iii = 0;int selectStart = 0;ArrayList restoreRange = new ArrayList();while (true){iii++;bool findstamptext = false;if (Stamp.findWord != ""){WordApp.Selection.Range.Start = selectStart;Word.Find fnd = WordApp.Selection.Find;Object findText = Stamp.findWord;Object matchCase = false;Object matchWholeWord = Type.Missing;Object matchWildcards = false;Object matchSoundsLike = false;Object matchAllWordForms = false;Object forward = true;Object wrap = Word.WdFindWrap.wdFindContinue;Object format = false;Object replaceWith = "";Object replace = Type.Missing; ;Object matchKashida = Type.Missing;Object matchDiacritics = Type.Missing;Object matchAlefHamza = Type.Missing;Object matchControl = Type.Missing;if (fnd.Execute(ref findText, ref matchCase, ref matchWholeWord, ref matchWildcards, ref matchSoundsLike, ref matchAllWordForms,ref forward, ref wrap, ref format, ref replaceWith, ref replace, ref matchKashida, ref matchDiacritics, ref matchAlefHamza, ref matchControl)){selectStart = WordApp.Selection.Range.Start;restoreRange.Add(WordApp.Selection.Range);findstamptext = true;}else{findstamptext = false;}}if (findstamptext == false){break;}Word.InlineShape pic = WordApp.Selection.Range.InlineShapes.AddPicture(Stamp.stampImageFilename, false, true);Word.Shape picshape = pic.ConvertToShape();picshape.WrapFormat.Type = Word.WdWrapType.wdWrapNone;if (Stamp.stampImageWidth != 0){picshape.Width = Stamp.stampImageWidth;}if (Stamp.stampImageHeight != 0){picshape.Height = Stamp.stampImageHeight;}float pagewidth = 0;float pageheight = 0;if (findstamptext == true){if (Stamp.stampAngle > 0){Random rnd = new Random();picshape.Rotation = Stamp.randomStampAngle == false ? Stamp.stampAngle : rnd.Next(Stamp.stampAngle);}pagewidth = WordApp.Selection.PageSetup.PageWidth;pageheight = WordApp.Selection.PageSetup.PageHeight;int ox = 0; int oy = 0; int ow = 0; int oh = 0;WordApp.Windows[1].GetPoint(out ox, out oy, out ow, out oh, WordApp.Selection.Range);WordApp.Selection.Range.Text = "";picshape.RelativeHorizontalPosition = Word.WdRelativeHorizontalPosition.wdRelativeHorizontalPositionPage;picshape.RelativeVerticalPosition = Word.WdRelativeVerticalPosition.wdRelativeVerticalPositionPage;picshape.Left = (float)(ox * 0.405402299) - (picshape.Width / 2);picshape.Top = WordApp.Selection.Range.Information[Word.WdInformation.wdVerticalPositionRelativeToPage] - (picshape.Height / 2);if ((bool)WordApp.Selection.Range.Information[Word.WdInformation.wdWithInTable] == true){picshape.RelativeHorizontalPosition = Word.WdRelativeHorizontalPosition.wdRelativeHorizontalPositionCharacter;picshape.RelativeVerticalPosition = Word.WdRelativeVerticalPosition.wdRelativeVerticalPositionLine;picshape.Left = 0;picshape.Top = 0;}}picshape.Left = picshape.Left + Stamp.findWordOffsetX;picshape.Top = picshape.Top + Stamp.findWordOffsetY;if (Stamp.stampImageVisible == false){picshape.Visible = Microsoft.Office.Core.MsoTriState.msoFalse;}if (Stamp.stampImageFilename2 != ""&&isfirst==true){int ra = Stamp.roteAngle;if (ra > 0){Random rnd = new Random();ra = Stamp.randomRoteAngle == false ? ra : rnd.Next(ra);}Bitmap cc = (Bitmap)Image.FromFile(Stamp.stampImageFilename2);Bitmap bb = Rotate(cc, -ra, Stamp.roteReFix);
WordDoc.Windows[1].Panes[1].Pages;int pages2 = WordDoc.ComputeStatistics(Word.WdStatistic.wdStatisticPages, ref Nothing);if (pages2 == 1){pages2 = 0; //如果一页就不盖骑缝章}for (int pi = 1; pi <= pages2; pi++){Word.Range pagerange = WordDoc.GoTo(Word.WdGoToItem.wdGoToPage, Word.WdGoToDirection.wdGoToAbsolute, pi.ToString());int rx = (pi - 1) * bb.Width / pages2;int ry = 0;int rw = bb.Width / pages2;int rh = bb.Height;if (Stamp.stamp2Direction == "bottom"){rx = 0;ry = (pi - 1) * bb.Height / pages2;rw = bb.Width;rh = bb.Height / pages2;}else if (Stamp.stamp2Direction == "left"){rx = (pages2 - pi) * bb.Width / pages2;ry = 0;rw = bb.Width / pages2;rh = bb.Height;}else if (Stamp.stamp2Direction == "top"){rx = 0;ry = (pages2 - pi) * bb.Height / pages2;rw = bb.Width;rh = bb.Height / pages2;}if (rw < 1 || rh < 1){continue;}Bitmap sepbitmap1 = bb.Clone(new System.Drawing.Rectangle(rx, ry, rw, rh), System.Drawing.Imaging.PixelFormat.Format32bppPArgb);string temppng = "d:\\" + System.Guid.NewGuid().ToString() + ".png";sepbitmap1.Save(temppng);Word.InlineShape pic2 = pagerange.InlineShapes.AddPicture(temppng, false, true);Word.Shape picshape2 = pic2.ConvertToShape();picshape2.WrapFormat.Type = Word.WdWrapType.wdWrapNone;picshape2.Width = picshape.Width / pages2;picshape2.Height = picshape.Height;if (Stamp.stamp2Direction == "bottom" || Stamp.stamp2Direction == "top"){picshape2.Width = picshape.Width;picshape2.Height = picshape.Height / pages2;}picshape2.RelativeHorizontalPosition = Word.WdRelativeHorizontalPosition.wdRelativeHorizontalPositionPage;picshape2.RelativeVerticalPosition = Word.WdRelativeVerticalPosition.wdRelativeVerticalPositionPage;picshape2.Left = pagewidth - picshape2.Width;picshape2.Top = Stamp.stamp2Y;if (Stamp.stamp2Direction == "bottom"){picshape2.Left = Stamp.stamp2X;picshape2.Top = pageheight - picshape2.Height;}else if (Stamp.stamp2Direction == "left"){picshape2.Left = 0;picshape2.Top = Stamp.stamp2Y;}else if (Stamp.stamp2Direction == "top"){picshape2.Left = Stamp.stamp2X;picshape2.Top = 0;}resultReport += string.Format("stamp2 {2} left: {0} top:{1} width:{3} height:{4}<br>", picshape2.Left, picshape2.Top,pi,picshape2.Width,picshape2.Height);File.Delete(temppng);}}//stamp2if (Stamp.stampImageFilename3 != ""&&isfirst==true){int ra = Stamp.stamp3Angle;if (ra > 0){Random rnd = new Random();ra = Stamp.randomRoteAngle == false ? ra : rnd.Next(ra);}Bitmap cc = (Bitmap)Image.FromFile(Stamp.stampImageFilename3);Bitmap bb = Rotate(cc, -ra, true);int pages2 = WordDoc.ComputeStatistics(Word.WdStatistic.wdStatisticPages, ref Nothing);resultReport += string.Format(" PageCount3:{0}<br>", pages2);for (int pi = 1; pi <= pages2; pi++){Word.Range pagerange = WordDoc.GoTo(Word.WdGoToItem.wdGoToPage, Word.WdGoToDirection.wdGoToAbsolute, pi.ToString());int rx = (pi - 1) * bb.Width / pages2;rx = 0;int ry = 0;int rw = bb.Width;int rh = bb.Height;Bitmap sepbitmap1 = bb.Clone(new System.Drawing.Rectangle(rx, ry, rw, rh), System.Drawing.Imaging.PixelFormat.Format32bppPArgb);string temppng = "d:\\" + System.Guid.NewGuid().ToString() + ".png";Word.InlineShape pic2 = pagerange.InlineShapes.AddPicture(temppng, false, true);Word.Shape picshape2 = pic2.ConvertToShape();picshape2.WrapFormat.Type = Word.WdWrapType.wdWrapNone;picshape2.Width = picshape.Width;picshape2.Height = picshape.Height;picshape2.RelativeHorizontalPosition = Word.WdRelativeHorizontalPosition.wdRelativeHorizontalPositionPage;picshape2.RelativeVerticalPosition = Word.WdRelativeVerticalPosition.wdRelativeVerticalPositionPage;picshape2.Left = Stamp.stamp3X;//                       picshape2.Left = Stamp.stamp2X;picshape2.Top = Stamp.stamp2Y;File.Delete(temppng);}}//stamp3isfirst = false;}// whileforeach (Word.Range range in restoreRange){range.Text = Stamp.findWord;}}//foreachWordDoc.Save();WordDoc.Close(ref Nothing, ref Nothing, ref Nothing);//关闭WordApp组件对象WordApp.Quit(ref Nothing, ref Nothing, ref Nothing);return _lastfile;}

旋转图片方法

        public Bitmap Rotate(Bitmap b, int angle,bool fix=false){angle = angle % 360;//弧度转换double radian = angle * Math.PI / 180.0;double cos = Math.Cos(radian);double sin = Math.Sin(radian);//原图的宽和高int w = b.Width;int h = b.Height;int ow = w;int oh = h;int d = ((int)Math.Sqrt(Math.Pow(w - 0, 2) + Math.Pow(h- 0, 2))+1);if (fix == true){w = d;h = d;}int W = (int)(Math.Max(Math.Abs(w * cos - h * sin), Math.Abs(w * cos + h * sin)));int H = (int)(Math.Max(Math.Abs(w * sin - h * cos), Math.Abs(w * sin + h * cos)));//目标位图Bitmap dsImage = new Bitmap(w, h);System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(dsImage);g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Bilinear;g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;//计算偏移量System.Drawing.Point Offset = new System.Drawing.Point((W - w) / 2, (H - h) / 2);//构造图像显示区域:让图像的中心与窗口的中心点一致System.Drawing.Rectangle rect = new System.Drawing.Rectangle(fix==false?0:(d-ow)/2, fix == false ? 0 : (d-oh)/2, ow, oh);
//            System.Drawing.Rectangle rect = new System.Drawing.Rectangle(Offset.X, Offset.Y, w, h);//           System.Drawing.Point center = new System.Drawing.Point(rect.X + rect.Width / 2, rect.Y + rect.Height / 2);System.Drawing.Point center = new System.Drawing.Point(rect.X + rect.Width / 2, rect.Y + rect.Height / 2);g.TranslateTransform(center.X, center.Y);g.RotateTransform(360 - angle);//恢复图像在水平和垂直方向的平移g.TranslateTransform(-center.X, -center.Y);g.DrawImage(b, rect);//重至绘图的所有变换g.ResetTransform();g.Save();g.Dispose();//dsImage.Save("yuancd.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);return dsImage;}

总结 

以上是实现设计的一些参考代码,在实际的使用中,可能还会遇到如下问题:

1、定位关键字的叠加效果不好,因此针对每一个模板文件均需要调整图片的x、y偏移量,以达到最佳效果

2、对于超多页面的文件(如几万页),骑缝的效果可能不佳,可以采取调整图片像素宽度,或拆分模板文件进行处理

示例代码仅作参考,欢迎大家评论指教!

这篇关于C# 实现 Word 加盖骑缝章效果的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/644299

相关文章

golang版本升级如何实现

《golang版本升级如何实现》:本文主要介绍golang版本升级如何实现问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录golanwww.chinasem.cng版本升级linux上golang版本升级删除golang旧版本安装golang最新版本总结gola

SpringBoot中SM2公钥加密、私钥解密的实现示例详解

《SpringBoot中SM2公钥加密、私钥解密的实现示例详解》本文介绍了如何在SpringBoot项目中实现SM2公钥加密和私钥解密的功能,通过使用Hutool库和BouncyCastle依赖,简化... 目录一、前言1、加密信息(示例)2、加密结果(示例)二、实现代码1、yml文件配置2、创建SM2工具

Mysql实现范围分区表(新增、删除、重组、查看)

《Mysql实现范围分区表(新增、删除、重组、查看)》MySQL分区表的四种类型(范围、哈希、列表、键值),主要介绍了范围分区的创建、查询、添加、删除及重组织操作,具有一定的参考价值,感兴趣的可以了解... 目录一、mysql分区表分类二、范围分区(Range Partitioning1、新建分区表:2、分

MySQL 定时新增分区的实现示例

《MySQL定时新增分区的实现示例》本文主要介绍了通过存储过程和定时任务实现MySQL分区的自动创建,解决大数据量下手动维护的繁琐问题,具有一定的参考价值,感兴趣的可以了解一下... mysql创建好分区之后,有时候会需要自动创建分区。比如,一些表数据量非常大,有些数据是热点数据,按照日期分区MululbU

MySQL中查找重复值的实现

《MySQL中查找重复值的实现》查找重复值是一项常见需求,比如在数据清理、数据分析、数据质量检查等场景下,我们常常需要找出表中某列或多列的重复值,具有一定的参考价值,感兴趣的可以了解一下... 目录技术背景实现步骤方法一:使用GROUP BY和HAVING子句方法二:仅返回重复值方法三:返回完整记录方法四:

IDEA中新建/切换Git分支的实现步骤

《IDEA中新建/切换Git分支的实现步骤》本文主要介绍了IDEA中新建/切换Git分支的实现步骤,通过菜单创建新分支并选择是否切换,创建后在Git详情或右键Checkout中切换分支,感兴趣的可以了... 前提:项目已被Git托管1、点击上方栏Git->NewBrancjsh...2、输入新的分支的

C# 比较两个list 之间元素差异的常用方法

《C#比较两个list之间元素差异的常用方法》:本文主要介绍C#比较两个list之间元素差异,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1. 使用Except方法2. 使用Except的逆操作3. 使用LINQ的Join,GroupJoin

Python实现对阿里云OSS对象存储的操作详解

《Python实现对阿里云OSS对象存储的操作详解》这篇文章主要为大家详细介绍了Python实现对阿里云OSS对象存储的操作相关知识,包括连接,上传,下载,列举等功能,感兴趣的小伙伴可以了解下... 目录一、直接使用代码二、详细使用1. 环境准备2. 初始化配置3. bucket配置创建4. 文件上传到os

关于集合与数组转换实现方法

《关于集合与数组转换实现方法》:本文主要介绍关于集合与数组转换实现方法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、Arrays.asList()1.1、方法作用1.2、内部实现1.3、修改元素的影响1.4、注意事项2、list.toArray()2.1、方

使用Python实现可恢复式多线程下载器

《使用Python实现可恢复式多线程下载器》在数字时代,大文件下载已成为日常操作,本文将手把手教你用Python打造专业级下载器,实现断点续传,多线程加速,速度限制等功能,感兴趣的小伙伴可以了解下... 目录一、智能续传:从崩溃边缘抢救进度二、多线程加速:榨干网络带宽三、速度控制:做网络的好邻居四、终端交互