• 写了一个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文件即可.

  • 相关阅读:
    CF Round #427 (Div. 2) C. Star sky [dp]
    顺时针打印矩阵
    堆 栈-相关知识【转】
    二叉树的镜像
    树的子结构
    合并两个排序的链表
    数值的整数次方
    位运算:二进制中1的个数
    斐波那契数列及其变形
    重建二叉树
  • 原文地址:https://www.cnblogs.com/jcb1991/p/14382331.html
Copyright © 2020-2023  润新知