一.小工具的主要功能:
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文件即可.