C# 读取多条数据记录导出到 Word标签模板之图片输出改造

目录

应用需求

设计

范例运行环境

配置Office DCOM

实现代码

组件库引入

​核心代码

调用示例

小结


应用需求

在我的文章《C# 读取多条数据记录导出到 Word 标签模板》里,讲述读取多条数据记录结合 WORD 标签模板输出文件的功能,原有输出图片的约定是在 WORD 模板文件中借助书签设置进行输出,如下图:

该书签名称代表了一条指令,格式为(输出关键字_图片宽度_图片高度)。如图中书签名称设置,当系统遇到 ds_qz 关键字时,输出按后继设置进行,图片宽度为100、图片高度为 50。

现有一模板需求如下图:

我们需要在考官评语和考官本人签字位置输出手写图片,原有的书签模式输出会遇到一些问题:

(1)只能为嵌入式,位置输出无法设置,无法进一步调整到较优呈现位置。

(2)只能插入式输出,无法实现嵌入式如文字浮动、环绕效果。

(3)需要在无关位置插入书签,否则会在输出关键字时被替换掉,而无法识别配置。

(4)书签的名称不能输入一些特定字符,如%,减号等,给配置带来一些麻烦。

(5)如果在文档里真需要设置书签,容易造成混乱。

设计

设计提供一个 ArrayList 类型参数取代书签模式的设计,其格式为 (输出关键字_图片宽度_图片高度_图片 Left 相对值_图片 Top 相对值 )。如添加 ds_qz_100_50_500_-20 字符串,当系统遇到 ds_qz 关键字时,输出按后继设置进行,图片宽度为100、图片高度为 50、图片 Left 为500、图片 Top 为 -20。后四个参数如果设置null则表示忽略,ds_qz_null_null_500_-20 ,则表示忽略宽度和高度设置,即表示原始大小输出。

定位到的图片输出,采取浮动于文字下方的处理。

范例运行环境

操作系统: Windows Server 2019 DataCenter

操作系统上安装 Office Word 2016

数据库:Microsoft SQL Server 2016

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

开发工具:VS2019  C#

配置Office DCOM

配置方法可参照我的文章《C# 读取Word表格到DataSet》进行处理和配置。

实现代码

组件库引入

核心代码

public string DataTableToWord(string _filename,string _repeatKey,object _dataset,ArrayList DataSetPictureConfig),该方法提供4个参数,WORD模板文件名、自定义关键字、System.Data.DataSet,配置图片用的 ArrayList 列表指令。

