C#操作Word文档--使用FreeSpire.Office

编程入门 行业动态 更新时间:2024-10-21 10:14:13

之前有个Asp.Net项目中需要从Excel中里导入数据,导出合同及合同的借据,心想着就用办公室提供的提供的那堆DLL库吧,简单方便,可是这堆DLL库严重依赖办公室,不可能在服务器上装个办公吧吧。于是Google了一下,搜出来那么一两个可以使用的库,一个是【NPOI  】,另外一个是【FreeSpire.Office】.FreeSpire.Office的API相对NPOI  的API要相对简单一些.FreeSpire.Office的正式版要收费,比如要使用到Spire.Office的一些功能(如:导出超过三页的PDF格式,EXCEL的Sheet创建五个以上等)就要收费了。

根据项目的情况,经过简单的分析,最后决定采用免费版的FreeSpire.Office,做一些复杂一点的操作时再用NPOI  。

这里先讲解一下项目中使用到的FreeSpire.Office的功能。

一,使用FreeSpire.Office从Excel中里读取数据

先准备存有数据的出色文件:

 读取数据的C#代码(忘了之前那段读取的代码在哪了,所以有写了段示例意思意思)

public static List<Person> FromExcel(string filePath)
{   
    if (!File.Exists(filePath))
    {
        throw new Exception("文件不存在");
    }
    List<Person> ps = new List<Person>();
    try
    {
        Workbook workbook = new Workbook();
        workbook.LoadFromFile(filePath);//加载excel文件

        //获取第一个Sheet
        Worksheet sheet = workbook.Worksheets[0];
        //循环读取数据
        
        int count = 2;
        while (true)
        {
            if (string.IsNullOrEmpty(sheet.Range[$"A{count}"].Text)) { break; }
            ps.Add(new Person()
            {
                Name = sheet.Range[$"A{count}"].Text,
                Gender = sheet.Range[$"B{count}"].Text
            });
            count++;
        }
    }
    catch
    {
        throw;
    }
    return ps;
}

二,使用FreeSpire.Office把数据写出在擅长里

准备要写入的数据:

Dictionary<string, string> dict = new Dictionary<string, string>();//单元格位置,内容
{                    
    dict.Add("A3", $"合同编号:{m2.LoanAgreementNO}");
    dict.Add("E3", $"担保合同编号:{m2.GuaranteeNO}");
    dict.Add("B7", $"(币种)人民币:{m2.MoneyDaXue}");

    dict.Add("P8", m2.MoneyFeng);//分
    dict.Add("O8", m2.MoneyJiao);//角
    dict.Add("N8", m2.MoneyYuan);//元
    dict.Add("M8", m2.MoneyShi);//十
    dict.Add("L8", m2.MoneyBai);//百
    dict.Add("K8", m2.MoneyQian);//千
    dict.Add("J8", m2.MoneyWan);//万
    dict.Add("I8", m2.MoneyShiWan);//十万
    dict.Add("H8", m2.MoneyBaiWan);//百万
    dict.Add("G8", m2.MoneyQianWan);//千万

    dict.Add("C9", $"{m2.StartDtYear}年{m2.StartDtMonth}月{m2.StartDtDay}日至{m2.EndDtYear}年{m2.EndDtMonth}月{m2.EndDtDay}日共{m2.Deadline}个月");
    dict.Add("G9", $"借款方式:{m2.JKFS}");
    dict.Add("j9", $"月利率:{m2.InteresRate}%");
    dict.Add("M9", $"还款方式:{m2.HKFS}");


    dict.Add("P22", m2.MoneyFeng);//分
    dict.Add("O22", m2.MoneyJiao);//角
    dict.Add("N22", m2.MoneyYuan);//元
    dict.Add("M22", m2.MoneyShi);//十
    dict.Add("L22", m2.MoneyBai);//百
    dict.Add("K22", m2.MoneyQian);//千
    dict.Add("J22", m2.MoneyWan);//万
    dict.Add("I22", m2.MoneyShiWan);//十万
    dict.Add("H22", m2.MoneyBaiWan);//百万
    dict.Add("G22", m2.MoneyQianWan);//千万

    dict.Add("C23", $"{m2.StartDtYear}年{m2.StartDtMonth}月{m2.StartDtDay}日至{m2.EndDtYear}年{m2.EndDtMonth}月{m2.EndDtDay}日共{m2.Deadline}个月");
    dict.Add("G23", $"借款方式:{m2.JKFS}");
    dict.Add("j23", $"月利率:{m2.InteresRate}%");
    dict.Add("M23", $"还款方式:{m2.JKFS}");

    dict.Add("P36", m2.MoneyFeng);//分
    dict.Add("O36", m2.MoneyJiao);//角
    dict.Add("N36", m2.MoneyYuan);//元
    dict.Add("M36", m2.MoneyShi);//十
    dict.Add("L36", m2.MoneyBai);//百
    dict.Add("K36", m2.MoneyQian);//千
    dict.Add("J36", m2.MoneyWan);//万
    dict.Add("I36", m2.MoneyShiWan);//十万
    dict.Add("H36", m2.MoneyBaiWan);//百万
    dict.Add("G36", m2.MoneyQianWan);//千万

    dict.Add("C37", $"{m2.StartDtYear}年{m2.StartDtMonth}月{m2.StartDtDay}日至{m2.EndDtYear}年{m2.EndDtMonth}月{m2.EndDtDay}日共{m2.Deadline}个月");
    dict.Add("G37", $"借款方式:{m2.JKFS}");
    dict.Add("j37", $"月利率:{m2.InteresRate}%");
    dict.Add("M37", $"还款方式:{m2.JKFS}");
}

