C# 操作 Word 修改word的高级属性中的自定义属性

word的类库使用的是word2007版本的类库,类库信息见下面图片,折腾了半天,终于找到入口,网上 很多说的添加或者修改word的高级属性中的自定义属性都是错误的,感觉都是在copy网上的代码,自己终于摸索成功了,Mark下。

直接上代码,代码如下:

[csharp] view plaincopy

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.IO;
  6. using System.Collections;
  7. using Microsoft.Office.Interop.Word;
  8. using Microsoft.Office.Core;
  9. using System.Reflection;
  10. namespace TestWord
  11. {
  12. /// <summary>
  13. /// 从传入的word文档中替换掉指定书签的内容,主要是为了解决封面中的内容
  14. /// 抽取命令:
  15. /// xx.exe -p D:/temp/test.doc D:/result/mappting.txt
  16. ///
  17. /// mappting.txt 文件是替换test.doc文档中标签的匹配文件,比如哪个标签的内容需要替换为其他的值
  18. /// </summary>
  19. class PageExtractor : IExtractor
  20. {
  21. private object oMissing = System.Reflection.Missing.Value;
  22. //标准页眉要替换的值在mapping.txt文件中存储的key
  23. private String TB_YEMEI_GJB = "TB_YEMEI_GJB";
  24. //写入word的高级属性中的内容,需要设置为整形的高级属性名
  25. private String[] m_oIntegerAdvPropertyNames = new String[]{ "密级","稿件"};
  26. //写入word的高级属性中的内容,需要设置为boolean
  27. private String[] m_oBoolAdvPropertyNames = new String[] { "TRS" };
  28. /// <summary>
  29. /// 从指定word中抽取出word正文
  30. /// </summary>
  31. /// <param name="_sSourceWordPath"></param>
  32. /// <returns></returns>
  33. public bool execute(string[] args)
  34. {
  35. _Application oWord = WordProcessHelper.getInstance().getApplication();
  36. _Document oDoc = null;
  37. String _sWordPath = "";
  38. LogServer currLogServer = LogServer.getInstance();
  39. try
  40. {
  41. //1.参数需要长度为3,第一个是“-p”,第二个是“要抽取的word路径”,第三个是“匹配的书签替换文件”
  42. if (args.Length < 3)
  43. {
  44. throw new Exception("替换封面时传入的参数个数至少为3个,第一个是‘-p’,第二个是‘要抽取的word路径’,第三个是标签‘匹配的UTF-8编码的txt文件内容’,第四个是文档的高级属性内容");
  45. }
  46. _sWordPath = args[1];//获取要抽取的原word路径
  47. if (!File.Exists(_sWordPath))
  48. {
  49. throw new Exception("Word文件[" + _sWordPath + "]不存在!");
  50. }
  51. String sMappingFilePath = args[2];
  52. if (CMyString.isEmpty(sMappingFilePath))
  53. {
  54. throw new Exception("没有传入替换doc文件内容的匹配文件路径!");
  55. }
  56. //1.读取需要替换的文件内容
  57. Properties mappingProperties = new Properties(sMappingFilePath);
  58. if (mappingProperties.size() <= 0)
  59. {
  60. currLogServer.writeLogLine("文件[" + sMappingFilePath + "]中要替换的内容为空!");
  61. return true;
  62. }
  63. //2.读取word中标签
  64. DateTime beginDateTime = new DateTime();
  65. object oDocFilePath = _sWordPath;
  66. object oReadOnly = false;
  67. object oAddToRecentFiles = false;
  68. oDoc = oWord.Documents.Open(ref oDocFilePath, ref oMissing, ref oReadOnly, ref oAddToRecentFiles, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing);
  69. //3.获取标签名与对应的Range对象的对应关系
  70. Hashtable oBookIdToRangeMap = getBookIdToRange(oDoc, mappingProperties);
  71. if (oBookIdToRangeMap == null || (oBookIdToRangeMap.Count == 0))
  72. {
  73. return true;
  74. }
  75. //4.替换Range对象的内容为mapping文件中的属性值
  76. replaceMappingContent(oDoc, oBookIdToRangeMap, mappingProperties);
  77. //5.替换页眉
  78. Range allRange = oDoc.Range(ref oMissing, ref oMissing);
  79. Sections allSections = allRange.Sections;
  80. currLogServer.writeLogLine("开始替换[" + _sWordPath + "]页眉.");
  81. if (allSections != null && (allSections.Count > 0))
  82. {
  83. String sTBYeMeiGJB = mappingProperties.getPropertyAsString(TB_YEMEI_GJB, false);
  84. currLogServer.writeLogLine("[" + _sWordPath + "]页眉要替换的值为:" + sTBYeMeiGJB);
  85. sTBYeMeiGJB = CMyString.showEmpty(sTBYeMeiGJB);
  86. for (int i = 1; i <= allSections.Count; i++)
  87. {
  88. Section aSection = allSections[i];
  89. if (aSection == null)
  90. {
  91. continue;
  92. }
  93. //设置奇数页和偶数页的页眉
  94. aSection.Headers[WdHeaderFooterIndex.wdHeaderFooterPrimary].Range.Text = sTBYeMeiGJB;
  95. aSection.Headers[WdHeaderFooterIndex.wdHeaderFooterEvenPages].Range.Text = sTBYeMeiGJB;
  96. }
  97. }
  98. DateTime endDateTime = new DateTime();
  99. String sTimeDuration = DateTimeHelper.dateDiff(beginDateTime, endDateTime);
  100. currLogServer.writeLogLine("[" + _sWordPath + "]页眉替换完成,用时:" + sTimeDuration);
  101. //TDO:写入国军标的一些标准属性
  102. //读取需要写入到文档高级属性的
  103. if (args.Length < 4) {
  104. return true;
  105. }
  106. String sAdvancePropertyFilePath=args[3];
  107. if (CMyString.isEmpty(sAdvancePropertyFilePath)) {
  108. return true;
  109. }
  110. Properties advanceProperties = new Properties(sAdvancePropertyFilePath);
  111. if (advanceProperties.size() <= 0)
  112. {
  113. currLogServer.writeLogLine("文件[" + sAdvancePropertyFilePath + "]中要写入的高级属性内容为空!");
  114. return true;
  115. }
  116. //写入属性
  117. currLogServer.writeLogLine("[" + _sWordPath + "]开始写入高级属性.");
  118. writeDocAdvanceProperty(oDoc, advanceProperties);
  119. currLogServer.writeLogLine("[" + _sWordPath + "]高级属性写入完成.");
  120. //TODO:返回成功标记
  121. return true;
  122. }
  123. catch (Exception ex)
  124. {
  125. currLogServer.writeLogLine("页眉替换从文件[" + _sWordPath + "]时发生错误:"+ex.Message);
  126. throw new Exception("页眉替换从文件[" + _sWordPath + "]时发生错误", ex);
  127. }
  128. finally
  129. {
  130. //关闭当前文档
  131. object saveOption = WdSaveOptions.wdSaveChanges;
  132. if (oDoc != null)
  133. {
  134. oDoc.Close(ref saveOption, ref oMissing, ref oMissing);
  135. //System.Runtime.InteropServices.Marshal.ReleaseComObject(oDoc);
  136. }
  137. }
  138. }
  139. /// <summary>
  140. /// 把指定的高级属性的Properties中的内容写入到文档的高级属性中
  141. /// </summary>
  142. /// <param name="oDoc"></param>
  143. /// <param name="advanceProperties"></param>
  144. private void writeDocAdvanceProperty(_Document oDoc, Properties advanceProperties) {
  145. if (oDoc == null || (advanceProperties == null) || (advanceProperties.size()<=0))
  146. {
  147. return;
  148. }
  149. //遍历Properties属性
  150. Hashtable allAdvanceProperties=advanceProperties.getProperties();
  151. if (allAdvanceProperties == null || (allAdvanceProperties.Count <= 0)) {
  152. return;
  153. }
  154. //获取高级属性对象
  155. object oDocCustomProps = oDoc.CustomDocumentProperties;
  156. Type typeDocCustomProps = oDocCustomProps.GetType();
  157. //遍历集合
  158. foreach (String sPropName in allAdvanceProperties.Keys)
  159. {
  160. String sValue = (String)allAdvanceProperties[sPropName];
  161. sValue = CMyString.showEmpty(sValue);
  162. //获取属性名的类型
  163. Object oPropItemObj = getPropertyObjByName(oDocCustomProps, typeDocCustomProps, sPropName);
  164. if (oPropItemObj == null)
  165. {
  166. //不存在,则添加
  167. MsoDocProperties oPropertType = getPropertyTypeByName(sPropName);
  168. object[] oArgs = {sPropName,false,
  169. oPropertType,
  170. sValue};
  171. typeDocCustomProps.InvokeMember("Add", BindingFlags.Default |
  172. BindingFlags.InvokeMethod, null,
  173. oDocCustomProps, oArgs);
  174. }
  175. else {
  176. //已经存在,则覆盖属性
  177. Type typeItemProp = oPropItemObj.GetType();
  178. typeItemProp.InvokeMember("Value",
  179. BindingFlags.Default | BindingFlags.SetProperty,
  180. null, oPropItemObj,
  181. new object[] { sValue });
  182. }
  183. }
  184. }
  185. /// <summary>
  186. /// 从指定的自定义高级属性中查找指定名称的Item对象,如果没有找到,则返回null
  187. /// </summary>
  188. /// <param name="oDocCustomProps"></param>
  189. /// <param name="typeDocCustomProps"></param>
  190. /// <param name="_sPropertyName"></param>
  191. /// <returns></returns>
  192. private object getPropertyObjByName(object oDocCustomProps,Type typeDocCustomProps, String _sPropertyName)
  193. {
  194. if (CMyString.isEmpty(_sPropertyName)) {
  195. return null;
  196. }
  197. if (oDocCustomProps == null || typeDocCustomProps == null) {
  198. return null;
  199. }
  200. //通过反射去查找对象
  201. //获取值
  202. object oPropItem = null;
  203. try
  204. {
  205. oPropItem = typeDocCustomProps.InvokeMember("Item",
  206. BindingFlags.Default |
  207. BindingFlags.GetProperty,
  208. null, oDocCustomProps,
  209. new object[] { _sPropertyName });
  210. }
  211. catch (Exception ex) {
  212. //TODO:由于没有找到判断是否存在属性的接口,所以这里通过Item来判断,如果属性不存在,则会报错,这里粗鲁的忽略掉异常
  213. oPropItem = null;
  214. }
  215. //返回结果
  216. return oPropItem;
  217. }
  218. /// <summary>
  219. /// 根据属性名获取该属性对应的类型
  220. /// </summary>
  221. /// <param name="sPropName"></param>
  222. /// <returns></returns>
  223. private MsoDocProperties getPropertyTypeByName(String sPropName)
  224. {
  225. if (CMyString.isEmpty(sPropName)) {
  226. return MsoDocProperties.msoPropertyTypeString;
  227. }
  228. //判断是否是整形
  229. bool bInStrArray = CMyList.isInStrArray(sPropName, m_oIntegerAdvPropertyNames, true);
  230. if (bInStrArray) {
  231. return MsoDocProperties.msoPropertyTypeNumber;
  232. }
  233. //判断是否是bool型
  234. bInStrArray = CMyList.isInStrArray(sPropName, m_oBoolAdvPropertyNames, true);
  235. if (bInStrArray) {
  236. return MsoDocProperties.msoPropertyTypeBoolean;
  237. }
  238. //默认返回字符串
  239. return MsoDocProperties.msoPropertyTypeString;
  240. }
  241. /// <summary>
  242. /// 返回指定文档中需要替换属性的书签名称与Range对象HashTable对象
  243. /// </summary>
  244. /// <param name="oDoc"></param>
  245. /// <param name="mappingProperties"></param>
  246. /// <returns></returns>
  247. private Hashtable getBookIdToRange(_Document oDoc, Properties mappingProperties) {
  248. //1.参数校验
  249. Hashtable oBookIdToRangeMap = new Hashtable();
  250. if (oDoc == null || (mappingProperties == null)) {
  251. return oBookIdToRangeMap;
  252. }
  253. //获取标签内容
  254. Bookmarks allBookMars = oDoc.Bookmarks;
  255. for (int i = 1; i <= allBookMars.Count; i++)
  256. {
  257. object oIndex = i;
  258. Bookmark aBookMark = allBookMars.get_Item(ref oIndex);
  259. if (aBookMark == null)
  260. {
  261. continue;
  262. }
  263. String sBookName = aBookMark.Name;
  264. if (CMyString.isEmpty(sBookName)) {
  265. continue;
  266. }
  267. //是否包含在要替换的属性集合中
  268. if (!mappingProperties.contains(sBookName,true)) {
  269. continue;
  270. }
  271. //压入书签名称与Range对象集合中
  272. oBookIdToRangeMap.Add(sBookName.Trim().ToUpper(), aBookMark.Range);
  273. }
  274. //返回集合中
  275. return oBookIdToRangeMap;
  276. }
  277. /// <summary>
  278. /// 根据 mappingProperties中的属性值替换 oBookIdToRangeMap 指定Range对象的内容,并设置Range对象的书签名称
  279. /// </summary>
  280. /// <param name="oDoc"></param>
  281. /// <param name="oBookIdToRangeMap"></param>
  282. /// <param name="mappingProperties"></param>
  283. private void replaceMappingContent(_Document oDoc,Hashtable oBookIdToRangeMap, Properties mappingProperties)
  284. {
  285. //1.参数校验
  286. if (oDoc == null || (oBookIdToRangeMap == null) || (mappingProperties == null)) {
  287. return;
  288. }
  289. //2.遍历Map对象
  290. foreach (String sBookIdKey in oBookIdToRangeMap.Keys)
  291. {
  292. Range currBookRange = (Range)oBookIdToRangeMap[sBookIdKey];
  293. if (currBookRange == null) {
  294. continue;
  295. }
  296. //获取替换的值
  297. String sReplaceValue = mappingProperties.getPropertyAsString(sBookIdKey,true);
  298. sReplaceValue = CMyString.showEmpty(sReplaceValue);
  299. currBookRange.Text = sReplaceValue;
  300. //重新设置书签
  301. if (!oDoc.Bookmarks.Exists(sBookIdKey))
  302. {
  303. object oTempBookRange = currBookRange;
  304. oDoc.Bookmarks.Add(sBookIdKey, ref oTempBookRange);
  305. }
  306. }
  307. }
  308. }
  309. }
