Java导入导出Excel和Word

目的

实现Excel/Word导入导出,分以下步骤

  • 导入
    • 上传文件
    • 解析Excel/Word里面的内容
  • 导出
    • 生成Excel/Word文件
    • 文件下载

如何实现

  • 上传文件----------Commons FileUpload上传组件
  • Excel/Word-------Apache POI----Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能。
  • 下载文件----------ServletOutputStream直接输出文件流

简单的demo实现

首先需要这么几个jar包,红色的部分是处理文件上传需要的jar包,蓝色部分是JSTL标签库需要jar包,其他就是处理EXCEL/WORD的jar包

这里插一段遇到的问题

IDEA将WEB-INF/lib目录指定为jar目录,并且将相应的jar包复制过去,但IDEA不提示相关类

解决方案:手动重新导入,更多操作方式看这个贴 https://blog.csdn.net/gdsgdh308227363/article/details/82930321

文件上传demo

/*
 * @author MrPeng
 * @date 2019/1/29
 */
@WebServlet("/importExcel")
public class ImportExcelServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //表单上传到这个Servlet中解析
        //判断表单提交是否存在enctype="multipart/form-data"属性,也就是有文件流上传,这种表单getParameter方式是拿不到值的
        //需要导入commons-fileupload和commons-io这2个包
        if (ServletFileUpload.isMultipartContent(request)){
            //创建ServletFileUpload对象,默认配置即可
            ServletFileUpload upload =new ServletFileUpload(new DiskFileItemFactory());
            //设置编码utf-8
            upload.setHeaderEncoding("UTF-8");

            try {
                //从请求中解析出各种表单控件
                List<FileItem> fileItemList = upload.parseRequest(request);
                for (FileItem fileItem:fileItemList){
                    //判断是普通表单
                    if (fileItem.isFormField()){
                        //获取表单的name和value
                        System.out.println(fileItem.getFieldName()+':'+fileItem.getString("UTF-8"));
                    }else{
                        //说明是个文件流
                        System.out.println(fileItem.getFieldName());
                        //直接写到一个文件中--上传成功
                        fileItem.write(new File("D:/JavaWeb/ExcelWord/web/upload/"+fileItem.getName()));
                    }
                }
            } catch (FileUploadException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }else{
            //request.getParameter("")

        }
    }
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request,response);
    }
}

处理Excel解析/生成Demo

这里需要理解一下POI中的类与EXCEL之间的关系

  • Excel对象本身对应------------POI中WorkBook类
  • Excel中sheet1/2/3对应-------POI中Sheet类
  • Excel中每一行对应------------POI中Row类
  • Excel中每一个单元格---------POI中Cell类
/**处理EXCEL的类
 * @author MrPeng
 * @date 2019/1/29
 */
public class ExcelServiceDemo {

