Aspose使用

发布于:2025-08-14 ⋅ 阅读:(17) ⋅ 点赞:(0)

模板文档手动添加占位符:
1)使用邮件合并域方式:

快捷键:按 Ctrl+F9 插入域代码括号 { }--在括号内输入:MERGEFIELD 占位符名称
例:{ MERGEFIELD Name }   或:插入->文档部件->域->MERGEFIELD 域名部分输入名称

使用 Aspose.Words 填充数据

Document doc = new Document("模板.docx");

// 创建数据源(例如 DataTable 或自定义对象)
DataTable dataTable = new DataTable();
dataTable.Columns.Add("Name"); // 列名需匹配占位符名称
dataTable.Rows.Add("张三");

// 执行邮件合并
doc.MailMerge.Execute(dataTable);

doc.Save("结果.docx");

2)使用自定义文本标记(简单替换)
直接写入可识别的唯一文本,例如:
[姓名]{{COMPANY}}%%DATE%% 等。

Document doc = new Document("模板.docx");

// 替换所有匹配的占位符
doc.Range.Replace("[姓名]", "李四", new FindReplaceOptions());
doc.Range.Replace("{{COMPANY}}", "Acme Corp", new FindReplaceOptions());
doc.Range.Replace("%%DATE%%", DateTime.Now.ToString("yyyy-MM-dd"), new FindReplaceOptions());

doc.Save("结果.docx");

一些详细的配置项:
 

// 配置替换选项(区分大小写、全字匹配等)
FindReplaceOptions options = new FindReplaceOptions {
    MatchCase = true,    // 区分大小写
    FindWholeWordsOnly = true // 全字匹配
};

3)复杂内容的插入:

Aspose.Words提供了强大的扩展能力,主要通过`MailMerge`的`FieldMergingCallback`和域代码(如IF域)来实现。

(1)插入表格或图片(使用FieldMergingCallback)

在需要插入表格或图片的位置,插入一个MERGEFIELD域,例如:`{ MERGEFIELD InsertTable }`。

创建一个类,实现`IFieldMergingCallback`接口,并在`FieldMerging`方法中处理特定域的合并行为。

在`FieldMerging`方法中: - 判断当前域的名称。 - 如果是要插入表格或图片的域,则创建表格或图片对象,并将其添加到当前合并域的位置。

// 1. 创建自定义回调类
public class ImageTableFieldMerger : IFieldMergingCallback
{
    public void FieldMerging(FieldMergingArgs args)
    {
        // 处理图片插入
        if (args.FieldName == "CompanyLogo")
        {
            // 从文件加载图片
            Shape shape = new Shape(args.Document, ShapeType.Image);
            shape.ImageData.SetImage("logo.png");
            shape.Width = 100;   // 设置宽度
            shape.Height = 50;  // 设置高度
            
            // 插入到文档
            args.Document.FirstSection.Body.FirstParagraph.AppendChild(shape);
            args.Text = "";  // 清除默认文本
        }
        // 处理表格插入
        else if (args.FieldName == "ProductTable")
        {
            // 创建数据表格
            DataTable products = new DataTable();
            products.Columns.Add("Name");
            products.Columns.Add("Price");
            products.Rows.Add("Laptop", "$1200");
            products.Rows.Add("Phone", "$800");
            
            // 创建Word表格
            Table table = new Table(args.Document);
            table.PreferredWidth = PreferredWidth.FromPercent(100);
            
            // 添加表头
            Row headerRow = new Row(args.Document);
            headerRow.RowFormat.HeadingFormat = true;
            headerRow.Cells.Add(new Cell(args.Document) { CellFormat = { Shading = { BackgroundPatternColor = Color.LightGray }}}).AppendChild(new Paragraph(args.Document)).AppendChild(new Run(args.Document, "Product"));
            headerRow.Cells.Add(new Cell(args.Document)).AppendChild(new Paragraph(args.Document)).AppendChild(new Run(args.Document, "Price"));
            table.AppendChild(headerRow);
            
            // 添加数据行
            foreach (DataRow row in products.Rows)
            {
                Row dataRow = new Row(args.Document);
                dataRow.Cells.Add(new Cell(args.Document)).AppendChild(new Paragraph(args.Document)).AppendChild(new Run(args.Document, row["Name"].ToString()));
                dataRow.Cells.Add(new Cell(args.Document)).AppendChild(new Paragraph(args.Document)).AppendChild(new Run(args.Document, row["Price"].ToString()));
                table.AppendChild(dataRow);
            }
            
            // 插入表格到文档
            args.Document.FirstSection.Body.AppendChild(table);
            args.Text = "";  // 清除默认文本
        }
    }

