Excel导入导出与解析


​ 本文采用Apache的 POI相关API,实现对Excel和Word的文档的解析。

Apache POI 是用Java编写的免费开源的 Java API,提供对Microsoft Office格式档案读和写的功能,下载和帮助

​ 除了Apache POI外,Docx4j 也是一个用于创建和操作Microsoft Open XML (Word docx、Powerpoint pptx和Excel xlsx)文件的Java库。

  • HSSF - 提供读写Microsoft Excel XLS格式档案的功能。
  • XSSF - 提供读写Microsoft Excel OOXML XLSX格式档案的功能。
  • HWPF - 提供读写Microsoft Word DOC格式档案的功能。
  • HSLF - 提供读写Microsoft PowerPoint格式档案的功能。

使用到的 jar包:

  1. commons-fileupload-1.3.3.jar
  2. poi-3.16.jar
  3. poi-ooxml-3.16.jar
  4. poi-ooxml-schemas-3.16.jar
  5. poi-scratchpad-3.16.jar

一、JSP配置${basePath}

​ 新建common.jsp文件,在该文件中获取当前JSP的地址bsthPath,并把它存入request中,在web.xml中添加配置,使其作用域每一个JSP文件中,这样在当前工程的所有JSP中都可以使用**EL表达式${basePath}**表示当前工程地址,方便JSP页面地址的跳转。

1、common.jsp文件
<%
    String basePath = request.getScheme() + "://" + request.getServerName() + ":"
            + request.getServerPort() + request.getContextPath();
    request.setAttribute("basePath", basePath);
%>
2、web.xml配置
<jsp-config>
    <jsp-property-group>
        <url-pattern>*.jsp</url-pattern>
        <include-prelude>/WEB-INF/JSP/common.jsp</include-prelude>
    </jsp-property-group>
</jsp-config>

二、通用数据类和工具类

1、request参数解析结果类(通用数据类)

​ 该类存放request流中的Form表单提交的数据。

public class ParamDto {
    private Map<String, String> paramMap;  // 普通参数
    private Map<String, FileItem> fileMap; // 文件参数

    public ParamDto() {
        paramMap = new HashMap<>();
        fileMap = new HashMap<>();
    }

    public Map<String, String> getParamMap() {return paramMap;}
    public void setParamMap(Map<String, String> paramMap) {this.paramMap = paramMap;}

    public Map<String, FileItem> getFileMap() {return fileMap;}
    public void setFileMap(Map<String, FileItem> fileMap) {this.fileMap = fileMap;}
}
2、request参数解析工具类

​ 从request流中解析出JSP页面中Form表单提交的参数,将普通参数存入Map<String, String> 映射内,将文件参数参数存入Map<String, FileItem> 内。

public class RequestUtil {
    public static ParamDto parseParam(HttpServletRequest request) {
        ParamDto result = new ParamDto();  //结果存放类
		// 核心解析类
        ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());
        upload.setHeaderEncoding("UTF-8");
        try {
            List<FileItem> fileItemList = upload.parseRequest(request);
            for (FileItem fileItem : fileItemList) {
                if (fileItem.isFormField()) {
                    // 将普通参数放置到参数传递类的映射paramMap中
                    result.getParamMap().put(fileItem.getFieldName(), fileItem.getString("UTF-8"));
                } else {
                    // 将文件参数放置到参数传递类的映射fileMap中
                    result.getFileMap().put(fileItem.getFieldName(), fileItem);
                }
            }
        } catch (FileUploadException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
}
3、文件保存工具类

​ 为了避免用户上传同名文件,这里采用加时间戳的方法重命名,当然也可以采用UUID的方式。文件的保存使用 FileItem 的Write方法

public class FileUtil {
    public static final String SAVE_PATH = "C:/Users/Administrator/Desktop/";

