写了一个Word和Excel读写有关的小工具,在此记录一下

一.小工具的主要功能:

  1.将Excel中的数据填充到Word模板文档中,生成多个Word文档;

  2.将多个Word文档合并成一个;

图示:

      Excel转Word:     合并Word: 

      Word模板:    Excel数据表: 

二.涉及的相关依赖

    <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.5.4</version>
        </dependency>
        <dependency>
            <groupId>com.deepoove</groupId>
            <artifactId>poi-tl</artifactId>
            <version>1.9.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>4.1.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>4.1.2</version>
        </dependency>

三.相关源码

Word读取并填充,及合并Word:

package com.example.demo;

import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.xwpf.NiceXWPFDocument;
import org.apache.poi.xwpf.usermodel.BreakType;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.List;
import java.util.Map;

/**
 * 填充word模板数据的工具类
 * @Author JCB
 * @Date  2021/1/29
 **/
public class WriteWordUtil {

    /**
     * 传入多组数据合并成一个Word导出
     * word占位用{{object}}比较完美可以填充图片
     * @param filePath
     * @param paramsList
     * @param outFilePath
     * @return
     * @throws Exception
     */
    public static String templateWrite1(String filePath, List<Map<String, Object>> paramsList, String outFilePath)throws Exception{
        NiceXWPFDocument doc = XWPFTemplate.compile(filePath).render(paramsList.get(0)).getXWPFDocument();
        for (int i = 0; i < paramsList.size(); i++) {
            XWPFTemplate template = XWPFTemplate.compile(filePath).render(paramsList.get(i));
            NiceXWPFDocument xwpfDocument = template.getXWPFDocument();
            if (i == 0) {
                continue;
            } else if (i == paramsList.size() -1) {
                doc.merge(xwpfDocument);
            } else {
                xwpfDocument.createParagraph().createRun().addBreak(BreakType.PAGE);
                doc.merge(xwpfDocument);
            }
        }
        FileOutputStream out = new FileOutputStream(outFilePath);
        doc.write(out);
        out.flush();
        out.close();
        doc.close();
        return "";
    }
    
    /**
     * 传入一组数据导出一个Word
     * word占位用{{object}}比较完美可以填充图片
     * @param filePath
     * @param params
     * @param outFilePath
     * @return
     * @throws Exception
     */
    public static String templateWrite2(String filePath, Map<String, Object> params,String outFilePath)throws Exception{
        XWPFTemplate template = XWPFTemplate.compile(filePath).render(params);
        FileOutputStream out = new FileOutputStream(outFilePath);
        template.write(out);
        out.flush();
        out.close();
        template.close();
        return "";
    }

    /**
     * 合并多个Word文档
     * @Author JCB
     * @Date  2021/2/4
     **/
    public static void mergeWord(List<String> fileList, String outFilePath) throws Exception{
        //新文档的地址
        FileOutputStream out = new FileOutputStream(outFilePath);
        //合并并输出
        NiceXWPFDocument mainDoc = new NiceXWPFDocument(new FileInputStream(fileList.get(0).trim()));
        for (int i = 1; i < fileList.size(); i++) {
            NiceXWPFDocument subDoc = new NiceXWPFDocument(new FileInputStream(fileList.get(i).trim()));
            mainDoc = mainDoc.merge(subDoc);
        }
        mainDoc.write(out);
        mainDoc.close();
        out.close();
    }
}

创建窗口:

package com.example.demo;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.filechooser.FileSystemView;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
//@SpringBootApplication
public class JNUtil extends JFrame{
    private static final long serialVersionUID = 8162801603108721756L;

    private JPanel contentPane;
    private JPanel contentPane1;
    private JPanel contentPane2;

    private JTextField textField1;
    private JTextField textField2;
    private JTextField textField3;
    private JTextField textField4;
    private JTextField textField5;
    private JTextField textField6;
    private JTextField textField7;

    private JLabel label1;
    private JLabel label2;
    private JLabel label3;
    private JLabel jokeLabel1;
    private JLabel jokeLabel2;

    private JButton  jb1;
    private JButton  jb2;
    private JButton  jb3;
    private JButton  jb4;
    private JButton  jb5;