public void DataTableToWord(string _filename,string _repeatKey,object _dataset,ArrayList DataSetPictureConfig){if (DataSetPictureConfig == null) { DataSetPictureConfig = new ArrayList(); }Object Nothing = System.Reflection.Missing.Value;object filename = _filename;//创建一个名为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;//关闭显示拼写错误提示框WordApp.Selection.WholeStory();WordApp.Selection.Cut();DataSet ds=(DataSet)_dataset;System.Data.DataTable  dt=ds.Tables[0];for(int i=0;i<dt.Rows.Count;i++){WordApp.Selection.Paste();for(int j=0;j<dt.Columns.Count;j++){string _repKey=_repeatKey+dt.Columns[j].ColumnName.ToString();string _repValue=string.Format("{0}",dt.Rows[i][j].ToString());bool isPhoto=false;if(dt.Columns[j].DataType==typeof(System.Byte[])){isPhoto=true;_repValue="";}WordApp.Options.ReplaceSelection=true;Word.Find fnd = WordApp.Selection.Find;fnd.ClearFormatting();Object findText = _repKey;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;while(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)){string r_f=WordApp.Selection.Font.Name.ToString();WordApp.Selection.Range.Text=_repValue;if(isPhoto==true){string _jpgfile=_path+System.Guid.NewGuid()+".jpg";if (dt.Rows[i][j] == System.DBNull.Value){continue;}byte[] filedata = (byte[])dt.Rows[i][j];System.IO.MemoryStream ms = new MemoryStream(filedata);System.Drawing.Image img1 = System.Drawing.Image.FromStream(ms);img1.Save(@_jpgfile);ms.Close();Word.InlineShape pic= WordApp.Selection.InlineShapes.AddPicture(@_jpgfile,false,true);foreach (string bm in  DataSetPictureConfig){string _findkey=_repKey+"_";int _f1 =bm.IndexOf(_findkey);if(_f1==0 && bm.Length>(_findkey.Length)){string[] _paras=bm.Substring(_findkey.Length,bm.Length-_findkey.Length).Split('_');if(_paras.GetLength(0)>1){if (_paras[0] != "null"){int def_width = int.Parse(_paras[0]);pic.Width = def_width;}if (_paras[1] != "null"){int def_height = int.Parse(_paras[1]);pic.Height = def_height;}}}}Word.Shape pic2 = pic.ConvertToShape();pic2.WrapFormat.Type = Word.WdWrapType.wdWrapThrough;pic2.WrapFormat.Type = Word.WdWrapType.wdWrapBehind;pic2.Left = 0;pic2.Top = 0;foreach (string bm in DataSetPictureConfig){string _findkey = _repKey + "_";int _f1 = bm.IndexOf(_findkey);if (_f1 == 0 && bm.Length > (_findkey.Length)){string[] _paras = bm.Substring(_findkey.Length, bm.Length - _findkey.Length).Split('_');if (_paras.GetLength(0) > 3){if (_paras[2] != "null")pic2.Left = float.Parse(_paras[2]);if (_paras[3] != "null")pic2.Top =float.Parse(_paras[3]);}}}File.Delete(@_jpgfile);}}}object dummy = System.Reflection.Missing.Value;object what = Word.WdGoToItem.wdGoToLine;object which = Word.WdGoToDirection.wdGoToLast;object count = System.Reflection.Missing.Value;
//					WordApp.Selection.GoTo(ref oGoToItem, ref oGoToLast, ref Nothing, ref Nothing);WordApp.Selection.GoTo(ref what, ref which, ref count, ref dummy);//default 表示每行记录之间插入分页符,最后一行时不再插入分页符,以免造成多余一空白页if(i!=dt.Rows.Count-1){object ib = Word.WdBreakType.wdPageBreak; WordApp.Selection.InsertBreak(ref ib);}}}WordDoc.Save();WordDoc.Close(ref Nothing, ref Nothing, ref Nothing);//关闭WordApp组件对象WordApp.Quit(ref Nothing, ref Nothing, ref Nothing);}

调用示例

示例代码如下:

DataSet rv = GetDataSet("select * from tabble");ArrayList picconfig = new ArrayList();   //可配置每个图片字段的大小及位置
picconfig.Add("ds_kg_sign_100_50_500_-20");   //格式为: key_width_height_left_top
string ModuleFile = "d:\\bfile\\word\\面试评分表.docx";  //假设的模板文件
string _lastfile = DataTableToWord(ModuleFile,"ds_",ds,picconfig);MessageBox.Show(string.Format("已成功导出文件:{0}", _lastfile));

运行结果预览如下图:

 

小结

核心代码中需要将 Word.InlineShape 转换为 Word.Shape 后,可以进行环绕文字的操作,如下:

Word.Shape pic2 = pic.ConvertToShape();
pic2.WrapFormat.Type = Word.WdWrapType.wdWrapThrough;
pic2.WrapFormat.Type = Word.WdWrapType.wdWrapBehind;
pic2.Left = 0;
pic2.Top = 0;

使用 ConvertToShape() 方法转换为 pic2 , pic2.WrapFormat.Type = Word.WdWrapType.wdWrapBehind;  可以浮动于文字下方,然后初始图片的 Left 和 Top ,否则有可能无法正常显示位置。

我们可以根据自己的实际情况设置环绕格式,可参阅读如下地址:

https://learn.microsoft.com/zh-cn/office/vba/api/word.wdwraptypemerged

这些代码我们提供了一些操作WORD相关的关键方法,这里仅作参考,欢迎大家评论指教!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/478239.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

『 Linux 』网络层 - IP协议 (二)

文章目录 路由NAT技术分片与组装分片的组装IP协议分片的短板 路由 通常情况路由器具备了一个非常重要的功能,即构建子网; 同时路由器需要实现跨网络通信,说明路由器必须存在两个或以上的IP地址,通常在路由器中可以看到几个接口,分别是一个WAN口和几个LAN口; WAN口IP被称为公网I…

使用 OpenCV 进行视频中的行人检测

在计算机视觉领域&#xff0c;行人检测是一个重要的研究方向&#xff0c;它在视频监控、自动驾驶、人机交互等领域都有着广泛的应用。本文将介绍如何使用 OpenCV 库来实现视频中的行人检测。 环境准备 首先&#xff0c;我们需要安装 OpenCV 库。可以通过以下命令来安装&#…

javaEE初阶——多线程(1)

文章目录 一些背景知识操作系统&#xff08;OS&#xff09;&#xff08;计算机的大管家&#xff09;操作系统的基本概念&#xff1a;市面上常见的操作操作系统&#xff1a; 关于前端与后端的介绍&#xff1a;&#xff08;针对服务的体系架构&#xff09;计算机是如何工作的&…

Apple Vision Pro开发003-PolySpatial2.0新建项目

unity6.0下载链接:Unity 实时开发平台 | 3D、2D、VR 和 AR 引擎 一、新建项目 二、导入开发包 com.unity.polyspatial.visionos 输入版本号 2.0.4 com.unity.polyspatial&#xff08;单独导入&#xff09;&#xff0c;或者直接安装 三、对应设置 其他的操作与之前的版本相同…

学习threejs,使用设置normalMap法向量贴图创建更加细致的凹凸和褶皱

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️THREE.MeshPhongMaterial高…

Python办公自动化案例:将演示文稿批量导出为图片和PDF文件

案例:将演示文稿批量导出为图片和PDF文件 准备资料:准备好PPT,并起好名称,放在同一目录下。 批量的将ppt,pptx转换为pdf和图片,代码如下: import comtypes.client import osdef init_powerpoint():powerp

数据结构 ——— 直接选择排序算法的实现

目录 直接选择排序算法的思想 优化直接选择排序算法的思想 代码实现&#xff08;默认升序&#xff09; 直接选择排序算法的思想 直接选择排序算法的思想类似与直接插入排序 区别在于从大到小选择最小的元素或者最大的元素直接放在元素应该停留的位置每次从待排序的元素中选…

linux从0到1——shell编程9

声明&#xff01; 学习视频来自B站up主 **泷羽sec** 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团队无关&a…

selinux及防火墙

selinux说明 SELinux 是 Security-Enhanced Linux 的缩写&#xff0c;意思是安全强化的 linux 。 SELinux 主要由美国国家安全局&#xff08; NSA &#xff09;开发&#xff0c;当初开发的目的是为了避免资源的误用。 httpd进程标签&#xff08;/usr/share/nginx/html &#…

前端:JavaScript (学习笔记)【2】

目录 一&#xff0c;数组的使用 1&#xff0c;数组的创建 [ ] 2&#xff0c;数组的元素和长度 3&#xff0c;数组的遍历方式 4&#xff0c;数组的常用方法 二&#xff0c;JavaScript中的对象 1&#xff0c;常用对象 &#xff08;1&#xff09;String和java中的Stri…

QML学习 —— 28、3种等待指示控件(附源码)

效果如下 说明 BusyIndicator应用于指示在加载内容或UI被阻止等待资源可用时的活动。BusyIndicator类似于一个不确定的ProgressBar。两者都可以用来指示背景活动。主要区别在于视觉效果,ProgressBar还可以显示具体的进度(当可以确定时)。由于视觉差异,繁忙指示器和不确定的…

Java 基于SpringBoot+Vue的家政服务管理平台

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

DataGear 5.2.0 发布,数据可视化分析平台

DataGear 企业版 1.3.0 已发布&#xff0c;欢迎体验&#xff01; http://datagear.tech/pro/ DataGear 5.2.0 发布&#xff0c;图表插件支持定义依赖库、严重 BUG 修复、功能改进、安全增强&#xff0c;具体更新内容如下&#xff1a; 重构&#xff1a;各模块管理功能访问路径…

nature communications论文 解读

题目《Transfer learning with graph neural networks for improved molecular property prediction in the multi-fidelity setting》 这篇文章主要讨论了如何在多保真数据环境&#xff08;multi-fidelity setting&#xff09;下&#xff0c;利用图神经网络&#xff08;GNNs&…

Flutter:SlideTransition位移动画,Interval动画延迟

配置vsync&#xff0c;需要实现一下with SingleTickerProviderStateMixinclass _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin{// 定义 AnimationControllerlate AnimationController _controller;overridevoid initState() {super.…

svn 崩溃、 cleanup失败 怎么办

在使用svn的过程中&#xff0c;可能出现整个svn崩溃&#xff0c; 例如cleanup 失败的情况&#xff0c;类似于 这时可以下载本贴资源文件并解压。 或者直接访问网站 SQLite Download Page 进行下载 解压后得到 sqlite3.exe 放到发生问题的svn根目录的.svn路径下 右键呼出pow…

GPT系列文章

GPT系列文章 GPT1 GPT1是由OpenAI公司发表在2018年要早于我们之前介绍的所熟知的BERT系列文章。总结&#xff1a;GPT 是一种半监督学习&#xff0c;采用两阶段任务模型&#xff0c;通过使用无监督的 Pre-training 和有监督的 Fine-tuning 来实现强大的自然语言理解。在 Pre-t…

Linux线程(Linux和Windows的线程区别、Linux的线程函数、互斥、同步)

Linux线程&#xff08;Linux和Windows的线程区别、Linux的线程函数、互斥、同步&#xff09; 1. 线程介绍 线程的概念&#xff1a; 线程是 CPU 调度的基本单位。它被包含在进程之中&#xff0c;是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流&#xff0…

Large Spatial Model:End-to-end Unposed Images to Semantic 3D 论文解读

目录 一、概述 二、相关工作 1、SfM和可微神经表示 2、端到端的Image-to-3D 三、LSM 1、密集几何预测 2、2D信息特征提取 3、点特征融合 4、可微渲染 5、损失函数 四、实验 一、概述 该论文提出一种大型空间模型&#xff08;Larget Spatial Model,LSM&#xff09;…

Leetcode207. 课程表(HOT100)

链接 题解&#xff1a;先统计入度为0的点&#xff0c;如果一个节点入度为0&#xff0c;说明没有课程指向它&#xff0c;那么你就可以学习它了。反之说明还有先修课。 注意&#xff1a;图存在拓扑排序等价于图不存在环。其实可以想出&#xff1a;如果是一个环&#xff0c;那么…