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

前言:

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

程序开源地址:

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

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

程序实现的主要代码:

一、Lrmx文件解析:

本质上中组部任免审批表的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类
复制代码
    public  class GanBu
    {
      public   String XingMing;   //姓名  1,0,0   1,0,1
        public String XingBie;  //性别  1,0,2   1,0,3
        public String ChuShengNianYue;  //出生年月  YYYYMM格式    1,0,4  1,0,5
        public String MinZu;  //民族     1,1,0   1,1,1
        public String JiGuan;   //籍贯  1,1,2     1,1,3
        public String ChuShengDi;// 出生地  1,1,4  1,1,5
        public String RuDangShiJian;// 入党时间   1,2,0
        public String CanJiaGongZuoShiJian;//参加工作时间  1,2,2
        public String JianKangZhuangKuang;//健康状况  1,2,4
        public String ZhuanYeJiShuZhiWu;//专业技术职务  1,3,0
        public String ShuXiZhuanYeYouHeZhuanChang;//熟悉专业有何专长   1,3,2
        public String QuanRiZhiJiaoYu_XueLi;//全日制教育学历       1,4,2
        public String QuanRiZhiJiaoYu_XueWei;//全日制教育学位 1,4,2
        public String QuanRiZhiJiaoYu_XueLi_BiYeYuanXiaoXi;//全日制毕业学校   1,4,4
        public String QuanRiZhiJiaoYu_XueWei_BiYeYuanXiaoXi;//全日制毕业院校专业     1,5,4
        public String ZaiZhiJiaoYu_XueLi;//在职教育学历   1,6,2
        public String ZaiZhiJiaoYu_XueWei;//在职教育学位  1,6,2
        public String ZaiZhiJiaoYu_XueLi_BiYeYuanXiaoXi;//在职教育毕业院校    1,6,4
        public String ZaiZhiJiaoYu_XueWei_BiYeYuanXiaoXi;//在职教育毕业院校专业  1,7,4
        public String XianRenZhiWu;//现任职务     1,8,0
        public String NiRenZhiWu;//拟任职务    1,9,0
        public String NiMianZhiWu;//拟免职务   1,10,0
        public List<JianLi> JianLi;  //简历   1,11,0
        public String JiangChengQingKuang;//奖惩情况    2,0,0
        public String NianDuKaoHeJieGuo;//年度考核结果    2,1,0
        public String RenMianLiYou;//任免理由   2,2,0
        public   List<JiaTingChengYuan> JiaTingChengYuan;//家庭成员   2,4,1  称谓    2   姓名      3  年龄  4  政治面貌  5  工作单位及职务
        public String ChengBaoDanWei;//承报单位
        public String JiSuanNianLingShiJian;//计算年龄时间
        public String TianBiaoShiJian;//填报时间
        public String TianBiaoRen;//填报人
        public String ShenFenZheng;//身份证号码
        public String ZhaoPian;//  照片
        public String Version;//版本
        public int NianLing; //年龄

    }
2.2 JianLi 类
cs 复制代码
   public  class JianLi
   {
       public String KaiShiNianYue;
       public String JieSuNianYue;
       public String JingLi;  //经历
   }
2.3 JiaTingChengYuan 类
cs 复制代码
   public  class JiaTingChengYuan
    {
        public String ChengWei;//称谓
        public String XingMing;//姓名
        public String ChuShengRiQi;//出生日期  YYYYMM
        public String ZhengZhiMianMao;//政治面貌
        public String GongZuoDanWeiJiZhiWu;//工作单位及职务
        public int NianLing; //年龄
    }

3 解析lrmx文件过程

代码就是读取xml文件,将对应的内容解析赋值给GanBu类

