干部任免管理系统(五)开源了一个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 需要注意点:

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

总结:

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

相关推荐
徐同保13 小时前
vue 在线预览word和excel
vue.js·word·excel
eybk3 天前
拖放WORD文件朗读全文
开发语言·c#·word
codelife3213 天前
记录word转xml文件踩坑
xml·word
老田低代码3 天前
根据NVeloDocx Word模板引擎生成Word(五)
开发语言·c#·word
xuanyu223 天前
Word使用手册
word
忧郁的蛋~3 天前
asp.net core调用wps实现word转pdf的方法
pdf·word·wps
zhangdabai13 天前
在Word中,用VBA比较两段文本的相似度
word·wps
weixin_457703924 天前
如何设置word页码从指定页开始
word
老田低代码4 天前
根据NVeloDocx Word模板引擎生成Word(六-结束)
word
uolian4 天前
WORD批量转换器MultiDoc Converter
word