写入的方法:

public static class ToExcel
{ 
    /// <summary>
    /// 
    /// </summary>
    /// <param name="yuanPath">模板路径</param>
    /// <param name="mubiaoPath">目标路径</param>
    /// <param name="dict">需要替换的excel的单元格及字符串</param>
    /// <returns></returns>
    public static bool ToExcelByMuban(string yuanPath,string mubiaoPath,Dictionary<string,string> dict) {
        if (dict == null)
        {
            throw new Exception("字典为空!");
        }

        if (!File.Exists(yuanPath))
        {
            throw new Exception("指定路径的模板文件不存在!");
        }

        try
        {
            Workbook book = new Workbook();
            book.LoadTemplateFromFile(yuanPath);
            Worksheet sheet = book.Worksheets[0];
            foreach (var d in dict)
            {
                sheet.Range[d.Key].Text = d.Value;
            }
            book.SaveToFile(mubiaoPath, ExcelVersion.Version97to2003);
            return true;
        }
        catch
        {
            return false;
        }
    }
}

调用写入方法:

bool b1 = ToExcel.ToExcelByMuban(JieJuYuanUrl, Server.MapPath(JieJuMubiaoUrl),dict);

 

三,使用FreeSpire.Office根据Wrod文档模板导出合同

1.准备文档模板

 

2.在文字文档中制定要替换的内容

以上图中的编号举例说明:

调出字中的【开发工具】选项卡

【文件】 - >【选项】 - >【自定义公能区】 - >勾选【开发工具】 - >确认

选中要替换的位置:【开发工具】,【工具箱】,【旧式窗体】,【AB |】插入一个【文本域(窗体控件)】

添加唯一标识符:选中上一步骤添加的【文本域(窗体控件)】,双击,调出【文本域(窗体控件)】选项,填写【书签】

导出合同的方法:

/// <summary>
/// 
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="mod">对象(其中的字段的名称和word模板文档中【文本域(窗体控件)】的【书签】的名称一致)</param>
/// <param name="TempleteFilePath">模板文档目录</param>
/// <param name="ExpFilePath">导出文件的目录</param>
/// <returns></returns>
public static bool ExportWordByFields<T>(T mod, string TempleteFilePath, string ExpFilePath)
{
    if (mod == null)
    {
        throw new Exception("模型为空!");
    }

    System.Reflection.PropertyInfo[] properties = mod.GetType().GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
    if (properties.Length <= 0)
    {
        throw new Exception("模型属性为空!");
    }

    if (!File.Exists(TempleteFilePath))
    {
        throw new Exception("指定路径的模板文件不存在!");
    }

    try
    {
        Document doc = new Document();
        doc.LoadFromFile(TempleteFilePath);

        #region 替换文字
        //doc.Replace("海关", "海关口岸", true, true);
        //doc.Replace("报验", "报检", true, true);
        #endregion

        //清除表单域阴影
        doc.Properties.FormFieldShading = false;
        FormFieldCollection collection = doc.Sections[0].Body.FormFields;
        //遍历Word模板中的文本域(field.name为文本域名称)
        foreach (FormField field in collection)
        {
            foreach (System.Reflection.PropertyInfo prop in properties)
            {
                string name = prop.Name; //属性名称  
                object value = prop.GetValue(mod, null);  //属性值  
                //string des = ((DescriptionAttribute)Attribute.GetCustomAttribute(prop, typeof(DescriptionAttribute))).Description;// 属性描述值

                //注意:文本域名称 == 模型中属性的 Description 值 !!!!!!
                //也可以: 文本域名称 == 模型中属性的 Name 值 !!!!!!
                if (field.Name == name && value != null)
                {
                    if (field.DocumentObjectType == DocumentObjectType.TextFormField)   //文本域
                    {
                        if (prop.PropertyType.Name == "Boolean")
                        {
                            if ((Boolean)value)
                            {
                                field.Text = "☑";   //插入勾选符号
                            }
                            else
                            {
                                field.Text = "⬜";   //插入勾选符号
                            }
                            break;
                        }
                        else
                        {
                            field.Text = value.ToString();   //向Word模板中插入值
                            break;
                        }
                    }
                    else if (field.DocumentObjectType == DocumentObjectType.CheckBox)   //复选框
                    {
                        (field as CheckBoxFormField).Checked = (value as bool?).HasValue ? (value as bool?).Value : false;
                    }
                }
            }
        }
        doc.Protect(ProtectionType.AllowOnlyReading, Guid.NewGuid().ToString());//加密文档
        doc.SaveToFile(ExpFilePath, FileFormat.Docx);
        doc.Close();

        return true;
    }
    catch (Exception ex)
    {
        throw new Exception(ex.Message);
    }
}

在上面导出合同中没有涉及到循环导出的问题

该项目还有另外一中合同涉及到多人一起签署合同的情况,需要把合同的签署人一起到处

我的办法是,在模板里添加一个一行一列的表格,弄成无边框的,

在代码中拼接内容,在把内容添加到表格中(因为合同中有三个地方需要添加,所以弄了三个表格,另外两个地方是以表格的形式显示的)

TableCollection tableCollection = doc.Sections[0].Tables;//获取文档内的所有表格
int i = 0;
foreach (Table v in tableCollection)
{
    int j = 0;
    foreach (EMultilevelJointInsurance c in eMultilevelJointInsurances)
    {
        if (i == 0)
        {
            Paragraph p = v.Rows[0].Cells[0].AddParagraph();
            p.AppendText("联保人:").CharacterFormat.FontSize = 15;
            TextRange range = p.AppendText(c.Name);
            range.CharacterFormat.UnderlineStyle = UnderlineStyle.Single;
            range.CharacterFormat.FontSize = 15;

            p.AppendText("身份证号码:").CharacterFormat.FontSize = 15;
            TextRange rangeId = p.AppendText(c.IDCardNo);
            rangeId.CharacterFormat.FontSize = 15;
            rangeId.CharacterFormat.UnderlineStyle = UnderlineStyle.Single;
            p.AppendText("\n");
            p.AppendText("居住地址:").CharacterFormat.FontSize = 15;
            TextRange rangeAdd = p.AppendText(c.ResidenceAddress);
            rangeAdd.CharacterFormat.FontSize = 15;
            rangeAdd.CharacterFormat.UnderlineStyle = UnderlineStyle.Single;
        }
        else if (i == 1)
        {
            v.AddRow();
            Paragraph p = v.Rows[j + 1].Cells[0].AddParagraph();
            p.Format.HorizontalAlignment = HorizontalAlignment.Center;
            p.AppendText((j + 1).ToString());

            Paragraph p1 = v.Rows[j + 1].Cells[1].AddParagraph();
            p1.Format.HorizontalAlignment = HorizontalAlignment.Center;
            p1.AppendText(c.Name);

            Paragraph p2 = v.Rows[j + 1].Cells[2].AddParagraph();
            p2.Format.HorizontalAlignment = HorizontalAlignment.Center;
            p2.AppendText(c.IDCardNo);

            Paragraph p3 = v.Rows[j + 1].Cells[3].AddParagraph();
            p3.Format.HorizontalAlignment = HorizontalAlignment.Center;
            p3.AppendText((c.ApprovalQuota * 10000).ToString());

            Paragraph p4 = v.Rows[j + 1].Cells[4].AddParagraph();
            p4.Format.HorizontalAlignment = HorizontalAlignment.Center;
            p4.AppendText(c.LoanUsage);

            CellFormat cellStyle = v.Rows[j + 1].Cells[0].CellFormat;
            cellStyle.VerticalAlignment = VerticalAlignment.Middle;
        }
        else if(i == 2)
        {
            v.AddRow();
            Paragraph p = v.Rows[j + 2].Cells[0].AddParagraph();
            p.Format.HorizontalAlignment = HorizontalAlignment.Center;
            p.AppendText(c.Name + $"({j + 1})");

            Paragraph p1 = v.Rows[j + 2].Cells[3].AddParagraph();
            p1.Format.HorizontalAlignment = HorizontalAlignment.Center;
            p1.AppendText(c.IDCardNo);

            CellFormat cellStyle = v.Rows[j + 1].Cells[0].CellFormat;
            cellStyle.VerticalAlignment = VerticalAlignment.Middle;
        }
        j++;
    }
    i++;
}

