Aspose.words使用记录

Aspose.words for java

一、邮件合并

  1. 接口编写,组装数据。

    组装map,以及需要遍历的列表数据。

    # invoice
    {
        "id": "1651783854850650113",
        "createBy": "admin",
        "createTime": "2023-04-28",
        "updateBy": null,
        "updateTime": null,
        "sysOrgCode": "A02A02A01",
        "invoiceNo": "INV-20230428-012",
        "invoiceType": "1",
        "parentContractNo": "000001",
        "customerName": "测试0426黄11",
        "customerId": "1651060982522449920",
        "billContact": "粉红色调",
        "billMail": "4949198@joifdc.com",
        "billTel": "5949189",
        "state": "2",
        "remark": "31321",
        "totalPrice": 1317.00,
        "orderDate": "2023-04-28",
        "mailAddress": "你好世界",
        "orderNo": "CM-20230428-001",
        "invoiceType_dictText": "维修"
    }
    ​
    #invoiceWorkList
    [
        {
            "id": "1651783855219748866",
            "invoiceId": "1651783854850650113",
            "workContent": "31",
            "unitPrice": 654.00,
            "deposite": null,
            "isDeductionOfDeposit": null,
            "plateNo": "TET",
            "carId": null
        },
        {
            "id": "1651783855219748867",
            "invoiceId": "1651783854850650113",
            "workContent": "2",
            "unitPrice": 6.00,
            "deposite": null,
            "isDeductionOfDeposit": null,
            "plateNo": "CAR-0426-01",
            "carId": null
        },
        {
            "id": "1651783855219748868",
            "invoiceId": "1651783854850650113",
            "workContent": "32455",
            "unitPrice": 654.00,
            "deposite": null,
            "isDeductionOfDeposit": null,
            "plateNo": "Tio-001",
            "carId": null
        },
        {
            "id": "1651783855219748869",
            "invoiceId": "1651783854850650113",
            "workContent": "456",
            "unitPrice": 3.00,
            "deposite": null,
            "isDeductionOfDeposit": null,
            "plateNo": "Tio-002",
            "carId": null
        }
    ]
    