3.1 完整转换为类的代码
cs 复制代码
 private GanBu LrmxToClass(string filename) {
     GanBu ganBu = new GanBu();
     Type type = ganBu.GetType();
     try {

         XmlDocument xmlDoc = new XmlDocument();
         xmlDoc.Load(filename);
         XmlNodeList nl = xmlDoc.DocumentElement.ChildNodes;
         foreach (XmlNode node in nl)
         {
             //Debug.WriteLine(node.Name);
             if (node.Name != "JianLi" && node.Name != "JiaTingChengYuan")
             {
                 FieldInfo fieldInfo = type.GetField(node.Name);
                 fieldInfo.SetValue(ganBu, node.InnerText);

             }

             if (node.Name == "JianLi")
             {
                 List<JianLi> jianLiList = new List<JianLi>();
                 string jianli = node.InnerText;
                 int rowNums = 0;
                 string[] JianLiArrayTmp = jianli.Split('\n');
                 List<String> JianLiArray = new List<string>();
                 foreach (string s in JianLiArrayTmp)
                 {
                     if (s.Replace("\n", "").Replace("\r","").Trim() != "")
                     {
                         JianLiArray.Add(s.Replace("\r",""));
                     }

                 }
                 foreach (string line in JianLiArray)
                 {
                     if (line.Trim() != "")
                     {
                         if (!Tools.isStartWithNumber(line.Trim()))
                         {
                             jianLiList[rowNums - 1].JingLi = jianLiList[rowNums - 1].JingLi + " " + line.Trim();
                            
                         }
                         else
                         {
                             JianLi jl = new JianLi();
                             String[] partArray = Regex.Split(line, "  ");
                             int tmpNum = 0;
                             String jingli = "";
                             foreach (string s in partArray)
                             {
                                 if (tmpNum == 0)
                                 {
                                     //第一列分割的用来做时间拆分
                                     string[] a = Regex.Split(s, "--|------");
                                     if (a.Length == 1)
                                     {
                                         a = Regex.Split(s, "-|---");
                                     }
                                     jl.KaiShiNianYue = a[0].Trim().Replace(" ","");
                                     if (a.Length == 1)
                                     {
                                         jl.JieSuNianYue = "";
                                     }
                                     else
                                     {
                                         jl.JieSuNianYue += a[1].Trim().Replace(" ", "");

                                     }
                                     tmpNum++;
                                 }
                                 else
                                 {
                                     jingli += s.Trim();
                                 }

                             }
                             jl.JingLi = jingli;

                             jianLiList.Add(jl);
                             rowNums++;

                         }
                     }
                 }


                 ganBu.JianLi = jianLiList;
             }

             if (node.Name == "JiaTingChengYuan")
             {
                 XmlNodeList node2list = node.ChildNodes;
                 List<JiaTingChengYuan> jtcyList = new List<JiaTingChengYuan>();
                 foreach (XmlNode node2 in node2list)
                 {
                     JiaTingChengYuan jtcy = new JiaTingChengYuan();
                     XmlNodeList node3List = node2.ChildNodes;
                     Type t2 = jtcy.GetType();
                     foreach (XmlNode node3 in node3List)
                     {
                         FieldInfo fi = t2.GetField(node3.Name);
                         fi.SetValue(jtcy, node3.InnerText.Trim());
                     }
                     jtcy.ChuShengRiQi = jtcy.ChuShengRiQi.Trim().Replace("\n", "").Replace("-", "");
                     if (jtcy.ChuShengRiQi.Length == 6 || jtcy.ChuShengRiQi.Length == 8)
                     {

                         jtcy.NianLing = Tools.JiSuanNianLing(jtcy.ChuShengRiQi, Tools.NullToEmpty(ganBu.JiSuanNianLingShiJian), Tools.NullToEmpty(ganBu.TianBiaoShiJian));
                     }

                     jtcyList.Add(jtcy);


                 }
                 ganBu.JiaTingChengYuan = jtcyList;

             }

         }

         //20240718 增加身份证提取出生日期
         if (ganBu.ChuShengNianYue.Length == 6 || ganBu.ChuShengNianYue.Length == 8)
         {
             ganBu.NianLing = Tools.JiSuanNianLing(ganBu.ChuShengNianYue, Tools.NullToEmpty(ganBu.JiSuanNianLingShiJian), Tools.NullToEmpty(ganBu.TianBiaoShiJian));
         }
         else
         {
             if (!string.IsNullOrEmpty(ganBu.ShenFenZheng))
             {
                 ganBu.ChuShengNianYue = Tools.GetDate(ganBu.ShenFenZheng);
                 ganBu.NianLing = Tools.JiSuanNianLing(ganBu.ChuShengNianYue, Tools.NullToEmpty(ganBu.JiSuanNianLingShiJian), Tools.NullToEmpty(ganBu.TianBiaoShiJian));
             }

         }


         logger.Info(filename + "转换为类成功!");

         return ganBu;
     
     }catch(Exception ex)
     {
         logger.Error(ex.ToString());
         logger.Error(filename + "转换为类失败!");
         return ganBu;
     }

 }