随便也说了一下word中表格的简单操作

四,使用FreeSpire.Office根据Wrod文档模板到处借据

同样也准备借据的模板:

根据以上借据分析,只有【联保成员】需要循环获取,其他地方只需要用【文本域(窗体控件)】替换旧可以了

我的做法是把联保人所涉及到的行全部删除,在导出的时候,把联保组长所在的行复制下来,再替换其内容

所以代码变成如下的了

TableCollection tableCollection = doc.Sections[0].Tables;//获取文档内的所有表格

foreach (Table v in tableCollection)
{
    //组长
    v.Rows[0].Cells[1].Paragraphs[0].Text = insurance.Name;//联保组织姓名
    //v.Rows[0].Cells[3].Paragraphs[0].Text = "建行";//开户行
    //v.Rows[0].Cells[5].Paragraphs[0].Text = "6217 0039 10000 853";//银行账号
    v.Rows[1].Cells[1].Paragraphs[0].Text = $"(大写)人民币{insurance.MoneyDaXue}元";//大写的金额

    v.Rows[2].Cells[2].Paragraphs[0].Text = insurance.MoneyBaiWan;//百
    v.Rows[2].Cells[3].Paragraphs[0].Text = insurance.MoneyShiWan;//十
    v.Rows[2].Cells[4].Paragraphs[0].Text = insurance.MoneyWan;//万

    v.Rows[2].Cells[5].Paragraphs[0].Text = insurance.MoneyQian;//千
    v.Rows[2].Cells[6].Paragraphs[0].Text = insurance.MoneyBai;//百

    v.Rows[2].Cells[7].Paragraphs[0].Text = insurance.MoneyShi;//十
    v.Rows[2].Cells[8].Paragraphs[0].Text = insurance.MoneyYuan;//元
    v.Rows[2].Cells[9].Paragraphs[0].Text = insurance.MoneyJiao;//角
    v.Rows[2].Cells[10].Paragraphs[0].Text = insurance.MoneyFeng;//分

    int i = 0;
    foreach (EMultilevelJointInsurance c in eMultilevelJointInsurances)
    {
        //把联保组长的【行】复制下来
        v.Rows.Insert((3 * i) + 3, v.Rows[0].Clone());
        v.Rows.Insert((3 * i) + 4, v.Rows[1].Clone());
        v.Rows.Insert((3 * i) + 5, v.Rows[2].Clone());


        v.Rows[(3 * i) + 3].Cells[0].Paragraphs[0].Text = $"联保成员({i + 1})";
        v.Rows[(3 * i) + 3].Cells[1].Paragraphs[0].Text = c.Name;
        v.Rows[(3 * i) + 3].Cells[3].Paragraphs[0].Text = "";//开户行
        v.Rows[(3 * i) + 3].Cells[5].Paragraphs[0].Text = "";//银行账号
        v.Rows[(3 * i) + 4].Cells[1].Paragraphs[0].Text = $"(大写)人民币{c.MoneyDaXue}元";//大写的金额


        v.Rows[(3 * i) + 5].Cells[2].Paragraphs[0].Text = c.MoneyBaiWan;//百
        v.Rows[(3 * i) + 5].Cells[3].Paragraphs[0].Text = c.MoneyShiWan;//十
        v.Rows[(3 * i) + 5].Cells[4].Paragraphs[0].Text = c.MoneyWan;//万

        v.Rows[(3 * i) + 5].Cells[5].Paragraphs[0].Text = c.MoneyQian;//千
        v.Rows[(3 * i) + 5].Cells[6].Paragraphs[0].Text = c.MoneyBai;//百

        v.Rows[(3 * i) + 5].Cells[7].Paragraphs[0].Text = c.MoneyShi;//十
        v.Rows[(3 * i) + 5].Cells[8].Paragraphs[0].Text = c.MoneyYuan;//元
        v.Rows[(3 * i) + 5].Cells[9].Paragraphs[0].Text = c.MoneyJiao;//角
        v.Rows[(3 * i) + 5].Cells[10].Paragraphs[0].Text = c.MoneyFeng;//分

        i++;
    }
}

 