@RequestMapping(value = "/printPdf", method = RequestMethod.GET)
    public void printPdf(@RequestParam(name="id") String id, HttpServletResponse response) {
        try {
            Invoice invoice=invoiceService.getById(id);
            Map<String, Object> objectMap = BeanUtil.beanToMap(invoice);
            String invoiceType = sysDictService.queryDictTextByKey("InvoiceType", String.valueOf(invoice.getInvoiceType()));
            // 处理字典
            objectMap.put("invoiceType", invoiceType);
            // 处理日期
            String orderDate = DateUtil.formatDate(invoice.getOrderDate());
            objectMap.put("orderDate", orderDate);
            // 插入水印
            objectMap.put("chapter", TemplatePathEnum.CHAPTER);
            // 查子表
            Map<String, Object> listMap = new HashMap<>();
            List<InvoiceWork> invoiceWorkList = invoiceWorkService.selectByMainId(id);
​
            listMap.put("invoiceWorkList", invoiceWorkList);
            AsposeWordUtil.GenerateByTemplate(TemplatePathEnum.INVOICE, response, objectMap,listMap, SaveFormat.PDF, new InvoiceFieldMergingCallback());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
  1. 生成模板方法。这里用了小胡子语法。

mailMerge.execute注入map数据,MailMergeDataSource需要自己继承实现

mailMerge.executeWithRegions注入列表数据,RegionsMailMergeDataSource需要自己继承实现

mailMerge.setFieldMergingCallback注入数据时的回调


public static void GenerateByTemplate(String path, HttpServletResponse response, Map<String,Object> data,Map<String,Object> listMap,int saveFormat,IFieldMergingCallback iFieldMergingCallback) {
​
        if (!getlic()){throw new JeecgBootException("获取证书失败");}
​
        response.addHeader("Content-Disposition", "attachment;filename="+"template."+SaveFormat.getName(saveFormat));
​
        try{
            InputStream resourceAsStream = AsposeWordUtil.class.getClassLoader().getResourceAsStream(path);
​
            Document doc = new Document(resourceAsStream);
            // 邮件合并
            MailMerge mailMerge = doc.getMailMerge();
​
            doc.getMailMerge().setCleanupOptions(MailMergeCleanupOptions.REMOVE_UNUSED_REGIONS);
            // 字段合并回调
            mailMerge.setFieldMergingCallback(iFieldMergingCallback);
            // 使用小胡子语法{{$value}}
            mailMerge.setUseNonMergeFields(true);
            // 注入map映射数据
            mailMerge.execute(new MailMergeDataSource(data));
            if(listMap!=null){
                // 注入列表数据
                for (Map.Entry<String, Object> entry : listMap.entrySet()) {
                    String key = entry.getKey();
                    Object value = entry.getValue();
                    if(ObjectUtil.isNull(value)){continue;}
                    List<Map<String, Object>> list = Convert.convert(new TypeReference<List<Map<String, Object>>>() {
                    }, value);
                    // if(list.size()==0){continue;}
                    // 邮件列表字段合并,必须要添加合并字段,否则setCleanupOptions不生效
                    mailMerge.executeWithRegions(new RegionsMailMergeDataSource(key, list));
                }
            }
​
            // 清除未使用的邮件合并字段
            mailMerge.deleteFields();
            doc.save(response.getOutputStream(), saveFormat);
            response.getOutputStream().close();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
  1. MailMergeDataSource
package com.autotoll.aspose;
​
import cn.hutool.core.util.ObjectUtil;
import com.aspose.words.IMailMergeDataSource;
import com.aspose.words.ref.Ref;
​
import java.util.Map;
​
public class MailMergeDataSource implements IMailMergeDataSource {
    private Map<String,Object> map;
​
    // 只需要遍历一次
    private boolean Once;
​
    public MailMergeDataSource(Map<String, Object> map) {
        this.map = map;
        this.Once=true;
    }
​
    @Override
    public String getTableName() throws Exception {
        return null;
    }
​
    @Override
    public boolean moveNext() throws Exception {
        if (Once){
            Once=false;
            return true;
        }else{
            return false;
        }
    }
​
    @Override
    public boolean getValue(String s, Ref<Object> ref) throws Exception {
        ref.set(map.get(s));
        return ObjectUtil.isNotNull(map.get(s));
    }
​
    @Override
    public IMailMergeDataSource getChildDataSource(String s) throws Exception {
        return null;
    }
}
  1. RegionsMailMergeDataSource

package com.autotoll.aspose;
​
import cn.hutool.core.util.ObjectUtil;
import com.aspose.words.IMailMergeDataSource;
import com.aspose.words.ref.Ref;
​
import java.util.Iterator;
import java.util.List;
import java.util.Map;
​
public class RegionsMailMergeDataSource implements IMailMergeDataSource {
    private List<Map<String,Object>> list;
​
    private Iterator<Map<String,Object>> iterator;
​
    private String tableName;
​
    private Map<String,Object> item;
​
    public RegionsMailMergeDataSource(String tableName,List<Map<String, Object>> list) {
        this.list = list;
        this.iterator = this.list.iterator();
        this.tableName = tableName;
    }
​
    @Override
    public String getTableName() throws Exception {
        return this.tableName;
    }
​
    @Override
    public boolean moveNext() throws Exception {
        if(iterator.hasNext()){
            item = iterator.next();
            return true;
        }else{
            return false;
        }
    }
​
    @Override
    public boolean getValue(String s, Ref<Object> ref) throws Exception {
        ref.set(item.get(s));
        return ObjectUtil.isNotNull(item.get(s));
    }
​
    @Override
    public IMailMergeDataSource getChildDataSource(String s) throws Exception {
        return null;
    }
}
  1. 回调
package com.autotoll.aspose.merge;
​
import com.aspose.words.*;
import com.autotoll.aspose.FieldMergingCallback;
​
import java.io.InputStream;
​
public class InvoiceFieldMergingCallback implements IFieldMergingCallback {
​
    private DocumentBuilder mBuilder;
​
    @Override
    public void fieldMerging(FieldMergingArgs e) throws Exception {
        // if (mBuilder == null)
        //     mBuilder = new DocumentBuilder(e.getDocument());
​
        Document doc = e.getDocument();
​
        // 删除书签所在位置===>标题栏
        // if("totalPrice".equals(e.getFieldName())){
        //     if(new BigDecimal(e.getFieldValue().toString()).compareTo(BigDecimal.ZERO)==0){
        //         BookmarkCollection bookmarks = doc.getRange().getBookmarks();
        //         Bookmark myBookmark = bookmarks.get("myBookmark");
        //         myBookmark.getBookmarkStart().getParentNode().getParentNode().getParentNode().remove();
        //         FieldStart start = e.getField().getStart();
        //         if (start.getParentNode().getParentNode().getParentNode() != null) {
        //             start.getParentNode().getParentNode().getParentNode().remove();
        //         }
        //         e.getField().remove();
        //     }
        // }
    }
​
    @Override
    public void imageFieldMerging(ImageFieldMergingArgs args) throws Exception {
        InputStream resourceAsStream = FieldMergingCallback.class.getClassLoader().getResourceAsStream(args.getFieldValue().toString());
​
        Shape shape = new Shape(args.getDocument(), ShapeType.IMAGE);
        {
            shape.setWidth(70.0); shape.setHeight(70.0);
            shape.setWrapType(WrapType.NONE);
        }
        // 设置图片数据流
        shape.getImageData().setImage(resourceAsStream);
​
        // 形状在文字下面
        shape.setBehindText(true);
​
        shape.setHorizontalAlignment(HorizontalAlignment.CENTER);
        shape.setTop(-20);
        args.setShape(shape);
​
    }
}
​
  1. 模板

    其中小胡子语法{{}}不需要加域,《》是加域后显示的效果。

image-20230428144101381.png 7. 结果

image-20230428144319869.png

2023.5.16 小胡子语法中使用if,和官网相同,但是比较坑的是没有告知{}是用域创建的,word快捷键是ctrl+f9 image.png

二、 LINQ报告引擎

个人感觉不好用,可参考docs.aspose.com/words/java/…

image.png