    public static String save(FileItem fileItem,String path) throws Exception {
        String fileName = System.currentTimeMillis() + "_" + fileItem.getName();
        fileItem.write(new File(path + fileName));
        return fileName;
    }
}

三、Excel的导入与解析

​ 实现将Excel文件上传到Web服务器的指定地址,解析该Excel文件并显示到浏览器。

1、业务界面 JSP
<form id="mainForm" method="post" enctype="multipart/form-data" action="${basePath}/importExcel">
	...
    <input type="button" class="tabSub" value="导     入"
	onclick="document.getElementById('mainForm').submit();" />
    ...
</form>

在这里插入图片描述

2、业务参数类

​ 存放上面JSP传递过来的参数。具体是由request解析数据到通用数据类,再从通用数据类存放到导入Excel的参数类,便于管理和明确各类的功能。

public class ImportExcelParamDto {
    private String title;
    private FileItem excel;

    public String getTitle() {return title;}
    public void setTitle(String title) {this.title = title;}

    public FileItem getExcel() {return excel;}
    public void setExcel(FileItem excel) {this.excel = excel;}
}
3、业务结果类

​ 此类是对业务处理后,结果数据的封装。

public class ImportExcelResultDto {
    private String title;  // Form表单提交的数据
    private List<Student> studentList;  // Excel解析的数据
    private String msg;  // 存放错误信息

    public String getTitle() {return title;}
    public void setTitle(String title) {this.title = title;}

    public List<Student> getStudentList() {return studentList;}
    public void setStudentList(List<Student> studentList) {this.studentList = studentList;}

    public String getMsg() {return msg;}
    public void setMsg(String msg) {this.msg = msg;}
}
4、业务实现类

​ 根据提供业务参数:业务参数对象,实现 保存指定导入的Excel文件到服务器,和解析Excel文件,将解析结果存入业务结果对象中,用于返回 。

public class ExcelService {  
	public ImportExcelResultDto importExcelService(ImportExcelParamDto dto) {
        // 创建导入Excel解析结果对象
        ImportExcelResultDto result = new ImportExcelResultDto();
        result.setTitle(dto.getTitle());
        List<Student> studentList = new ArrayList<>();
        result.setStudentList(studentList);
        // 保存上传文件
        String fileName = null;
        try {
            fileName = FileUtil.save(dto.getExcel(), FileUtil.SAVE_PATH);
        } catch (Exception e) {
            result.setMsg("保存上传文件失败啦!");
        }

        // 正确到获取文件名,就可以解析Excel啦
        if (null != fileName) {
            Workbook workbook = null;
            try {
                /* 可以直接传入文件流,这样用于浏览器只要求解析文件,不需要在服务器上进行保存的场景
                workbook = WorkbookFactory.create(new File(dto.getExcel().getInputStream());*/
                // 根据文件对象实例化工作簿
                workbook = WorkbookFactory.create(new File(FileUtil.SAVE_PATH + fileName));
                // 获取Excel中第0张表单, 或使用workbook.getSheet("Sheet1");拿到对应名字的表单
                Sheet sheet = workbook.getSheetAt(0);
                // 取得表单中有内容的总行数
                int rowNum = sheet.getLastRowNum();
                // 循环遍历每一行
                for (int i = 1; i <= rowNum; i++) {
                    Row row = sheet.getRow(i);  //获取第i行
                    Student student = new Student();
                    studentList.add(student);
                    // 以字符串方式获取该行第0列元素
                    student.setName(row.getCell(0).getStringCellValue());
                    // 以数字(double)方式获取该行第0列元素
                    student.setAge((int)row.getCell(1).getNumericCellValue());
                    // 以日期(Date)方式获取该行第0列元素
                    student.setTime(row.getCell(2).getDateCellValue());
                }
            } catch (Exception e) {
                result.setMsg("解析Excel文件失败啦!");
            } finally {  // 这里一定要处理把workbook关闭掉,避免占用资源
                if (workbook != null) {
                    try {
                        workbook.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return result;
    }
}
5、业务Servlet

​ 对以上实现的方法进行调用,实现业务逻辑,将结果数据返回给显示的JSP。

public class ImportExcelServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 判断表单提交的enctype属性,需要“multipart/form-data”类型
        if (ServletFileUpload.isMultipartContent(request)) {
            // 解析request,转化为业务参数对象
            ParamDto dto = RequestUtil.parseParam(request);
            ImportExcelParamDto paramDto = new ImportExcelParamDto();
            paramDto.setTitle(dto.getParamMap().get("title"));
            paramDto.setExcel(dto.getFileMap().get("excel"));   
            // 实现业务逻辑,将结果数据存放到request中,返给JSP
            ExcelService service = new ExcelService();
            ImportExcelResultDto resultDto = service.importExcelService(paramDto);
            request.setAttribute("result", resultDto);
        } 
        // 转发给JSP,显示数据
        request.getRequestDispatcher("/WEB-INF/JSP/importExcelResult.jsp").forward(request, response);
    }
}
6、JSP展示业务数据

​ 使用EL表达式JSTL协助展示数据。

<head>
	<script type="text/javascript">
		function bodyInit() {    // 当有错误信息,显示错误信息
			if('${result.msg}') {
				alert('${result.msg}');
			}
		}
	</script>
</head>
<body style="background: #e1e9eb;" onload="bodyInit();">
    <table class="tab1">
        ...
        <td>${result.title}</td>
        <c:forEach items="${result.studentList}" var="item" varStatus="s">
            <tr>
                <td>${s.count}</td>
                <td>${item.name}</td>
                <td>${item.age}</td>
                <!-- fmt JSTL中的格式化标签 -->
                <td><fmt:formatDate value="${item.time}" pattern="yyyy-MM-dd"/></td>
            </tr>
        </c:forEach>
        ...
    </table>
	...
</body>

在这里插入图片描述

四、Excel的导出与解析

1、业务界面 JSP
<form action="${basePath}/exportExcel" id="mainForm" method="post">
    ...
	<input type="button" class="tabSub" value="查询" onclick="" />
    &nbsp;&nbsp;&nbsp;&nbsp;
	<input type="button" class="tabSub" value="导出" onclick="document.getElementById('mainForm').submit();" />
    ...
</form>

在这里插入图片描述

2、业务实现类

​ 业务参数类与导入时一致,注意将数据封装成二维的形式,方便于数据写入Excel.

导出Excel可向外留接口选择导出03版的还是07版的。

public class ExcelService {
    public Workbook exportExcel(boolean isXlsx) {
        Workbook workbook = null;
        if (isXlsx) {
            workbook = new XSSFWorkbook();  // 03版的Excel .xls
        } else {
            workbook = new HSSFWorkbook();  // 07版的Excel  .xlsx
        }

        // 创建一张表单  名称:My Sheet
        Sheet sheet = workbook.createSheet("My Sheet");
		
        // 逐个遍历写入到对应的单元格
        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));
            }
        }
        return workbook;
    }
}
3、业务Servlet

