zoukankan      html  css  js  c++  java
  • NPOI使用word模板

    /// <summary>
        /// 1、支持定义模板变量的开头与结尾字符
        /// 2、支持自定义模板变量查找正则表达式
        /// 3、模板中的变量组成"变量开头_变量名称",如:txt_name,变量名称与class中的字段或属性一致
        /// 4、支持定义模板中图片变量开头
        /// 5、支持定义模板中文本变量中的开头
        /// 6、表格不支持处理图片,文本变量命名格式与4相同
        /// 7、NPOI BUG提示:
        ///     使用模板时,定义变量请使用记事本编写后,复制到word中
        ///     直接在word中写时,使用  XWPFParagraph.Runs 获取变量可能导致被拆分,如 <name> 被拆成 <,name,>,正确的应该是  ,<name>,
        /// </summary>
        public class WordManage
        {
            // 模板开头
            public string modelStart = "<$";
            // 模板结束
            public string modelEnd = "$>";
            // 模板查找正则表达式
            public string regexStr = @"<\$\w+\$>";
            // 定义模板中,图片得开头
            public string modelPictureStart = "pic_";
            // 定义模板中,文字得开头
            public string modelTextStart = "txt_";
    
            /// <summary>
            /// 通过模板创建word文档
            /// </summary>
            public MemoryStream ModelCreateWord<T>(string filepath, T t) where T : AbstractGetValue
            {
                using (FileStream stream = File.OpenRead(filepath))
                {
                    XWPFDocument doc = new XWPFDocument(stream);
                    
                    // 遍历段落                  
                    foreach (var para in doc.Paragraphs)
                    {
                        ReplaceText(para, t);
                        ReplacePictures(para, t);
                    }
    
                    // 处理表格
                    ReplaceTables(doc,t); 
    
                    // 写入流
                    MemoryStream ms = new MemoryStream();
                    doc.Write(ms);
                    return ms;
                }
            }
    
            /// <summary>
            /// 保存word文档
            /// </summary>
            /// <param name="ms">MemoryStream流对象</param>
            /// <param name="savepath">保存地址</param>
            public void SaveWord(MemoryStream ms,string savepath)
            {
                try
                {
                    FileStream fs = new FileStream(savepath, FileMode.OpenOrCreate);
                    BinaryWriter w = new BinaryWriter(fs);
                    w.Write(ms.ToArray());
                    fs.Close();
                }
                catch(Exception ex)
                {
                    throw ex;
                }
            }
    
            #region 模板字符替换
    
            private void ReplaceText<T>(XWPFParagraph para, T t) where T : AbstractGetValue
            {
                if (para == null)
                {
                    throw new Exception("XWPFParagraph对象引用为null");
                }
    
                if (t == null)
                {
                    throw new Exception(t.GetType().Name + "对象引用为null");
                }
    
                try
                {
                    string text = para.ParagraphText;
    
                    List<string> matchTexts = GetModelName(text);
    
                    foreach (string str in matchTexts)
                    {
                        if (str.IndexOf(modelTextStart) > -1)
                        {
                            string name = str.Replace(modelTextStart, "");
                            string newText = Convert.ToString(t.GetValue(name));
    
                            para.ReplaceText(modelStart + str + modelEnd, newText);
                        }
                    }
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
    
            #endregion 
    
            #region 模板图片插入
    
            private void ReplacePictures<T>(XWPFParagraph para, T t) where T : AbstractGetValue
            {
                if (para == null)
                {
                    throw new Exception("XWPFParagraph对象引用为null");
                }
    
                if (t == null)
                {
                    return;
                }
    
                // 段落中得文本对象
                var runs = para.Runs;
    
                try
                {
                    for (int i = 0; i < runs.Count; i++)
                    {
                        var run = runs[i];
                        string text = run.ToString();
    
                        List<string> matchTexts = GetModelName(text);
    
                        List<string> paths = new List<string>();
    
                        foreach (string str in matchTexts)
                        {
                            // 只处理图片
                            if (str.IndexOf(modelPictureStart) == -1)
                            {
                                continue;
                            }
    
                            text = text.Replace(modelStart + str + modelEnd, "");
    
                            string name = str.Replace(modelPictureStart, "");
    
                            List<string> tempPaths = t.GetValue(name) as List<string>;
    
                            // 图片不是列表时,尝试解析为字符串
                            if(tempPaths == null)
                            {
                                string path = t.GetValue(name) as string;
    
                                if (string.IsNullOrEmpty(path))
                                {
                                    tempPaths = new List<string>()
                                    {
                                        path
                                    };
                                }
                            }
    
                            if (tempPaths != null && tempPaths.Count > 0)
                            {
                                paths.AddRange(tempPaths);
                            }
                        }
    
                        run.SetText(text, 0);
    
                        ReplacePictures(run, paths);
                    }
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
    
            private void ReplacePictures(XWPFRun run, List<string> paths)
            {
                if (run == null)
                {
                    throw new Exception("XWPFRun对象引用为null");
                }
    
                try
                {
                    foreach (string path in paths)
                    {
                        if (string.IsNullOrEmpty(path))
                        {
                            continue;
                        }
    
                        Bitmap b = new Bitmap(path);
                        FileStream gfs = new FileStream(path, FileMode.Open, FileAccess.Read);
    
                        int width = b.Width;
                        int height = b.Height;
                        double fold = 1;
    
                        if (width > 600)
                        {
                            fold = width / 600.0;
                        }
    
                        width = Convert.ToInt32(width / fold);
                        height = Convert.ToInt32(height / fold);
    
                        // 获取后缀
                        string extension = Path.GetExtension(path);
                        // 随机名称
                        string name = GuidTo16String() + extension;
    
                        // 添加图片到文档中
                        run.AddPicture(gfs, (int)PictureType.JPEG, name, Units.PixelToEMU(width), Units.PixelToEMU(height));
                        
                        b.Dispose();
                        gfs.Close();
                    }
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
            #endregion
    
            #region 表格
    
            public void ReplaceTables<T>(XWPFDocument doc,T t) where T:AbstractGetValue
            {
                try
                {
                    if (doc == null)
                    {
                        throw new Exception("XWPFDocument对象引用为null");
                    }
    
                    if (t.Tables == null || t.Tables.Count == 0)
                    {
                        return;
                    }
    
                    var tables = doc.Tables;
    
                    // 无模板
                    if (tables.Count == 0)
                    {
                        return;
                    }
    
                    for (int i = 0; i < t.Tables.Count; i++)
                    {
                        if (t.Tables[i] == null || t.Tables[i].Rows.Count == 0)
                        {
                            continue;
                        }
    
                        XWPFTable table = tables[i];
    
                        if (table != null)
                        {
                            ReplaceTable(table, t.Tables[i]);
                        }
                    }
                }
                catch(Exception ex)
                {
                    throw ex;
                }
            }
    
            private void ReplaceTable(XWPFTable table, DataTable dataTable)
            {
                try
                {
                    XWPFTableRow modelRows = table.Rows[1];
                    CT_Row ctrow = modelRows.GetCTRow();
    
                    table.RemoveRow(table.Rows.IndexOf(modelRows)); //先移除模板行
    
                    for (int i = 0; i < dataTable.Rows.Count; i++)
                    {
                        //复制cell结构
                        CT_Row targetRow = new CT_Row();
    
                        foreach (CT_Tc item in ctrow.Items)
                        {
                            CT_Tc addTc = targetRow.AddNewTc();
                            addTc.tcPr = item.tcPr;//cell样式,只包括列宽和cell对齐方式
    
                            IList<CT_P> list_p = item.GetPList();
    
                            foreach (var p in list_p)
                            {
                                CT_P addP = addTc.AddNewP();
                                addP.pPr = p.pPr;//段落样式
                                IList<CT_R> list_r = p.GetRList();
                                foreach (CT_R r in list_r)
                                {
                                    CT_R addR = addP.AddNewR();
                                    addR.rPr = r.rPr;//run样式 包括字体等
                                    List<CT_Text> list_text = r.GetTList();
                                    foreach (CT_Text text in list_text)
                                    {
                                        CT_Text addText = addR.AddNewT();
                                        addText.space = text.space;
                                        addText.Value = text.Value;
                                    }
                                }
                            }
                        }
    
                        XWPFTableRow mrow = new XWPFTableRow(targetRow, table);
                        table.AddRow(mrow);
    
                        // 填数据 第一行标题,数据填充从第二行开始
                        foreach (var cells in table.Rows[i + 1].GetTableCells())
                        {
                            foreach (var para in cells.Paragraphs)
                            {
                                List<string> texts = GetModelName(para.ParagraphText);
    
                                foreach (string str in texts)
                                {
                                    if (str.IndexOf(modelTextStart) > -1)
                                    {
                                        string name = str.Replace(modelTextStart, "");
                                        string newText = Convert.ToString(dataTable.Rows[i][name]);
                                        para.ReplaceText(modelStart + str + modelEnd, newText);
                                    }
                                }
                            }
                        }
                    }
                }
                catch(Exception ex)
                {
                    throw ex;
                }
            }
    
            #endregion 
    
            /// <summary>
            /// 获取段落中的模板参数
            /// </summary>
            private List<string> GetModelName(string text)
            {
                try
                {
                    List<string> matchTexts = new List<string>();
    
                    Regex reg = new Regex(regexStr);
                    Match match = reg.Match(text);
    
                    bool result = match.Success;
    
                    while (result)
                    {
                        string matchText = match.Groups[0].Value.Replace(modelStart, "").Replace(modelEnd, "");
                        matchTexts.Add(matchText);
    
                        match = match.NextMatch();
                        result = match.Success;
                    }
    
                    return matchTexts;
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
            
            /// <summary>
            /// 16位guid
            /// </summary>
            private string GuidTo16String()
            {
                long i = 1;
                foreach (byte b in Guid.NewGuid().ToByteArray())
                {
                    i *= ((int)b + 1);
                }
                return string.Format("{0:x}", i - DateTime.Now.Ticks);
            }
        }
    

      可供WordManage使用的类必须继承AbstractGetValue

    public class AbstractGetValue
        {
            private List<DataTable> _Tables = new List<DataTable>();
    
            public List<DataTable> Tables
            {
                get { return _Tables; }
                set { _Tables = value; }
            }
    
            /// <summary>
            /// 获取属性的值,可重写
            /// </summary>
            /// <param name="propertyName">属性名称</param>
            /// <returns></returns>
            public virtual object GetValue(string propertyName)
            {
                PropertyInfo property = this.GetType().GetProperty(propertyName);
    
                if (property == null)
                {
                    FieldInfo field = this.GetType().GetField(propertyName);
    
                    if (field != null)
                    {
                        return field.GetValue(this);
                    }
    
                    return string.Empty;
                }
                else
                {
                    return property.GetValue(this);
                }
            }
        }
    

      使用

     public void CreateWord()
            {
                // 模板地址
                string filepath = Server.MapPath("~/Content/FileModal/Word/demo.docx");
    
                // word生成
                WordManage word = new WordManage();
    
                #region 添加表格数据
                DataTable dt = new DataTable();
    
                dt.Columns.Add("column1");
                dt.Columns.Add("column2");
                dt.Columns.Add("column3");
                dt.Columns.Add("column4");
    
                DataRow newRow = dt.NewRow();
                newRow["column1"] = "zsw";
                newRow["column2"] = "13800000000";
                newRow["column3"] = "430723199005042222";
                newRow["column4"] = "读书";
    
                dt.Rows.Add(newRow);
    
                newRow = dt.NewRow();
                newRow["column1"] = "lisi";
                newRow["column2"] = "15555555555";
                newRow["column3"] = "446885222111256654";
                newRow["column4"] = "游泳";
    
                dt.Rows.Add(newRow);
    
                test t = new test()
                {
                    picture = new List<string> { @"E:\test project\WebApplication10\WebApplication10\Content\timg.jpg" },
                    text = "zsw",
                    Tables = new List<DataTable>() { dt }
                };
    
                #endregion
    
                // 流未关闭,请使用using或者ms.Close()
                using (MemoryStream ms = word.ModelCreateWord(filepath, t))
                {
                    // 保存路径
                    string path = @"E:\test project\WebApplication10\WebApplication10\Content\timg.docx";
                    word.SaveWord(ms, path);
    
                    // 生成成功后,需要保存网络路径到数据库
    
                    // 保存完成后,直接下载,请保持docx的编码格式
                    Response.Clear();
                    Response.ClearHeaders();
                    //Response.Buffer = false;
                    Response.ContentType = "application/octet-stream";
                    Response.AppendHeader("Content-Disposition", "attachment;filename="
                        + HttpUtility.UrlEncode("output.docx", System.Text.Encoding.UTF8));
                    Response.BinaryWrite(ms.ToArray());
                }
            }
    

      类

    /// <summary>
        /// 未继承AbstractGetValue无法被WordManage使用
        /// </summary>
        public class test : AbstractGetValue
        {
            public string text = string.Empty;
            public List<string> picture = new List<string>();
        }
    

      

    岁月无情催人老,请珍爱生命,远离代码!!!
  • 相关阅读:
    27. 移除元素
    axios调用webapi报错
    MySql重装以后,修改数据库路径,打开以前的数据库报Table 'XX库.XX表' doesn't exist错误的解决办法
    SqlServer2012,设置指定数据库对指定用户开放权限
    win10无法访问服务器上的共享文件夹怎么设置,提示:你不能访问此共享文件夹,因为你组织的安全策略阻止未经身份验证的来宾访问
    Vs2017的git的坑
    jira6.3.6创建问题不自动发邮件通知的问题
    在windows下面配置redis集群遇到的一些坑
    SqlServer2008 无法修改表,超时时间已到 在操作完成之前超时解决方法
    小程序中也可以使用三元运算符且可嵌套使用
  • 原文地址:https://www.cnblogs.com/zhoushangwu/p/15603425.html
Copyright © 2011-2022 走看看