1.word模板制作

  1. 在word文档光标位置,插入 -》文档部件 -》域,弹框如下:

excel模板填充数据打印 java java填充word模板_excel模板填充数据打印 java

最终生成的模板文档如下:

excel模板填充数据打印 java java填充word模板_java_02

注:图片域和单个变量域是同一个,定义图片域时,同一个图片需要定义不同的域名。

2.工具类准备

  1. 使用Aspose进行文档转换,首先引入相应的jar包到系统环境
  2. 项目resource下导入license.xml文件
  3. 使用Aspose时,需要调用设置License方法,设置完成第一次替换比较慢,再次就不需要设置License方法,效率会更高。

注意:使用Aspose时,每一个模块(words,pdf,cells)都有相同的类,如License类,SaveOptions类,SaveFormat类,功能各不相同。

获取license示例代码:

package com.sinoif.common.utils;

import com.aspose.words.License;
import lombok.extern.slf4j.Slf4j;

import java.io.InputStream;

/**
 * @description:
 * @author: guanlj
 * @date: 2020/7/24 11:10
 */
@Slf4j
public class AsposeLicenseUtil {
	private static License aposeLic = new License();

	/**
	 * 获取License的输入流
	 *
	 * @return
	 */
	private static InputStream getLicenseInput() {

		InputStream inputStream = null;
		ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
		try {
            //获取项目resource下的文件流
			inputStream = contextClassLoader.getResourceAsStream("license.xml");
		} catch (Exception e) {
			log.error("license not found!"+ e);
		}
		return inputStream;
	}

	/**
	 * 设置License
	 *
	 * @return true表示已成功设置License, false表示失败
	 */
	public static boolean setWordsLicense() {
		if (!aposeLic.getIsLicensed()) {
			try {
				aposeLic.setLicense(getLicenseInput());
				return aposeLic.getIsLicensed();
			} catch (Exception e) {
				log.error("set words license error!", e);
			}
		}
		return aposeLic.getIsLicensed();
	}

}

 

3.模板填充

代码示例:

package com.sinoif.common.utils;

import com.aspose.words.*;
import com.aspose.words.net.System.Data.DataRow;
import com.aspose.words.net.System.Data.DataTable;
import lombok.extern.slf4j.Slf4j;

import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.WritableRaster;
import java.beans.PropertyDescriptor;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author guanlj
 * @date 2020/01/22
 */
@Slf4j
public class ContractUtil {

	/** 方框value */
	public static String CODE_BOX = "codeBox";
	/** 方框打勾value */
	public static String CODE_TICK = "codeTick";

    private ContractUtil() {
    }

    /**
     * 调整bufferedimage大小
     * @param source BufferedImage 原始image
     * @param targetW int  目标宽
     * @param targetH int  目标高
     * @param flag boolean 是否同比例调整
     * @return BufferedImage  返回新image
     */
    public static BufferedImage resizeBufferedImage(BufferedImage source, int targetW, int targetH, boolean flag) {
        int type = source.getType();
        BufferedImage target = null;
        double sx = (double) targetW / source.getWidth();
        double sy = (double) targetH / source.getHeight();
        if (flag && sx > sy) {
            sx = sy;
            targetW = (int) (sx * source.getWidth());
        } else if(flag && sx <= sy){
            sy = sx;
            targetH = (int) (sy * source.getHeight());
        }
		// TYPE_CUSTOM
        if (type == BufferedImage.TYPE_CUSTOM) {
            ColorModel cm = source.getColorModel();
            WritableRaster raster = cm.createCompatibleWritableRaster(targetW, targetH);
            boolean alphaPremultiplied = cm.isAlphaPremultiplied();
            target = new BufferedImage(cm, raster, alphaPremultiplied, null);
        } else {
            target = new BufferedImage(targetW, targetH, type);
        }
        Graphics2D g = target.createGraphics();
		g.setBackground(new Color(255,255,255));
		g.setColor(new Color(255,255,255));
		g.fillRect(0, 0, targetW, targetH);
		g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
		g.drawImage(source.getScaledInstance(targetW, targetH, Image.SCALE_SMOOTH), 0, 0, null);
//        g.drawRenderedImage(source, AffineTransform.getScaleInstance(sx, sy));
        g.dispose();
        return target;
    }


    /**
     * 填充 word 模板(object数据格式)
     *
     * @param modelWordByte word模版二进制文件
     * @param obj     要填充的数据
     * @return 组合数据之后的word二进制
     */
    public static byte[] fillWordDataByDomain(byte[] modelWordByte, Object obj) {
        try {
            Class<?> aClass = obj.getClass();
            Field[] fields = aClass.getDeclaredFields();
            Map<String, Object> data = new HashMap<>(fields.length);
            for (Field field : fields) {
                PropertyDescriptor pd = new PropertyDescriptor(field.getName(), aClass);
                Method method = pd.getReadMethod();
                String key = field.getName();
                Object value = method.invoke(obj);
                if (value != null) {
                    data.put(key, value);
                } else {
					data.put(key, "  ");
				}
            }
            return fillWordDataByMap(modelWordByte, data);
        } catch (Exception e) {
        	e.printStackTrace();
            return modelWordByte;
        }
    }