    public void ImageFieldMerging(ImageFieldMergingArgs args)
    {
        // 图片处理接口(可空实现)
    }
}

// 2. 使用回调执行邮件合并
Document doc = new Document("template.docx");
doc.MailMerge.UseNonMergeFields = true; // 允许处理非MERGEFIELD
doc.MailMerge.FieldMergingCallback = new ImageTableFieldMerger();

// 3. 执行合并(即使没有数据源也需要调用)
doc.MailMerge.Execute(new string[0], new object[0]);

doc.Save("result.docx");

(2)条件文本(使用IF域):

域内输入条件语句:

{ IF { MERGEFIELD Amount } > 100 "High Value" "Normal Value" }
Document doc = new Document("template.docx");

// 准备数据源
DataTable data = new DataTable();
data.Columns.Add("Amount");
data.Rows.Add(150);  // 测试值1
data.Rows.Add(80);   // 测试值2

// 执行邮件合并
doc.MailMerge.Execute(data);

// 更新域计算结果(必须调用)
doc.UpdateFields();

doc.Save("result.docx");

带条件的表格输入:
 

// 自定义回调类增强版
public class AdvancedFieldMerger : IFieldMergingCallback
{
    public void FieldMerging(FieldMergingArgs args)
    {
        // 根据条件动态插入表格
        if (args.FieldName == "DetailTable")
        {
            // 从数据源获取条件值
            int orderAmount = (int)args.Record.GetValue("Amount");
            
            // 仅当金额>100时插入表格
            if (orderAmount > 100)
            {
                Table table = CreateDetailTable(args.Document);
                args.Document.FirstSection.Body.AppendChild(table);
            }
            args.Text = "";
        }
    }
    
    private Table CreateDetailTable(Document doc)
    {
        // 创建详细表格(代码同上)
        // ...
    }
}

// 使用方式
doc.MailMerge.FieldMergingCallback = new AdvancedFieldMerger();
doc.MailMerge.Execute(data);
doc.UpdateFields();  // 更新条件域

如何实习:
 

using Aspose.Words;
using FreeSql;
using System.Collections.Generic;
using System.Data;
using System.Linq;

public class ContractGenerator
{
    private readonly IFreeSql _fsql;  // FreeSql数据库访问对象

    // 构造函数:注入FreeSql实例
    public ContractGenerator(IFreeSql freeSql)
    {
        _fsql = freeSql;  // 初始化数据库访问对象
    }

    // 主方法:生成合同文档
    public void GenerateContract(int contractId)
    {
        // 1. 从数据库获取合同数据
        var contract = _fsql.Select<Contract>()  // 创建查询
            .Where(c => c.Id == contractId)      // 按ID过滤
            .First();                            // 获取第一条记录
        
        // 2. 根据合同类型选择模板路径
        string templatePath = contract.Type switch  // switch表达式匹配合同类型
        {
            1 => "Templates/contract_type1.docx",  // 类型1使用模板1
            2 => "Templates/contract_type2.docx",  // 类型2使用模板2
            _ => throw new Exception("未知合同类型") // 其他类型抛出异常
        };

        // 3. 加载Word模板
        Document doc = new Document(templatePath);
        
        // 4. 准备字段值字典
        Dictionary<string, object> fieldValues = PrepareFieldValues(contract);
        
        // 5. 执行邮件合并
        ExecuteMailMerge(doc, fieldValues);
        
        // 6. 保存生成的合同文档
        doc.Save($"Output/contract_{contractId}.docx");
    }

