0


干部任免管理系统(五)开源了一个c#开发的任免审批表转word的程序

前言:

  1. 好久没有写博文了,最近有几位csdn的网友想找过来借鉴开发的管理系统,因为工作调整我已经不在公司管理干部了,整套系统当时本身就是为了方便自己工作捣鼓的,现在也没人用了。牵涉到打架java运行环境,数据库,整合企业微信登录等等,要用起来也不方便,所以干脆就重新把最核心的转换审批表到实体类,然后再转换为word,以及提取简历功能用c#写了winform程序了。

程序开源地址:

干部任免审批报转换为word: 将干部任免审批表批量转换为word格式

首先声明本人不是专业的程序员,代码是比较烂我自己也知道,纯属给大家提供一个解决问题的思路。

程序实现的主要代码:

一、Lrmx文件解析:

  1. 本质上中组部任免审批表的lrmx文件就是一个xml格式文档,只是后缀为lrmx格式,核心思想就是解析xml文件,让文件中的内容与我们自己所定义的类对应。

1. 用到的依赖包:

1.1 Nlog 及 Nlog.from 日志记录用
1.2 NPOI 用于操作word和excel的。用这个包最大的好处就是你不需要去考虑客户端是否有安装office。
1.3 System.Xml.XDocument 和 System.Xml.ReaderWriter xml的解析工具了。

2. 定义的几个核心实体类

2.1 最核心的GanBu类
  1. public class GanBu
  2. {
  3. public String XingMing; //姓名 1,0,0 1,0,1
  4. public String XingBie; //性别 1,0,2 1,0,3
  5. public String ChuShengNianYue; //出生年月 YYYYMM格式 1,0,4 1,0,5
  6. public String MinZu; //民族 1,1,0 1,1,1
  7. public String JiGuan; //籍贯 1,1,2 1,1,3
  8. public String ChuShengDi;// 出生地 1,1,4 1,1,5
  9. public String RuDangShiJian;// 入党时间 1,2,0
  10. public String CanJiaGongZuoShiJian;//参加工作时间 1,2,2
  11. public String JianKangZhuangKuang;//健康状况 1,2,4
  12. public String ZhuanYeJiShuZhiWu;//专业技术职务 1,3,0
  13. public String ShuXiZhuanYeYouHeZhuanChang;//熟悉专业有何专长 1,3,2
  14. public String QuanRiZhiJiaoYu_XueLi;//全日制教育学历 1,4,2
  15. public String QuanRiZhiJiaoYu_XueWei;//全日制教育学位 1,4,2
  16. public String QuanRiZhiJiaoYu_XueLi_BiYeYuanXiaoXi;//全日制毕业学校 1,4,4
  17. public String QuanRiZhiJiaoYu_XueWei_BiYeYuanXiaoXi;//全日制毕业院校专业 1,5,4
  18. public String ZaiZhiJiaoYu_XueLi;//在职教育学历 1,6,2
  19. public String ZaiZhiJiaoYu_XueWei;//在职教育学位 1,6,2
  20. public String ZaiZhiJiaoYu_XueLi_BiYeYuanXiaoXi;//在职教育毕业院校 1,6,4
  21. public String ZaiZhiJiaoYu_XueWei_BiYeYuanXiaoXi;//在职教育毕业院校专业 1,7,4
  22. public String XianRenZhiWu;//现任职务 1,8,0
  23. public String NiRenZhiWu;//拟任职务 1,9,0
  24. public String NiMianZhiWu;//拟免职务 1,10,0
  25. public List<JianLi> JianLi; //简历 1,11,0
  26. public String JiangChengQingKuang;//奖惩情况 2,0,0
  27. public String NianDuKaoHeJieGuo;//年度考核结果 2,1,0
  28. public String RenMianLiYou;//任免理由 2,2,0
  29. public List<JiaTingChengYuan> JiaTingChengYuan;//家庭成员 2,4,1 称谓 2 姓名 3 年龄 4 政治面貌 5 工作单位及职务
  30. public String ChengBaoDanWei;//承报单位
  31. public String JiSuanNianLingShiJian;//计算年龄时间
  32. public String TianBiaoShiJian;//填报时间
  33. public String TianBiaoRen;//填报人
  34. public String ShenFenZheng;//身份证号码
  35. public String ZhaoPian;// 照片
  36. public String Version;//版本
  37. public int NianLing; //年龄
  38. }