    /**
     * 解析excel
     */
    public void impDemo(){
        try {
            //通过工厂方法创建excel对象
            Workbook workbook = WorkbookFactory.create(new File("D:/JavaWeb/ExcelWord/web/upload/import_03_excel.xls"));
            //处理第一个区域默认0开始
            Sheet sheet =workbook.getSheetAt(0);
            //获取有效数据的最后行数,默认首行从0开始
            int rowNum = sheet.getLastRowNum();
            //循环遍历每一行,从第2行开始,第一行是标题
            for (int i = 1; i <=rowNum ; i++) {
                Row row= sheet.getRow(i);
                //获取每一行每个单元格的数据,默认也是从开始的,并解析成对应格式的数据
                System.out.println("姓名:"+row.getCell(0).getStringCellValue());
                System.out.println("年龄:"+row.getCell(1).getNumericCellValue());
                System.out.println("时间:"+row.getCell(2).getDateCellValue());
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InvalidFormatException e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 导出excel
     * @param isXlsx 是否导出07版  03版后缀为xls ,07版为xlsx
     * @return
     */
    public void exportDemo(boolean isXlsx) {
        Workbook workbook = null;
        if (isXlsx) {
            //创建07版excel对象 ,07版有些新特性在这个类里有实现
            workbook = new XSSFWorkbook();
        } else {
            //创建03版excel对象
            workbook = new HSSFWorkbook();
        }
        //创建工作区域sheet,自定义名字
        Sheet sheet = workbook.createSheet("My Sheet");
        //模拟假数据建一个getContent()方法获取一个二维MAP数组
        List<List<String>> content = this.getContent();
        //外层循环控制行
        for (int i = 0; i < content.size(); i++) {
            //创建一行
            Row row = sheet.createRow(i);
            List<String> rowData = content.get(i);
            //内层循环控制每个单元格
            for (int j = 0; j < rowData.size(); j++) {
                //创建单元格,并设置值
                row.createCell(j).setCellValue(rowData.get(j));
            }
        }

        FileOutputStream fileOutputStream = null;
        try {
            fileOutputStream = new FileOutputStream("D:\\JavaWeb\\ExcelWord\\web\\upload\\demo-07.xlsx");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        //先将excel对象保存到文件输出流--可以不保留文件
        //workbook.write(outputStream);//也就是直接写入ServletOutputStream输出流对象中
        try {
            workbook.write(fileOutputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                workbook.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

处理Word解析生成Demo

/**Word解析生成Demo
 * @author MrPeng
 * @date 2019/1/29
 */
public class WordServiceDemo {
    /**
     * 解析03Word, 由于03和07差异较大 实际处理策略是先用03的解析 在用07的解析
     */
    public void imp03() {
        HWPFDocument doc = null;
        //尝试03版的解析
        try {
            //创建对象--文件流方式 如果需要保存文件,则可以使用File对象创建
            doc = new HWPFDocument(new FileInputStream("D:/JavaWeb/ExcelWord/web/upload/import_03_word.doc"));
            //直接获取doc中的文本信息,如果是原样一般是转PDF
            String text = doc.getDocumentText();
            //替换成html中的换行
            text=text.replace("\r","<br/>");
            //输出解析的文本
            System.out.println(text);
        } catch (OfficeXmlFileException oe) {
            //版本可能不对
            System.out.println("这可能是一个07版的Word");
        } catch (Exception e) {
            //解析错误
            e.printStackTrace();
        } finally {
            //释放资源
            if(doc != null) {
                try {
                    doc.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 解析07版
     */
    public void imp07()
    {
        XWPFDocument docx = null;
        try {
            //创建07版Word对象--文件流方式
            docx = new XWPFDocument(new FileInputStream("D:/JavaWeb/ExcelWord/web/upload/import_07_word.doc"));
            //从每一个段落取文本--当文字出现换行符认为是一个段落
            List<XWPFParagraph> paragraphList = docx.getParagraphs();
            StringBuilder content = new StringBuilder();
            for (int i = 0; i < paragraphList.size(); i++) {
                //换行处理
                if(i != 0) {
                    content.append("<br/>");
                }
                content.append(paragraphList.get(i).getText());
            }
            //输出文本
            System.out.println(content.toString());
        } catch (IOException e) {
            //解析错误
            e.printStackTrace();
        } finally {
            if(docx != null) {
                try {
                    docx.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 导出03版Word
     * @param replaceContent--需要替换的东西k-v
     * @return
     */
    public HWPFDocument export03(Map<String,String> replaceContent) {
        HWPFDocument doc = null;
        try {
            //创建03Word对象
            doc = new HWPFDocument(new FileInputStream("D:\\JavaWeb\\ExcelWord\\web\\template\\template_03.doc"));
            //获取Word文档范围
            Range range = doc.getRange();
            //替换模板中的变量
            for(Map.Entry<String,String> entry : replaceContent.entrySet()) {
                range.replaceText(entry.getKey(),entry.getValue());
            }
        } catch (Exception e) {
            //这里不能有finally关闭doc,否则servlet不能将其写入response响应流
            return null;
        }
        //返回doc对象,可以选择像之前的excel导出处理 是否保留文件
        return doc;
    }

    /**
     * 导出07版Word
     * @param replaceContent--需要替换的东西k-v
     * @return
     */
    public XWPFDocument export07(Map<String,String> replaceContent) {
        XWPFDocument docx = null;
        try {
            //创建07版WORD对象
            docx = new XWPFDocument(new FileInputStream("D:\\JavaWeb\\ExcelWord\\web\\template\\template_07.docx"));
            //获取每一个段落
            List<XWPFParagraph> paragraphList = docx.getParagraphs();
            for(XWPFParagraph paragraph : paragraphList) {
                //07版段落还不是最小单位,遇到不同样式或者格式的文本也可能再拆分
                List<XWPFRun> runs = paragraph.getRuns();
                for(XWPFRun run : runs) {
                    //获取最小单元的文本
                    String str = run.getText(run.getTextPosition());
                    //将key替换成value
                    for(Map.Entry<String,String> entry : replaceContent.entrySet()) {
                        str = str.replace(entry.getKey(),entry.getValue());
                    }
                    //直接赋值回去
                    run.setText(str,0);
                }
            }
        } catch (IOException e) {
            return null;
        }
        return docx;
    }
}

最后附上完整代码

一个实现上诉操作的建议Web应用

链接:https://pan.baidu.com/s/1al8_ux3LF6SJtBfXz4Z4-Q
提取码:u3a6 

猜你喜欢

转载自www.cnblogs.com/phperpxy/p/10335913.html