    // 准备字段值字典:核心逻辑
    private Dictionary<string, object> PrepareFieldValues(Contract contract)
    {
        // 创建字典存储字段名和对应值
        var values = new Dictionary<string, object>();
        
        // 添加基本字段
        values.Add("ContractId", contract.Id);  // 合同ID
        values.Add("ClientName", contract.ClientName);  // 客户名称
        values.Add("SignDate", contract.SignDate.ToString("yyyy-MM-dd"));  // 格式化签约日期
        
        // 处理单选框值:将逗号分隔字符串转换为列表
        var radioValues = contract.RadioValue?
            .Split(',')                         // 按逗号分割
            .Select(v => v.Trim())              // 去除空格
            .ToList() ?? new List<string>();    // 空值处理
        
        // 处理复选框值:同样转换为列表
        var checkValues = contract.CheckValues?
            .Split(',')
            .Select(v => v.Trim())
            .ToList() ?? new List<string>();
        
        // 单选框处理:检查值是否存在,返回对应符号
        values.Add("RADIO_Agree", 
            radioValues.Contains("Agree") ? "☑" : "□");
        values.Add("RADIO_Disagree", 
            radioValues.Contains("Disagree") ? "☑" : "□");
        
        // 复选框处理:同样逻辑
        values.Add("CHECK_24Support", 
            checkValues.Contains("24Support") ? "☑" : "□");
        values.Add("CHECK_FreeUpgrade", 
            checkValues.Contains("FreeUpgrade") ? "☑" : "□");
        values.Add("CHECK_VIPService", 
            checkValues.Contains("VIPService") ? "☑" : "□");
        
        // 动态内容处理
        values.Add("DYNAMIC_CONTENT", PrepareDynamicContent(contract));
        
        return values;  // 返回填充好的字典
    }

    // 准备动态内容:根据合同类型返回不同文本
    private string PrepareDynamicContent(Contract contract)
    {
        // 使用switch表达式处理不同类型
        return contract.Type switch
        {
            1 => "【类型1专属条款】\n1. 条款内容 A\n2. 条款内容 B",  // 类型1内容
            2 => "〖类型2特别约定〗\n• 特殊条款 1\n• 特殊条款 2",  // 类型2内容
            _ => string.Empty  // 默认空内容
        };
    }

    // 执行邮件合并
    private void ExecuteMailMerge(Document doc, Dictionary<string, object> fieldValues)
    {
        // 创建DataTable作为邮件合并数据源
        DataTable dataTable = new DataTable("ContractData");
        
        // 添加列:字典的每个键作为列名
        foreach (var key in fieldValues.Keys)
        {
            dataTable.Columns.Add(key);
        }
        
        // 创建数据行
        DataRow row = dataTable.NewRow();
        
        // 填充行数据:遍历字典键值对
        foreach (var kvp in fieldValues)
        {
            row[kvp.Key] = kvp.Value;  // 设置每列的值
        }
        
        // 添加行到DataTable
        dataTable.Rows.Add(row);
        
        // 配置邮件合并
        doc.MailMerge.UseNonMergeFields = true;  // 允许处理所有域,不仅是MERGEFIELD
        
        // 执行邮件合并:将DataTable数据合并到文档
        doc.MailMerge.Execute(dataTable);
    }
}

// 数据库实体类
public class Contract
{
    public int Id { get; set; }         // 合同ID
    public int Type { get; set; }        // 合同类型(1或2)
    public string ClientName { get; set; }  // 客户名称
    public DateTime SignDate { get; set; }  // 签约日期
    
    // 单选框值(逗号分隔的选项字符串)
    public string RadioValue { get; set; } 
    
    // 复选框值(逗号分隔的选项字符串)
    public string CheckValues { get; set; } 
}


网站公告

今日签到

点亮在社区的每一天
去签到