Java - 填充Word文本域、Word转PDF操作

先看效果:

填充前:

 填充后效果:


第一步: 引入Maven坐标:

        <!-- hutool工具类 -->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>4.6.3</version>
        </dependency>

        <!--word模板数据解析-->
        <dependency>
            <groupId>com.deepoove</groupId>
            <artifactId>poi-tl</artifactId>
            <version>1.9.0-beta</version>
        </dependency>
        <!-- word/pdf操作 -->
        <dependency>
            <groupId>com.aspose</groupId>
            <artifactId>aspose-words</artifactId>
            <version>14.7.0</version>
            <scope>system</scope>
            <systemPath>${pom.basedir}/lib/aspose-words-15.8.0-jdk16.jar</systemPath>
        </dependency>

 

第二步: 工具类: 

import cn.hutool.system.OsInfo;
import cn.hutool.system.SystemUtil;
import com.aspose.words.Document;
import com.aspose.words.FontSettings;
import com.aspose.words.License;
import com.aspose.words.SaveFormat;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.exception.RenderException;
import com.deepoove.poi.policy.HackLoopTableRenderPolicy;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.util.Map;

/**
 * @author LSL
 * @version 1.0
 * @date 2022/6/22
 */
@Slf4j
public class WordUtil {

    /**
     * 填充word模板,并且转成pdf文件后返回:
     * @param datas: 填充数据
     * @param fileStream: 文件模板流 -- 可从OSS/FastDFS上获取流,直接传入;
     * @return
     * @throws IOException
     */
    public static byte[] fillWordToPDF(Map<String,Object> datas,InputStream fileStream) throws IOException {
        try {
            //先填充word:
            byte[] bytes = fillWord(datas, fileStream);

            //在word转pdf:
            return wordToPDF(new ByteArrayInputStream(bytes));
        } catch (IOException ex){
            log.error("系统异常::{}",ex);
            throw ex;
        }
    }

    /**
     * 填充word模板,获取填充后的word文件流:
     * @param datas: 填充数据
     * @param fileStream: 文件模板流 -- 可从OSS/FastDFS上获取流,直接传入;
     * @return
     * @throws IOException
     */
    public static byte[] fillWord(Map<String,Object> datas, InputStream fileStream) throws IOException {
        XWPFTemplate template = null;
        ByteArrayOutputStream wordOut = new ByteArrayOutputStream(1024);
        try {
            //设置占位符:
            Configure config = Configure.builder()
                    .buildGramer("${", "}") //设置模板中的占位符${}, 默认是{{}}
                    .setValidErrorHandler(new Configure.AbortHandler()) //若模板中占位符与填充属性不对应,则报错;
                    .bind("item", new HackLoopTableRenderPolicy()) //设置模板中表格的参数属性
                    .build();

            //填充文本域:
            template = XWPFTemplate.compile(fileStream, config).render(datas);
            template.write(wordOut);
        }catch (RenderException ex){
            log.error("模板填充失败,请保证模板文本域与参数保持一致。错误信息::{}",ex);
            throw ex;
        } catch (IOException ex){
            log.error("系统异常::{}",ex);
            throw ex;
        }finally {
            try {
                if (template != null){
                    template.close();
                }
            } catch (IOException ex) {
                log.error("关闭文件流资源异常::{}",ex);
            }
        }
        return wordOut.toByteArray();
    }

    /**
     * word转pdf
     * @param wordInStream: word文件输入流;
     */
    public static byte[] wordToPDF(InputStream wordInStream) {
        ByteArrayOutputStream byteOut = new ByteArrayOutputStream(1024);
        try {
            InputStream licenseIn = WordUtil.class.getClassLoader().getResourceAsStream("license.xml");
            License aposeLic = new License();
            aposeLic.setLicense(licenseIn);

            //因linux环境没有语言包,当项目部署到linux环境后,转成的pdf中的中文是类似乱码的,所以需要去加载此目录下的语言包;
            OsInfo osInfo = SystemUtil.getOsInfo();
            if(osInfo.isLinux()){
                //====================================== 注意 ============================================
                //注意: 需要把项目中resource/fonts目录下的语言包全部放到linux中的此目录下,否则linux环境中处理是乱码;
                //以下是我自己定义的目录,你可随意更改为你linux上的目录;
                FontSettings.setFontsFolder("/usr/share/fonts/chinese", true);
                //=======================================================================================
            }

            //Address是将要被转化的word文档
            Document doc = new Document(wordInStream);
            //全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF,
            doc.save(byteOut, SaveFormat.PDF);
        } catch (Exception e) {
            log.error("word转pdf异常::{}",e);
            throw new RuntimeException("word转pdf异常");
        }
        return byteOut.toByteArray();
    }

    /**
     * word转pdf
     * @param wordInStream: word文件输入流;
     * @param pdfOutStream: pdf文件输出流;
     */
    public static void wordToPDF(InputStream wordInStream, OutputStream pdfOutStream) {
        try {
            InputStream licenseIn = WordUtil.class.getClassLoader().getResourceAsStream("license.xml");
            License aposeLic = new License();
            aposeLic.setLicense(licenseIn);

            //因linux环境没有语言包,当项目部署到linux环境后,转成的pdf中的中文是类似乱码的,所以需要去加载此目录下的语言包;
            OsInfo osInfo = SystemUtil.getOsInfo();
            if(osInfo.isLinux()){
                //====================================== 注意 ============================================
                //注意: 需要把项目中resource/fonts目录下的语言包全部放到linux中的此目录下,否则linux环境中处理是乱码;
                //以下是我自己定义的目录,你可随意更改为你linux上的目录;
                FontSettings.setFontsFolder("/usr/share/fonts/chinese", true);
                //=======================================================================================
            }

            //Address是将要被转化的word文档
            Document doc = new Document(wordInStream);
            //全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF,
            doc.save(pdfOutStream, SaveFormat.PDF);
        } catch (Exception e) {
            log.error("word转pdf异常::{}",e);
            throw new RuntimeException("word转pdf异常");
        }
    }
}

 注: license.xml文件内容如下