2.2 JianLi 类
  1. public class JianLi
  2. {
  3. public String KaiShiNianYue;
  4. public String JieSuNianYue;
  5. public String JingLi; //经历
  6. }
2.3 JiaTingChengYuan 类
  1. public class JiaTingChengYuan
  2. {
  3. public String ChengWei;//称谓
  4. public String XingMing;//姓名
  5. public String ChuShengRiQi;//出生日期 YYYYMM
  6. public String ZhengZhiMianMao;//政治面貌
  7. public String GongZuoDanWeiJiZhiWu;//工作单位及职务
  8. public int NianLing; //年龄
  9. }

3 解析lrmx文件过程

  1. 代码就是读取xml文件,将对应的内容解析赋值给GanBu
3.1 完整转换为类的代码
  1. private GanBu LrmxToClass(string filename) {
  2. GanBu ganBu = new GanBu();
  3. Type type = ganBu.GetType();
  4. try {
  5. XmlDocument xmlDoc = new XmlDocument();
  6. xmlDoc.Load(filename);
  7. XmlNodeList nl = xmlDoc.DocumentElement.ChildNodes;
  8. foreach (XmlNode node in nl)
  9. {
  10. //Debug.WriteLine(node.Name);
  11. if (node.Name != "JianLi" && node.Name != "JiaTingChengYuan")
  12. {
  13. FieldInfo fieldInfo = type.GetField(node.Name);
  14. fieldInfo.SetValue(ganBu, node.InnerText);
  15. }
  16. if (node.Name == "JianLi")
  17. {
  18. List<JianLi> jianLiList = new List<JianLi>();
  19. string jianli = node.InnerText;
  20. int rowNums = 0;
  21. string[] JianLiArrayTmp = jianli.Split('\n');
  22. List<String> JianLiArray = new List<string>();
  23. foreach (string s in JianLiArrayTmp)
  24. {
  25. if (s.Replace("\n", "").Replace("\r","").Trim() != "")
  26. {
  27. JianLiArray.Add(s.Replace("\r",""));
  28. }
  29. }
  30. foreach (string line in JianLiArray)
  31. {
  32. if (line.Trim() != "")
  33. {
  34. if (!Tools.isStartWithNumber(line.Trim()))
  35. {
  36. jianLiList[rowNums - 1].JingLi = jianLiList[rowNums - 1].JingLi + " " + line.Trim();
  37. }
  38. else
  39. {
  40. JianLi jl = new JianLi();
  41. String[] partArray = Regex.Split(line, " ");
  42. int tmpNum = 0;
  43. String jingli = "";
  44. foreach (string s in partArray)
  45. {
  46. if (tmpNum == 0)
  47. {
  48. //第一列分割的用来做时间拆分
  49. string[] a = Regex.Split(s, "--|——");
  50. if (a.Length == 1)
  51. {
  52. a = Regex.Split(s, "-|—");
  53. }
  54. jl.KaiShiNianYue = a[0].Trim().Replace(" ","");
  55. if (a.Length == 1)
  56. {
  57. jl.JieSuNianYue = "";
  58. }
  59. else
  60. {
  61. jl.JieSuNianYue += a[1].Trim().Replace(" ", "");
  62. }
  63. tmpNum++;
  64. }
  65. else
  66. {
  67. jingli += s.Trim();
  68. }
  69. }
  70. jl.JingLi = jingli;
  71. jianLiList.Add(jl);
  72. rowNums++;
  73. }
  74. }
  75. }
  76. ganBu.JianLi = jianLiList;
  77. }
  78. if (node.Name == "JiaTingChengYuan")
  79. {
  80. XmlNodeList node2list = node.ChildNodes;
  81. List<JiaTingChengYuan> jtcyList = new List<JiaTingChengYuan>();
  82. foreach (XmlNode node2 in node2list)
  83. {
  84. JiaTingChengYuan jtcy = new JiaTingChengYuan();
  85. XmlNodeList node3List = node2.ChildNodes;
  86. Type t2 = jtcy.GetType();
  87. foreach (XmlNode node3 in node3List)
  88. {
  89. FieldInfo fi = t2.GetField(node3.Name);
  90. fi.SetValue(jtcy, node3.InnerText.Trim());
  91. }
  92. jtcy.ChuShengRiQi = jtcy.ChuShengRiQi.Trim().Replace("\n", "").Replace("-", "");
  93. if (jtcy.ChuShengRiQi.Length == 6 || jtcy.ChuShengRiQi.Length == 8)
  94. {
  95. jtcy.NianLing = Tools.JiSuanNianLing(jtcy.ChuShengRiQi, Tools.NullToEmpty(ganBu.JiSuanNianLingShiJian), Tools.NullToEmpty(ganBu.TianBiaoShiJian));
  96. }
  97. jtcyList.Add(jtcy);
  98. }
  99. ganBu.JiaTingChengYuan = jtcyList;
  100. }
  101. }
  102. //20240718 增加身份证提取出生日期
  103. if (ganBu.ChuShengNianYue.Length == 6 || ganBu.ChuShengNianYue.Length == 8)
  104. {
  105. ganBu.NianLing = Tools.JiSuanNianLing(ganBu.ChuShengNianYue, Tools.NullToEmpty(ganBu.JiSuanNianLingShiJian), Tools.NullToEmpty(ganBu.TianBiaoShiJian));
  106. }
  107. else
  108. {
  109. if (!string.IsNullOrEmpty(ganBu.ShenFenZheng))
  110. {
  111. ganBu.ChuShengNianYue = Tools.GetDate(ganBu.ShenFenZheng);
  112. ganBu.NianLing = Tools.JiSuanNianLing(ganBu.ChuShengNianYue, Tools.NullToEmpty(ganBu.JiSuanNianLingShiJian), Tools.NullToEmpty(ganBu.TianBiaoShiJian));
  113. }
  114. }
  115. logger.Info(filename + "转换为类成功!");
  116. return ganBu;
  117. }catch(Exception ex)
  118. {
  119. logger.Error(ex.ToString());
  120. logger.Error(filename + "转换为类失败!");
  121. return ganBu;
  122. }
  123. }