3.2 转换过程中一些要点:

3.2.1 对于如何处理简历我的实现思路如下: 因为一条简历有可能会分行的,首先把简历的内容按行存到数组中,如果这行的内容不是数字开头(因为一条简历都是以年份开始的)那么这行就不是一条新的简历,而是一条简历分行了。如果再严格点可以取前四位是否为数字。

3.2.2 对于干部年龄的计算,如果有填写计算年龄时间那么就用该字段取,如果没有取填表时间,如果都没有取当前时间。如果没有填写出生日期,那么看是否有填写身份证号码。

二、 转换为word过程:

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

1. 完整代码

cs 复制代码
  try
  {
      GanBu ganBu = LrmxToClass(filename);                 

      string[]  tmpArr = filename.Split('\\');
      string newFileName = tmpArr[tmpArr.Length - 1];
      string filePath = Path.GetDirectoryName(filename);
      String targetFilePath = ".\\docx\\"  + filePath.Substring(3, filePath.Length - 3) + "\\" +  newFileName.Substring(0,  newFileName.Length -5) + "-任免审批表.docx"; 
      if (File.Exists(targetFilePath))
      {
          File.Delete(targetFilePath);
      }

      XWPFDocument docx;
      using (FileStream stream = File.OpenRead(".\\spbmb.docx"))
      {

          docx = new XWPFDocument(stream);
      }
      foreach (XWPFParagraph ph in docx.Paragraphs)
      {
          foreach (XWPFRun r in ph.Runs)
          {
              if (r.Text == "填表人:")
              {
                  r.SetText("填表人:" + ganBu.TianBiaoRen);

              }
          }
      }


      if (!string.IsNullOrEmpty(ganBu.ZhaoPian.Replace("\r", "").Replace("\n", "")))
      {
          XWPFTableCell imageCell = docx.Tables[1].Rows[0].GetTableCells()[6];
          XWPFParagraph pg = imageCell.Paragraphs[0];
          XWPFRun run = pg.CreateRun();
          byte[] b = Convert.FromBase64String(ganBu.ZhaoPian);
          InputStream sbs = new ByteArrayInputStream(b);
          run.AddPicture(new ByteArrayInputStream(b), (int)NPOI.SS.UserModel.PictureType.JPEG, "", 363 * 3600, 490 * 3600);
      }


      Boolean ifFirst = true;
      int num = 0;
      foreach (XWPFTable table in docx.Tables)
      {
          for (int i = 0; i < table.Rows.Count; i++)
          {
              for (int j = 0; j < table.Rows[i].GetTableCells().Count; j++)
              {
                  switch (table.Rows[i].GetTableCells()[j].GetText().Trim().Replace(" ", "").Replace("\r\n",""))
                  {
                      case "姓名":
                          if (num == 1)
                          {
                              table.Rows[i].GetTableCells()[j + 1].SetText(ganBu.XingMing);
                          }
                          break;
                      case "性别":
                          table.Rows[i].GetTableCells()[j + 1].SetText(ganBu.XingBie);
                          break;
                      case "出生年月(岁)":
                          table.Rows[i].GetTableCells()[j + 1].SetText(ganBu.ChuShengNianYue.Substring(0, 4) + "." + ganBu.ChuShengNianYue.Substring(4, 2) + "(" + ganBu.NianLing + "岁)");
                          break;
                      case "民族":
                          table.Rows[i].GetTableCells()[j + 1].SetText(ganBu.MinZu);
                          break;
                      case "籍贯":
                          table.Rows[i].GetTableCells()[j + 1].SetText(ganBu.JiGuan);
                          break;
                      case "出生地":
                          table.Rows[i].GetTableCells()[j + 1].SetText(ganBu.ChuShengDi);
                          break;
                      case "入党时间":
                          table.Rows[i].GetTableCells()[j + 1].SetText(ganBu.RuDangShiJian);
                          break;
                      case "参加工作时间":
                          table.Rows[i].GetTableCells()[j + 1].SetText(ganBu.CanJiaGongZuoShiJian);
                          break;
                      case "健康状况":
                          table.Rows[i].GetTableCells()[j + 1].SetText(ganBu.JianKangZhuangKuang);
                          break;
                      case "专业技术职务":
                          table.Rows[i].GetTableCells()[j + 1].SetText(ganBu.ZhuanYeJiShuZhiWu);
                          break;
                      case "熟悉专业有何专长":
                          table.Rows[i].GetTableCells()[j + 1].SetText(ganBu.ShuXiZhuanYeYouHeZhuanChang);
                          break;
                      case "全日制教育":
                          XWPFParagraph pg = table.Rows[i].GetTableCells()[j + 1].Paragraphs[0];
                          XWPFRun run = pg.CreateRun();
                          run.SetText(ganBu.QuanRiZhiJiaoYu_XueLi);
                          run.AddBreak();
                          run.SetText(ganBu.QuanRiZhiJiaoYu_XueWei);
                          break;
                      case "毕业院校系及专业":
                          if (ifFirst)
                          {
                              XWPFParagraph pg2 = table.Rows[i].GetTableCells()[j + 1].Paragraphs[0];
                              XWPFRun run2 = pg2.CreateRun();
                              run2.SetText(ganBu.QuanRiZhiJiaoYu_XueLi_BiYeYuanXiaoXi);
                              run2.AddBreak();
                              run2.SetText(ganBu.QuanRiZhiJiaoYu_XueWei_BiYeYuanXiaoXi);
                              ifFirst = false;
                          }
                          else
                          {
                              XWPFParagraph pg3 = table.Rows[i].GetTableCells()[j + 1].Paragraphs[0];
                              XWPFRun run3 = pg3.CreateRun();
                              run3.SetText(ganBu.ZaiZhiJiaoYu_XueLi_BiYeYuanXiaoXi);
                              run3.AddBreak();
                              run3.SetText(ganBu.ZaiZhiJiaoYu_XueWei_BiYeYuanXiaoXi);
                              ifFirst = true;
                          }
                          break;
                      case "在职教育":
                          XWPFParagraph pg4 = table.Rows[i].GetTableCells()[j + 1].Paragraphs[0];
                          XWPFRun run4 = pg4.CreateRun();
                          run4.SetText(ganBu.ZaiZhiJiaoYu_XueLi);
                          run4.AddBreak();
                          run4.SetText(ganBu.ZaiZhiJiaoYu_XueWei);
                          break;
                      case "现任职务":
                          table.Rows[i].GetTableCells()[j + 1].SetText(ganBu.XianRenZhiWu);
                          break;
                      case "拟任职务":
                          table.Rows[i].GetTableCells()[j + 1].SetText(ganBu.NiRenZhiWu);
                          break;
                      case "拟免职务":
                          table.Rows[i].GetTableCells()[j + 1].SetText(ganBu.NiMianZhiWu);
                          break;
                      case "简历":
                          int lastLine = 1;
                          XWPFParagraph pg5 = table.Rows[i].GetTableCells()[j + 1].Paragraphs[0];
                          XWPFRun run5 = pg5.CreateRun();
                          foreach (JianLi jl in ganBu.JianLi)
                          {
                              if (lastLine != ganBu.JianLi.Count)
                              {
                                  if (ifFirst)
                                  {
                                      run5.SetText(jl.KaiShiNianYue + "--" + jl.JieSuNianYue + "  " + jl.JingLi);
                                      ifFirst = false;
                                  }
                                  else
                                  {
                                      table.Rows[i].GetTableCells()[j + 1].AddParagraph().CreateRun().SetText(jl.KaiShiNianYue + "--" + jl.JieSuNianYue + "  " + jl.JingLi);
                                  }
                                  lastLine++;
                              }
                              else
                              {
                                  table.Rows[i].GetTableCells()[j + 1].AddParagraph().CreateRun().SetText(jl.KaiShiNianYue + "--" + "    " + jl.JieSuNianYue + "    " + jl.JingLi);
                              }
                          }
                          break;
                      case "奖惩情况":
                          table.Rows[i].GetTableCells()[j + 1].SetText(ganBu.JiangChengQingKuang);
                          break;
                      case "年核度结考果":
                          table.Rows[i].GetTableCells()[j + 1].SetText(ganBu.NianDuKaoHeJieGuo);
                          break;
                      case "任免理由":
                          table.Rows[i].GetTableCells()[j + 1].SetText(ganBu.RenMianLiYou);
                          break;
                      case "家庭主要成员及重要社会关系":
                          List<JiaTingChengYuan> jtcyList = ganBu.JiaTingChengYuan;
                          for (int m = 0; m < jtcyList.Count(); m++)
                          {
                              XWPFTableRow tr = table.Rows[i + m + 1];
                              tr.GetTableCells()[1].SetText(jtcyList[m].ChengWei);
                              tr.GetTableCells()[2].SetText(jtcyList[m].XingMing);
                              tr.GetTableCells()[3].SetText(jtcyList[m].NianLing.ToString());
                              tr.GetTableCells()[4].SetText(jtcyList[m].ZhengZhiMianMao);
                              tr.GetTableCells()[5].SetText(jtcyList[m].GongZuoDanWeiJiZhiWu);

                          }
                          break;
                      case "呈报单位":
                          table.Rows[i].GetTableCells()[j + 1].SetText(ganBu.ChengBaoDanWei);
                          break;
                      case "行任政免机意关见":
                          table.Rows[i].GetTableCells()[j + 1].SetText(" 同意 " );
                          break;
                  }
              }
          }
          num++;
      }





      System.IO.FileStream output = new System.IO.FileStream(targetFilePath, System.IO.FileMode.Create, System.IO.FileAccess.ReadWrite, System.IO.FileShare.ReadWrite);
      //写入文件
      docx.Write(output);

      output.Close();
      output.Dispose();

      logger.Info(targetFilePath + "文件生成成功!");
  }
  catch (Exception ex)
  {
      logger.Error(filename + "转换不成功");
      logger.Error(ex.ToString());

  }