​ 导出时一般不再服务器上备份Excel文件,如果需要也可以。

​ 此Servlet没有跳转到重定向到其他界面,点击导出时的执行浏览器直接下载export.xlsx文件。

public class ExportExcelServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        ExcelService service = new ExcelService();
        Workbook workbook = service.exportExcel(true);
		// 这个信息头告诉浏览器这个文件的名字和类型
        response.setHeader("Content-Disposition", "attachment;filename=export.xlsx");

        ServletOutputStream outputStream = response.getOutputStream();
        // 输出流直接导出
        workbook.write(outputStream);
        outputStream.flush();
        outputStream.close();
        workbook.close();

//        // 保存成文件再导出
//        // 1. 先保存成文件
//        FileOutputStream fileOutputStream = new FileOutputStream(SAVE_PATH + "export.xlsx");
//        workbook.write(fileOutputStream);
//        // 2. 再由文件导出
//        FileInputStream fileInputStream = new FileInputStream(FileUtil.SAVE_PATH + "export.xlsx");
//        byte[] bytes = new byte[fileInputStream.available()];
//        fileInputStream.read(bytes);
//        outputStream.write(bytes);
//        outputStream.flush();
//
//        // 3. 关闭流
//        outputStream.close();
//        fileInputStream.close();
//        fileOutputStream.close();
//        workbook.close();
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值