<?xml version="1.0" encoding="UTF-8" ?>
<License>
	<Data>
		<Products>
			<Product>Aspose.Total for Java</Product>
			<Product>Aspose.Words for Java</Product>
		</Products>
		<EditionType>Enterprise</EditionType>
		<SubscriptionExpiry>20991231</SubscriptionExpiry>
		<LicenseExpiry>20991231</LicenseExpiry>
		<SerialNumber>8bfe198c-7f0c-4ef8-8ff0-acc3237bf0d7</SerialNumber>
	</Data>
	<Signature>sNLLKGMUdF0r8O1kKilWAGdgfs2BvJb/2Xp8p5iuDVfZXmhppo+d0Ran1P9TKdjV4ABwAgKXxJ3jcQTqE/2IRfqwnPf8itN8aFZlV3TJPYeD3yWE7IT55Gz6EijUpC7aKeoohTb4w2fpox58wWoF3SNp6sK6jDfiAUGEHYJ9pjU=</Signature>
</License>

第三步: 测试

1、word模板文件: 请按照第一张图片自行制作;

2、测试代码:填充成功后直接转成pdf文件;

    public static void main(String[] args) throws IOException {
        //数据
        Map datas = new HashMap<String,Object>();
        datas.put("dept", "采购部");
        datas.put("name", "张三");
        LocalDate date = LocalDate.now();
        datas.put("year", date.getYear());
        datas.put("month", date.getMonthValue());
        datas.put("day", date.getDayOfMonth());
        //表格(多条数据格式):
        List itemList = new ArrayList<>();
        Map itemMap = new HashMap();
        itemMap.put("goods", "笔记本电脑");
        itemMap.put("num", "2");
        itemMap.put("cost", "10000");
        itemMap.put("remark", "按需采购");
        itemList.add(itemMap);
        itemMap = new HashMap();
        itemMap.put("goods", "台式电脑");
        itemMap.put("num", "1");
        itemMap.put("cost", "8000");
        itemMap.put("remark", "按需采购");
        itemList.add(itemMap);
        datas.put("item",itemList);
        datas.put("total","10000");
        //需要填充到word中的图片数据
        ClassLoader classLoader = WordUtil.class.getClassLoader();
        BufferedImage image = ImageIO.read(classLoader.getResourceAsStream("template/image.png"));
        datas.put("image", new PictureRenderData(image.getWidth(), image.getHeight(), PictureType.PNG, image));
        //模板文件流
        InputStream tempStream = classLoader.getResourceAsStream("template/测试模板文件.docx");

        //填充word:
        byte[] bytes = WordUtil.fillWord(datas, tempStream);
        //word转pdf:
        File pdfFile = new File("生成的PDF文件" + System.currentTimeMillis() + ".pdf");
        WordUtil.wordToPDF(new ByteArrayInputStream(bytes),new FileOutputStream(pdfFile));
    }

注意:

1、word转pdf的jar包,在maven中心仓库中不存在,下载不了。在此我提供了jar包:

百度网盘: 百度网盘 请输入提取码

提取码: qk0x

Maven项目手动引入Jar包的编译、打包方式请看此篇文章: https://mp.csdn.net/mp_blog/creation/editor/125435777

 2、word转pdf时,Linux会出现中文乱码问题(window不存在);解决办法:Linux环境aspose插件word转pdf中文乱码解决方案_赵广陆的博客-CSDN博客_aspose中文乱码

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
好的,我已经理解您的问题。您可以使用Apache POI库和iText库来实现这个需求。下面是一个简单的Java代码示例: 1. 首先,您需要使用Apache POI库来创建一个Word模板文件。 ```java // 创建一个Word模板文件 XWPFDocument doc = new XWPFDocument(); XWPFParagraph p1 = doc.createParagraph(); XWPFRun r1 = p1.createRun(); r1.setText("Hello, World!"); // 将模板文件保存到本地 FileOutputStream out = new FileOutputStream("template.docx"); doc.write(out); out.close(); ``` 2. 然后,您可以使用Apache POI库来填充模板文件中的占位符。 ```java // 打开Word模板文件,并替换其中的占位符 XWPFDocument doc = new XWPFDocument(new FileInputStream("template.docx")); XWPFParagraph p1 = doc.getParagraphs().get(0); XWPFRun r1 = p1.getRuns().get(0); String text = r1.getText(0); text = text.replace("World", "Java"); r1.setText(text, 0); // 将填充后的模板文件保存到本地 FileOutputStream out = new FileOutputStream("output.docx"); doc.write(out); out.close(); ``` 3. 最后,您可以使用iText库将填充后的Word文件换为PDF文件。 ```java // 打开填充后的Word文件,并将其换为PDF文件 XWPFDocument doc = new XWPFDocument(new FileInputStream("output.docx")); PdfWriter writer = new PdfWriter("output.pdf"); PdfDocument pdf = new PdfDocument(writer); Converter.convert(doc, pdf); pdf.close(); writer.close(); ``` 注意:以上代码示例仅供参考,具体的实现方式可能会因您的具体需求而有所不同。您需要根据您的需求进行相应的修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值