时间: 2024-10-13 19:26:21

C# 操作 Word 修改word的高级属性中的自定义属性的相关文章

批量修改WORD表格属性

有时候需要对word中很多表格的属性进行修改,而word无法批量修改属性,所有这里记录一个宏 Sub TableFormatter() Dim oTbl As Table, i As Integer For Each oTbl In Selection.Tables With oTbl .Rows.AllowBreakAcrossPages = False .Rows(1).HeadingFormat = True For i = 1 To .Columns.Count If i = 1 The

Aspose操作Excel和Word

这段时间一直在做office报表开发总结一下!Aspose操作遇到的难点. 读取出excel中的图片保存为静态图 public void ReadPic(string path, string toPath) { Common com = new Common(); int count = 1; try { string fileSaveName = String.Empty; string savePath = string.Empty; int chartNum = sheet.Charts

教您如何在Word的mathtype加载项中修改章节号

在MathType数学公式编辑器中,公式编号共有五部分内容:分别是章编号(Chapter Number).节编号(Section Number).公式编号(Equation Number).括号(Enclosure). 分隔符(Separator).这五部分内容可以进行自由切换,以实现不同的需要.本文将以Microsoft office为例,教大家如何在word的mathtype加载项中修改章节号. 公式编号的设置方法: 1.单击word文档中的MathType加载项,点击第三列中插入编号的倒置

怎么批量修改Word表格的宽度

怎么批量修改Word表格的宽度 怎么批量修改Word表格的宽度呢.Word表格可根据窗口自动调整表格宽度,使得所有的表格宽度和页面宽度一样.当页面设置了新的页边距后,所有的表格都需要调整新的宽度.或者文档中有许多大大小小的表格,希望宽度全部调整与页宽一样.下面的方法就非常有用啦. 第一步.打开Word文档,按下[Alt + F11] 第二步.在VBA编辑器窗口的左上方,双击[ThisDocument] 第三步.在右侧选择[Document],再在其右侧下拉选择[Open] 第四步.然后在宏代码编

WPS Office for Mac如何修改Word文档文字排列?WPS office修改Word文档文字排列方向教程

Word文档如何改变文字的排列方向?最新版WPS Office for Mac修复了文字排版相关的细节问题,可以更快捷的进行Word编辑,WPS Office在苹果电脑中如何修改Word文档文字排列方向呢?下面小编给大家带来详细的WPS office修改Word文档文字排列方向教程,希望对大家有所帮助! https://www.macdown.com WPS Office for Mac特别注意 为保证最新版WPS Office for Mac正常使用,请在安装WPS Office 2019 f

Expo大作战(二十三)--expo中expo kit 高级属性(没干货)

简要:本系列文章讲会对expo进行全面的介绍,本人从2017年6月份接触expo以来,对expo的研究断断续续,一路走来将近10个月,废话不多说,接下来你看到内容,讲全部来与官网 我猜去全部机翻+个人修改补充+demo测试的形式,对expo进行一次大补血!欢迎加入expo兴趣学习交流群:597732981 [之前我写过一些列关于expo和rn入门配置的东i西,大家可以点击这里查看:从零学习rn开发] 相关文章: Expo大作战(一)--什么是expo,如何安装expo clinet和xde,xd

hbase建表create高级属性 //hbase 表预分区也就是手动分区 这个很重要

2019/2/19 星期二 hbase建表create高级属性 //hbase 表预分区也就是手动分区 这个很重要 下面几个shell 命令在后续的hbase 操作中可以起到很到的作用,且主要体现在建表的过程中,看下面几个create 属性1.BLOOMFILTER 默认是NONE 是否使用布隆过虑使用何种方式布隆过滤可以每列族单独启用.使用HColumnDescriptor.setBloomFilterType(NONE |ROW | ROWCOL) 对列族单独启用布隆.Default = N

网络操作不能直接写在主线程中 以及 为什么不能在子线程中更新UI控件的属性

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ //注意: 所有网络操作不能直接写在主线程中 因为所有的网络操作都是耗时的,如果加载到主线程中,会导致与用户的交互出现问题 ,所以要加载到子线程中 // [self loadImage]; [self performSelectorInBackground:@selector(loadImage) withObject:nil]; } //加

Storm高级属性

之前写了2篇文章讲述了Storm的基本知识.最近也学习了Storm的高级属性了,单纯粹还是属于了解的状态.我就简单介绍几个比较简单的属性. 1.DRPC.简称分布式RPC,模型图: 用户直接面对的是DRPC Server,避开了所有的拓扑逻辑,Storm提供了一个名为LinearDRPCTopologyBuilder的线性拓扑构建器,他把DRPC所做的几乎所有步骤都自动实现了.本地模式的代码例子如下: LocalDRPC drpc = new LocalDRPC(); LocalCluster