2 核心思路和注意点

2.1 需要填充内容位置判断:

通过遍历表格中的文字内容来判断,填充的位置就是文字所在单元格位置横向+1 了。

2.2 需要注意点:

年度考核结果实际在解析模板中对应字符串为 "年核度结考果", 同样的还有行政任免机关意见对应为"行任政免机意关见" ,这个是个坑。

总结:

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

相关推荐
T0uken6 小时前
【前端】:单 HTML 去除 Word 批注
前端·html·word
诸葛大钢铁18 小时前
WORD压缩两个免费方法
word
KingCruel18 小时前
NPOI 操作 Word 文档
word
小可的科研日常1 天前
保持Word中插入图片的清晰度
word
小码ssim1 天前
通过POI实现对word基于书签的内容替换、删除、插入
java·word
一把年纪学编程2 天前
【牛马技巧】word统计每一段的字数接近“字数统计”
前端·数据库·word
爱吃零食的白糖2 天前
word换行符和段落标记
word
Etincelle3 天前
【LaTeX】Word插入LaTeX行间公式如何编号和对齐
word·wps·latex
老马啸西风3 天前
sensitive-word-admin v2.0.0 全新 ui 版本发布!vue+前后端分离
vue.js·ui·ai·nlp·github·word
wqqqianqian4 天前
国产linux系统(银河麒麟,统信uos)使用 PageOffice 在线打开Word文件,并用前端对话框实现填空填表
linux·前端·word·pageoffice