五,使用NPOI  导出数据到Excel中

因为要导出的数据较多,而FreeSpire.Office免费版限制,所以使用NPOI,这里只给出代码

private bool ExportToExcelAll(ISession iSession, List<EAssessmentResult> es,string path,string fileName)
{
    try
    {
        EAssessmentResultDetail.Schema s = new EAssessmentResultDetail.Schema();
        XSSFWorkbook book = new XSSFWorkbook();
        int i = 0;
        foreach (EAssessmentResult e in es)
        {
            var sheet = book.CreateSheet($"{i + 1}-{e.FullPathName}"); //创建工作表
            var row_Title = sheet.CreateRow(0); //创建列头行
            row_Title.CreateCell(0).SetCellValue("指标名称"); //创建单元格
            row_Title.CreateCell(1).SetCellValue("指标类型"); //创建单元格
            row_Title.CreateCell(2).SetCellValue("评分"); //创建单元格
            row_Title.CreateCell(3).SetCellValue("权重"); //创建单元格
            row_Title.CreateCell(4).SetCellValue("考评分数"); //创建单元格
            int j = 1;
            double total = 0;
            List<EAssessmentResultDetail> lst = QAssessmentResultDetail.Get(iSession, s.AssessmentResultsID == e.AssessmentResultsID, null);
            foreach (EAssessmentResultDetail d in lst)
            {
                var row = sheet.CreateRow(j); 
                row.CreateCell(0).SetCellValue(d.Name); //创建单元格
                row.CreateCell(1).SetCellValue(d.IndicatorsTypeName); //创建单元格
                row.CreateCell(2).SetCellValue(d.Rating.ToString()); //创建单元格
                row.CreateCell(3).SetCellValue(d.Weights.ToString()); //创建单元格
                row.CreateCell(4).SetCellValue(d.Score.ToString()); //创建单元格
                
                total += d.Score;                        
                j++;
            }
            var rowTotal = sheet.CreateRow(j);
            rowTotal.CreateCell(0).SetCellValue("总分");
            rowTotal.CreateCell(4).SetCellValue(total.ToString());
            i++;
        }
        if (!Directory.Exists(Server.MapPath(path)))
        {
            Directory.CreateDirectory(Server.MapPath(path));
        }
        FileStream fs2 = File.Create(Server.MapPath(path + fileName));
        book.Write(fs2);
        fs2.Close();
    }
    catch(Exception ex)
    {
        throw ex;
    }
    return true;
}

 

更多推荐

C#操作Word文档--使用FreeSpire.Office

本文发布于:2023-06-14 06:19:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1446074.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:操作   文档   Office   Word   FreeSpire

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!