3.2 转换过程中一些要点:
  1. 3.2.1 对于如何处理简历我的实现思路如下: 因为一条简历有可能会分行的,首先把简历的内容按行存到数组中,如果这行的内容不是数字开头(因为一条简历都是以年份开始的)那么这行就不是一条新的简历,而是一条简历分行了。如果再严格点可以取前四位是否为数字。
  2. 3.2.2 对于干部年龄的计算,如果有填写计算年龄时间那么就用该字段取,如果没有取填表时间,如果都没有取当前时间。如果没有填写出生日期,那么看是否有填写身份证号码。

二、 转换为word过程:

  1. 转换为word的过程采用的是按照模板来进行内容填充,本来想采用占位符替换的方式,发现有些问题,后来决定还是老老实实通过代码来实现。 审批表核心部分内容实际是一个大大表格,那么就可以按照excel单元格填充的思路来做处理了。

1. 完整代码

  1. try
  2. {
  3. GanBu ganBu = LrmxToClass(filename);
  4. string[] tmpArr = filename.Split('\\');
  5. string newFileName = tmpArr[tmpArr.Length - 1];
  6. string filePath = Path.GetDirectoryName(filename);
  7. String targetFilePath = ".\\docx\\" + filePath.Substring(3, filePath.Length - 3) + "\\" + newFileName.Substring(0, newFileName.Length -5) + "-任免审批表.docx";
  8. if (File.Exists(targetFilePath))
  9. {
  10. File.Delete(targetFilePath);
  11. }
  12. XWPFDocument docx;
  13. using (FileStream stream = File.OpenRead(".\\spbmb.docx"))
  14. {
  15. docx = new XWPFDocument(stream);
  16. }
  17. foreach (XWPFParagraph ph in docx.Paragraphs)
  18. {
  19. foreach (XWPFRun r in ph.Runs)
  20. {
  21. if (r.Text == "填表人:")
  22. {
  23. r.SetText("填表人:" + ganBu.TianBiaoRen);
  24. }
  25. }
  26. }
  27. if (!string.IsNullOrEmpty(ganBu.ZhaoPian.Replace("\r", "").Replace("\n", "")))
  28. {
  29. XWPFTableCell imageCell = docx.Tables[1].Rows[0].GetTableCells()[6];
  30. XWPFParagraph pg = imageCell.Paragraphs[0];
  31. XWPFRun run = pg.CreateRun();
  32. byte[] b = Convert.FromBase64String(ganBu.ZhaoPian);
  33. InputStream sbs = new ByteArrayInputStream(b);
  34. run.AddPicture(new ByteArrayInputStream(b), (int)NPOI.SS.UserModel.PictureType.JPEG, "", 363 * 3600, 490 * 3600);
  35. }
  36. Boolean ifFirst = true;
  37. int num = 0;
  38. foreach (XWPFTable table in docx.Tables)
  39. {
  40. for (int i = 0; i < table.Rows.Count; i++)
  41. {
  42. for (int j = 0; j < table.Rows[i].GetTableCells().Count; j++)
  43. {
  44. switch (table.Rows[i].GetTableCells()[j].GetText().Trim().Replace(" ", "").Replace("\r\n",""))
  45. {
  46. case "姓名":
  47. if (num == 1)
  48. {
  49. table.Rows[i].GetTableCells()[j + 1].SetText(ganBu.XingMing);
  50. }
  51. break;
  52. case "性别":
  53. table.Rows[i].GetTableCells()[j + 1].SetText(ganBu.XingBie);
  54. break;
  55. case "出生年月(岁)":
  56. table.Rows[i].GetTableCells()[j + 1].SetText(ganBu.ChuShengNianYue.Substring(0, 4) + "." + ganBu.ChuShengNianYue.Substring(4, 2) + "(" + ganBu.NianLing + "岁)");
  57. break;
  58. case "民族":
  59. table.Rows[i].GetTableCells()[j + 1].SetText(ganBu.MinZu);
  60. break;
  61. case "籍贯":
  62. table.Rows[i].GetTableCells()[j + 1].SetText(ganBu.JiGuan);
  63. break;
  64. case "出生地":
  65. table.Rows[i].GetTableCells()[j + 1].SetText(ganBu.ChuShengDi);
  66. break;
  67. case "入党时间":
  68. table.Rows[i].GetTableCells()[j + 1].SetText(ganBu.RuDangShiJian);
  69. break;
  70. case "参加工作时间":
  71. table.Rows[i].GetTableCells()[j + 1].SetText(ganBu.CanJiaGongZuoShiJian);
  72. break;
  73. case "健康状况":
  74. table.Rows[i].GetTableCells()[j + 1].SetText(ganBu.JianKangZhuangKuang);
  75. break;
  76. case "专业技术职务":
  77. table.Rows[i].GetTableCells()[j + 1].SetText(ganBu.ZhuanYeJiShuZhiWu);
  78. break;
  79. case "熟悉专业有何专长":
  80. table.Rows[i].GetTableCells()[j + 1].SetText(ganBu.ShuXiZhuanYeYouHeZhuanChang);
  81. break;
  82. case "全日制教育":
  83. XWPFParagraph pg = table.Rows[i].GetTableCells()[j + 1].Paragraphs[0];
  84. XWPFRun run = pg.CreateRun();
  85. run.SetText(ganBu.QuanRiZhiJiaoYu_XueLi);
  86. run.AddBreak();
  87. run.SetText(ganBu.QuanRiZhiJiaoYu_XueWei);
  88. break;
  89. case "毕业院校系及专业":
  90. if (ifFirst)
  91. {
  92. XWPFParagraph pg2 = table.Rows[i].GetTableCells()[j + 1].Paragraphs[0];
  93. XWPFRun run2 = pg2.CreateRun();
  94. run2.SetText(ganBu.QuanRiZhiJiaoYu_XueLi_BiYeYuanXiaoXi);
  95. run2.AddBreak();
  96. run2.SetText(ganBu.QuanRiZhiJiaoYu_XueWei_BiYeYuanXiaoXi);
  97. ifFirst = false;
  98. }
  99. else
  100. {
  101. XWPFParagraph pg3 = table.Rows[i].GetTableCells()[j + 1].Paragraphs[0];
  102. XWPFRun run3 = pg3.CreateRun();
  103. run3.SetText(ganBu.ZaiZhiJiaoYu_XueLi_BiYeYuanXiaoXi);
  104. run3.AddBreak();
  105. run3.SetText(ganBu.ZaiZhiJiaoYu_XueWei_BiYeYuanXiaoXi);
  106. ifFirst = true;
  107. }
  108. break;
  109. case "在职教育":
  110. XWPFParagraph pg4 = table.Rows[i].GetTableCells()[j + 1].Paragraphs[0];
  111. XWPFRun run4 = pg4.CreateRun();
  112. run4.SetText(ganBu.ZaiZhiJiaoYu_XueLi);
  113. run4.AddBreak();
  114. run4.SetText(ganBu.ZaiZhiJiaoYu_XueWei);
  115. break;
  116. case "现任职务":
  117. table.Rows[i].GetTableCells()[j + 1].SetText(ganBu.XianRenZhiWu);
  118. break;
  119. case "拟任职务":
  120. table.Rows[i].GetTableCells()[j + 1].SetText(ganBu.NiRenZhiWu);
  121. break;
  122. case "拟免职务":
  123. table.Rows[i].GetTableCells()[j + 1].SetText(ganBu.NiMianZhiWu);
  124. break;
  125. case "简历":
  126. int lastLine = 1;
  127. XWPFParagraph pg5 = table.Rows[i].GetTableCells()[j + 1].Paragraphs[0];
  128. XWPFRun run5 = pg5.CreateRun();
  129. foreach (JianLi jl in ganBu.JianLi)
  130. {
  131. if (lastLine != ganBu.JianLi.Count)
  132. {
  133. if (ifFirst)
  134. {
  135. run5.SetText(jl.KaiShiNianYue + "--" + jl.JieSuNianYue + " " + jl.JingLi);
  136. ifFirst = false;
  137. }
  138. else
  139. {
  140. table.Rows[i].GetTableCells()[j + 1].AddParagraph().CreateRun().SetText(jl.KaiShiNianYue + "--" + jl.JieSuNianYue + " " + jl.JingLi);
  141. }
  142. lastLine++;
  143. }
  144. else
  145. {
  146. table.Rows[i].GetTableCells()[j + 1].AddParagraph().CreateRun().SetText(jl.KaiShiNianYue + "--" + " " + jl.JieSuNianYue + " " + jl.JingLi);
  147. }
  148. }
  149. break;
  150. case "奖惩情况":
  151. table.Rows[i].GetTableCells()[j + 1].SetText(ganBu.JiangChengQingKuang);
  152. break;
  153. case "年核度结考果":
  154. table.Rows[i].GetTableCells()[j + 1].SetText(ganBu.NianDuKaoHeJieGuo);
  155. break;
  156. case "任免理由":
  157. table.Rows[i].GetTableCells()[j + 1].SetText(ganBu.RenMianLiYou);
  158. break;
  159. case "家庭主要成员及重要社会关系":
  160. List<JiaTingChengYuan> jtcyList = ganBu.JiaTingChengYuan;
  161. for (int m = 0; m < jtcyList.Count(); m++)
  162. {
  163. XWPFTableRow tr = table.Rows[i + m + 1];
  164. tr.GetTableCells()[1].SetText(jtcyList[m].ChengWei);
  165. tr.GetTableCells()[2].SetText(jtcyList[m].XingMing);
  166. tr.GetTableCells()[3].SetText(jtcyList[m].NianLing.ToString());
  167. tr.GetTableCells()[4].SetText(jtcyList[m].ZhengZhiMianMao);
  168. tr.GetTableCells()[5].SetText(jtcyList[m].GongZuoDanWeiJiZhiWu);
  169. }
  170. break;
  171. case "呈报单位":
  172. table.Rows[i].GetTableCells()[j + 1].SetText(ganBu.ChengBaoDanWei);
  173. break;
  174. case "行任政免机意关见":
  175. table.Rows[i].GetTableCells()[j + 1].SetText(" 同意 " );
  176. break;
  177. }
  178. }
  179. }
  180. num++;
  181. }
  182. System.IO.FileStream output = new System.IO.FileStream(targetFilePath, System.IO.FileMode.Create, System.IO.FileAccess.ReadWrite, System.IO.FileShare.ReadWrite);
  183. //写入文件
  184. docx.Write(output);
  185. output.Close();
  186. output.Dispose();
  187. logger.Info(targetFilePath + "文件生成成功!");
  188. }
  189. catch (Exception ex)
  190. {
  191. logger.Error(filename + "转换不成功");
  192. logger.Error(ex.ToString());
  193. }

2 核心思路和注意点

2.1 需要填充内容位置判断:
  1. 通过遍历表格中的文字内容来判断,填充的位置就是文字所在单元格位置横向+1 了。
2.2 需要注意点:
  1. 年度考核结果实际在解析模板中对应字符串为 "年核度结考果", 同样的还有行政任免机关意见对应为“行任政免机意关见” ,这个是个坑。

总结:

  1. 有些点说通了,会发现实现起来就没什么难度了。批量转换以及子目录这些我就不阐述了。 东西写得也比较粗,如果有需要的朋友可以留言给我,一起完善这个软件了。


本文转载自: https://blog.csdn.net/waxyy002/article/details/140681464
版权归原作者 IT大灰狼 所有, 如有侵权,请联系我们删除。

“干部任免管理系统(五)开源了一个c#开发的任免审批表转word的程序”的评论:

还没有评论