    private CardLayout card;

    public static void main(String[] args){
        try {
            UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");// 设置程序外观的风格
        } catch (Throwable e) {
            // TODO: handle exception
            e.printStackTrace();
        }

        EventQueue.invokeLater(new Runnable(){

            @Override
            public void run() {
                // TODO Auto-generated method stub
                try {
                    JNUtil frame = new JNUtil();// 设置窗体
                    frame.setVisible(true);// 设置可见
                }catch (Exception e) {
                    // TODO: handle exception
                    e.printStackTrace();
                }
            }
        });
    }

    public JNUtil(){
        setTitle("JN小工具");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(500, 400, 400, 300);
        setIconImage(new ImageIcon("./13.png").getImage());

        contentPane = new JPanel();// 创建全局内容面板
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));// 设置边框大小
        setContentPane(contentPane);// 应用全局内容面板
        card = new CardLayout();
        contentPane.setLayout(card);

        //菜单栏
        JMenuBar jMenuBar = new JMenuBar();
        setJMenuBar(jMenuBar);
        //一级菜单
        JMenu jMenu1 = new JMenu("功能选择");
        JMenu jMenu2 = new JMenu("帮助");
        jMenuBar.add(jMenu1);
        jMenuBar.add(jMenu2);
        //子菜单
        JMenuItem jMenuItem1 = new JMenuItem("Excel转Word");
        JMenuItem jMenuItem2 = new JMenuItem("合并Word");
        jMenu1.add(jMenuItem1);
        jMenu1.add(jMenuItem2);
        JMenuItem jMenuItem3 = new JMenuItem("说明");
        jMenu2.add(jMenuItem3);

        //卡片设置
        contentPane1 = new JPanel();
        contentPane1.setLayout(new GridLayout(7,1,0,0));
        contentPane.add("card1",contentPane1);
        contentPane2 = new JPanel();
        contentPane2.setLayout(new BorderLayout());
        contentPane.add("card2",contentPane2);
        card.show(contentPane,"card1");

        /**
         * 卡片1功能区
         * */
        //*******文件选择区*******
        JPanel pannel1 = new JPanel();
        contentPane1.add(pannel1);
        label1 = new JLabel(" Word模板路径:");
        pannel1.add(label1);
        textField1 = new JTextField();

        // 应用文本框
        pannel1.add(textField1);
        // 将文本框设置成18列
        textField1.setColumns(18);
        // 是否设置成文本框不可编辑
        // textField1.setEnabled(false);

        jb1 = new JButton("选择文件");
        jb1.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //按钮点击事件
                JFileChooser chooser = new JFileChooser();             //设置选择器
                chooser.setMultiSelectionEnabled(false);             //是否设为多选
                FileSystemView fsv = FileSystemView.getFileSystemView();  //注意了,这里重要的一句
                chooser.setCurrentDirectory(fsv.getHomeDirectory());
                int returnVal = chooser.showOpenDialog(jb1);        //是否打开文件选择框
                if (returnVal == JFileChooser.APPROVE_OPTION) {          //如果符合文件类型
                    String filepath = chooser.getSelectedFile().getAbsolutePath();      //获取绝对路径
                    textField1.setText(filepath);
                }
            }
        });
        pannel1.add(jb1);

        JPanel pannel2 = new JPanel();
        contentPane1.add(pannel2);
        label2 = new JLabel("Excel数据路径:");
        pannel2.add(label2);
        textField2 = new JTextField();
        pannel2.add(textField2);
        textField2.setColumns(18);

        jb2 = new JButton("选择文件");
        jb2.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //按钮点击事件
                JFileChooser chooser = new JFileChooser();             //设置选择器
                chooser.setMultiSelectionEnabled(false);             //是否设为多选
                FileSystemView fsv = FileSystemView.getFileSystemView();  //注意了,这里重要的一句
                chooser.setCurrentDirectory(fsv.getHomeDirectory());
                int returnVal = chooser.showOpenDialog(jb2);        //是否打开文件选择框
                if (returnVal == JFileChooser.APPROVE_OPTION) {          //如果符合文件类型
                    String filepath = chooser.getSelectedFile().getAbsolutePath();      //获取绝对路径
                    textField2.setText(filepath);
                }
            }
        });
        pannel2.add(jb2);

        JPanel pannel3 = new JPanel();
        contentPane1.add(pannel3);
        label3 = new JLabel(" 目标文件目录:");
        pannel3.add(label3);
        textField3 = new JTextField();
        pannel3.add(textField3);
        textField3.setColumns(18);

        jb3 = new JButton("选择目录");
        jb3.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //按钮点击事件
                JFileChooser chooser = new JFileChooser();             //设置选择器
                FileSystemView fsv = FileSystemView.getFileSystemView();  //注意了,这里重要的一句
                chooser.setCurrentDirectory(fsv.getHomeDirectory());
                chooser.setDialogTitle("请选择要上传的文件...");
                chooser.setApproveButtonText("确定");
                chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
                int result = chooser.showOpenDialog(jb3);
                if (JFileChooser.APPROVE_OPTION == result) {
                    String filepath = chooser.getSelectedFile().getPath();
                    textField3.setText(filepath);
                }
            }
        });
        pannel3.add(jb3);

        //*******Excel参数设置区*******
        JPanel pannel4 = new JPanel();
        contentPane1.add(pannel4);
        JLabel label4 = new JLabel("工作表名称:");
        pannel4.add(label4);
        textField4 = new JTextField();
        pannel4.add(textField4);
        textField4.setColumns(10);
        JLabel label5 = new JLabel("数据标题行:");
        pannel4.add(label5);
        textField5 = new JTextField();
        pannel4.add(textField5);
        textField5.setColumns(10);

        JPanel pannel5 = new JPanel();
        contentPane1.add(pannel5);
        JLabel label6 = new JLabel("数据起始行:");
        pannel5.add(label6);
        textField6 = new JTextField();
        pannel5.add(textField6);
        textField6.setColumns(10);
        JLabel label7 = new JLabel("数据结束行:");
        pannel5.add(label7);
        textField7 = new JTextField();
        pannel5.add(textField7);
        textField7.setColumns(10);

        //*******执行转换区*******
        JPanel buttonJP = new JPanel();
        jb4 = new JButton("开始");
        jb5 = new JButton("重置");
        buttonJP.add(jb4);
        buttonJP.add(jb5);
        contentPane1.add(buttonJP);
        jb4.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //按钮点击事件
                //读取参数,并校验
                String wordTemplatePath = textField1.getText();
                if (StrUtil.isBlank(wordTemplatePath) || !wordTemplatePath.endsWith(".docx")) {
                    JOptionPane.showMessageDialog(null, "请选择正确的Word模板文件!", "警告", JOptionPane.WARNING_MESSAGE);
                    return;
                }
                String excelDataPath = textField2.getText();
                if (StrUtil.isBlank(excelDataPath) || !excelDataPath.endsWith(".xlsx")) {
                    JOptionPane.showMessageDialog(null, "请选择正确的Excel数据文件!", "警告", JOptionPane.WARNING_MESSAGE);
                    return;
                }
                String wordTargetPath = textField3.getText();
                if (StrUtil.isBlank(wordTargetPath)) {
                    wordTargetPath = "C:/Users/Administrator/Desktop";
                }
                String excelSheetName = textField4.getText();
                if (StrUtil.isBlank(excelSheetName)) {
                    JOptionPane.showMessageDialog(null, "请正确填写工作表名称!", "警告", JOptionPane.WARNING_MESSAGE);
                    return;
                }
                Integer excelHeaderRow = Integer.valueOf(textField5.getText()) - 1;
                if (excelHeaderRow == null || excelHeaderRow < 0) {
                    JOptionPane.showMessageDialog(null, "请正确填写数据的标题行数!", "警告", JOptionPane.WARNING_MESSAGE);
                    return;
                }
                Integer excelStartRow = Integer.valueOf(textField6.getText()) - 1;
                if (excelStartRow == null || excelStartRow < 0) {
                    JOptionPane.showMessageDialog(null, "请正确填写数据的起始行数!", "警告", JOptionPane.WARNING_MESSAGE);
                    return;
                }
                Integer excelEndRow = Integer.valueOf(textField7.getText()) - 1;
                if (excelStartRow == null || excelStartRow < 0) {
                    JOptionPane.showMessageDialog(null, "请正确填写数据的结束行数!", "警告", JOptionPane.WARNING_MESSAGE);
                    return;
                }
                if (excelStartRow > excelEndRow) {
                    JOptionPane.showMessageDialog(null, "兄弟!起始行数不得大于结束行数!", "警告", JOptionPane.WARNING_MESSAGE);
                    return;
                }
                //开始转换
                String msg = "准备导出到目标文件夹,可能需要点时间,请耐心等待...点击确定开始导出";
                int flag = JOptionPane.showConfirmDialog(null, msg, "提示信息", JOptionPane.PLAIN_MESSAGE);
                if (flag == -1) {
                    return;
                }
                boolean relust = startExrcute(wordTemplatePath, excelDataPath, wordTargetPath, excelSheetName, excelHeaderRow, excelStartRow, excelEndRow);
                msg = "导出失败!";
                if (relust) {
                    msg = "导出完成!";
                }
                JOptionPane.showMessageDialog(null, msg, "提示信息", JOptionPane.PLAIN_MESSAGE);
            }
        });
        jb5.addActionListener(e -> {
            cleanText1();
        });

        //笑话区
        JPanel jokeJP1 = new JPanel();
        JPanel jokeJP2 = new JPanel();
        jokeLabel1 = new JLabel(JokeUtil.getJoke());
        jokeLabel2 = new JLabel(JokeUtil.getJoke());
        jokeJP1.add(jokeLabel1);
        jokeJP2.add(jokeLabel2);
        contentPane1.add(jokeJP1);
        contentPane2.add(jokeJP2,BorderLayout.SOUTH);
        jokeLabel1.addMouseListener(new MouseListener() {
            @Override
            public void mouseClicked(MouseEvent e) {
                jokeLabel1.setText(JokeUtil.getJoke());
            }
            @Override
            public void mousePressed(MouseEvent e) {}
            @Override
            public void mouseReleased(MouseEvent e) {}
            @Override
            public void mouseEntered(MouseEvent e) {}
            @Override
            public void mouseExited(MouseEvent e) {}
        });
        jokeLabel2.addMouseListener(new MouseListener() {
            @Override
            public void mouseClicked(MouseEvent e) {
                jokeLabel2.setText(JokeUtil.getJoke());
            }
            @Override
            public void mousePressed(MouseEvent e) {}
            @Override
            public void mouseReleased(MouseEvent e) {}
            @Override
            public void mouseEntered(MouseEvent e) {}
            @Override
            public void mouseExited(MouseEvent e) {}
        });

        /**
         * 卡片2功能区
         * */
        JPanel jPanel = new JPanel();
        JTextArea jTextArea = new JTextArea(9,35);
        jTextArea.setLineWrap(true);
        //定义带滚动条的panel,并将JTextArea存入到panel中,使textarea具有滚动条显示功能。
        JScrollPane scrollpane = new JScrollPane(jTextArea);
        //取消显示水平滚动条
        scrollpane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        //显示垂直滚动条
        scrollpane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
        jPanel.add(scrollpane);
        contentPane2.add(jPanel,BorderLayout.CENTER);
        //选择文件按钮
        JButton jButton1 = new JButton("选择文件");
        jButton1.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //按钮点击事件
                JFileChooser chooser = new JFileChooser();             //设置选择器
                chooser.setMultiSelectionEnabled(true);             //是否设为多选
                FileSystemView fsv = FileSystemView.getFileSystemView();  //注意了,这里重要的一句
                chooser.setCurrentDirectory(fsv.getHomeDirectory());
                int returnVal = chooser.showOpenDialog(jButton1);        //是否打开文件选择框
                if (returnVal == JFileChooser.APPROVE_OPTION) {          //如果符合文件类型
                    File[] selectedFiles = chooser.getSelectedFiles();
                    jTextArea.setText(Arrays.toString(selectedFiles).replace("[","").replace("]",""));
                }
            }
        });
        //开始合并按钮
        JButton jButton2 = new JButton("开始合并");
        jButton2.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //按钮点击事件
                //读取参数,并校验
                String wordPath = jTextArea.getText();
                if (StrUtil.isBlank(wordPath)) {
                    JOptionPane.showMessageDialog(null, "请选择需要合并的Word文件!", "警告", JOptionPane.WARNING_MESSAGE);
                    return;
                }
                //开始转换
                String msg = "准备合并文件到桌面,可能需要点时间,请耐心等待...点击确定开始合并";
                int flag = JOptionPane.showConfirmDialog(null, msg, "提示信息", JOptionPane.PLAIN_MESSAGE);
                if (flag == -1) {
                    return;
                }
                //需要合并的文件
                String[] split = wordPath.split(",");
                List<String> wordList = Arrays.asList(split);
                if (wordList.size() < 2) {
                    JOptionPane.showMessageDialog(null,"兄弟!别逗我!一个文件咋合并呢!");
                    return;
                }
                boolean relust = startMerge(wordList);
                msg = "导出失败!";
                if (relust) {
                    msg = "导出完成!";
                }
                JOptionPane.showMessageDialog(null, msg, "提示信息", JOptionPane.PLAIN_MESSAGE);
            }
        });
        //清空文本框按钮
        JButton jButton3 = new JButton("清空文本框");
        jButton3.addActionListener(e -> jTextArea.setText(""));
        JPanel butoonJP = new JPanel();
        butoonJP.add(jButton1);
        butoonJP.add(jButton2);
        butoonJP.add(jButton3);
        contentPane2.add(butoonJP,BorderLayout.NORTH);

        //菜单栏事件添加
        jMenuItem1.addActionListener(e -> {
            card.show(contentPane,"card1");
            jTextArea.setText("");
        });
        jMenuItem2.addActionListener(e -> {
            card.show(contentPane,"card2");
            cleanText1();
        });
        jMenuItem3.addActionListener(e -> {
            try {
                Desktop.getDesktop().open(FileUtil.file("./说明.txt"));
            } catch (Exception exception) {
                JOptionPane.showMessageDialog(null,"打开说明出错啦!","ERROR",JOptionPane.ERROR_MESSAGE);
                exception.printStackTrace();
            }
        });
    }

    /**
     * 清空界面1文本框
     * @Author JCB
     * @Date  2021/2/6
     **/
    private void cleanText1() {
        textField1.setText("");
        textField2.setText("");
        textField3.setText("");
        textField4.setText("");
        textField5.setText("");
        textField6.setText("");
        textField7.setText("");
    }

    /**
     * 开始合并数据
     * @Author JCB
     * @Date  2021/2/5
     **/
    private static boolean startMerge(List<String> wordList){
        //目标文件位置
        String wordTargetPath = "C:/Users/Administrator/Desktop" + "/" + IdUtil.simpleUUID() + ".docx";
        try {
            WriteWordUtil.mergeWord(wordList, wordTargetPath);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 开始导出数据
     * @Author JCB
     * @Date  2021/2/4
     **/
    private static boolean startExrcute(String wordTemplatePath, String excelDataPath, String wordTargetPath, String excelSheetName, int excelHeaderRow, int excelStartRow, int excelEndRow){
        //读取Excel数据文件
        ExcelReader dataReader = ExcelUtil.getReader(FileUtil.file(excelDataPath), excelSheetName);
        List<Map<String, Object>> dataList = dataReader.read(excelHeaderRow, excelStartRow, excelEndRow);
        System.out.println("dataList = " + dataList.toString());

        //导入word模板,输出目标word
        if(!FileUtil.exist(wordTargetPath)) {
            FileUtil.mkdir(wordTargetPath);
        }
        try {
            for (Map<String, Object> params : dataList) {
                WriteWordUtil.templateWrite2(wordTemplatePath, params, wordTargetPath + "/" + params.get("文档名") + ".docx");
            }
            return true;
        } catch (Exception e) {
            return false;
        }
    }
}

本工具主要涉及到POI对Word和Excel读写的知识,及相关swing组件的知识.

代码完成之后将其打包,用exe4j生成exe文件即可.

原文地址:https://www.cnblogs.com/jcb1991/p/14382331.html