    /**
     * 填充 word 模板(map数据格式)
     *
     * @param file word二进制
     * @param data 要填充的数据
     * @return 组合数据之后的word二进制
     */
    public static byte[] fillWordDataByMap(byte[] file, Map<String, Object> data) throws Exception {
        byte[] ret = null;
        if (data == null || data.isEmpty()) {
            return ret;
        }
		long start = System.currentTimeMillis();
        try (InputStream is = new ByteArrayInputStream(file);
             ByteArrayOutputStream out = new ByteArrayOutputStream()) {
            Document doc = new Document(is);
            DocumentBuilder builder = new DocumentBuilder(doc);
            Map<String, String> toData = new HashMap<>();
            for (Map.Entry<String, Object> en : data.entrySet()) {
                String key = en.getKey();
                Object value = en.getValue();

                if (value instanceof List) {
                    //写入表数据
                    DataTable dataTable = fillListData((List) value, key, builder);
                    doc.getMailMerge().executeWithRegions(dataTable);
                }

                if (value instanceof BufferedImage) {
                    builder.moveToMergeField(key);
                    builder.insertImage((BufferedImage) value);
                }
				if (value instanceof byte[]) {
					builder.moveToMergeField(key);
					if ("signImage3".equals(key)){
						builder.insertImage((byte[]) value,60,45);
					} else {
						builder.insertImage((byte[]) value,80,60);
					}
				}

				//方框打勾
				if (CODE_TICK.equals(value)){
					builder.moveToMergeField(key);
					//设置字体
					builder.getFont().setName("Wingdings 2");
					builder.write("\uF052");
				}
				//方框
				if (CODE_BOX.equals(value)){
					builder.moveToMergeField(key);
					//设置字体
					builder.getFont().setName("Wingdings 2");
					builder.write("\uF0A3");
				}
				//为空则默认空字符串
                String valueStr = String.valueOf(en.getValue());
                if (value == null || "null".equals(value)) {
					valueStr = " ";
                }

                toData.put(key, valueStr);
            }

            String[] fieldNames = new String[toData.size()];
            String[] values = new String[toData.size()];

            int i = 0;
            for (Map.Entry<String, String> entry : toData.entrySet()) {
                fieldNames[i] = entry.getKey();
                values[i] = entry.getValue();
                i++;
            }

            //合并数据
            doc.getMailMerge().execute(fieldNames, values);
            doc.save(out, SaveOptions.createSaveOptions(SaveFormat.DOCX));
            ret = out.toByteArray();
        }
		long end = System.currentTimeMillis();
		log.info("replace docx completed, elapsed " + (end - start) / 1000.0 + " seconds!");

		return ret;
    }

    /**
     * 封装 list 数据到 word 模板中(word表格)
     *
     * @param list      数据
     * @param tableName 表格列表变量名称
     * @return word表格数据DataTable
     */
    private static DataTable fillListData(List<Object> list, String tableName, DocumentBuilder builder) throws Exception {

        //创建DataTable,并绑定字段
        DataTable dataTable = new DataTable(tableName);
        for (Object obj : list) {
            //创建DataRow,封装该行数据
            DataRow dataRow = dataTable.newRow();
            Class<?> objClass = obj.getClass();
            Field[] fields = objClass.getDeclaredFields();
            for (int i = 0; i < fields.length; i++) {
                Field field = fields[i];
                dataTable.getColumns().add(fields[i].getName());
                PropertyDescriptor pd = new PropertyDescriptor(field.getName(), objClass);
                Method method = pd.getReadMethod();
                dataRow.set(i, method.invoke(obj));
            }
            dataTable.getRows().add(dataRow);
        }
        return dataTable;
    }

    /*
     * 加载 license
     * 由于 aspose是收费的,若没有 license,则会出现水印。
     */
    static {
        try {
			AsposeLicenseUtil.setWordsLicense();
        } catch (Exception e) {
            throw new RuntimeException("自动加载aspose证书文件失败!");
        }
    }
}

图片填充有两种方式:

一种使用BufferedImage 工具类转换图片插入对应的域;

一种是使用自带的图片插入方法 DocumentBuilder.insertImage(文件流,字节等,图片的参数宽,高);注:这种方式图片会更清晰。

模板替换还可以替换特殊字符等

//设置字体
 builder.getFont().setName("Wingdings 2");


builder.write("\uF052");//打勾的方框 需要其他字符就找对应的编码就行

4.所使用的相关jar包和配置