前言

最近在做一个小项目,有个模块的功能涉及到excel的导入导出,并且要求对导出的excel文件部分列和单元格设置为只读不可更改,在网上到处查找了一番资料,结合自己的想法,发现也并不难,这里整理记录一下,给有相同想法和有这个需求的朋友们做个参考。

正文

java导出excel文件用的最多的就用poi的方式,这里也一样。POI 提供了对2003版本的Excel的支持 ---- HSSFWorkbook,可用于生成.xls。POI 提供了对2007版本以及更高版本的支持 ---- XSSFWorkbook ,可生成.xlsx后缀的excel文件。

导出的大致的思路,先从数据库查询出要导出的数据,这些数据可以放入一个List<bean>集合中,然后把数据按一定顺序写入excel的文件中,再对写入的数据到excel单元格进行样式设置,再以流的形式传给前端。大概流程就是上面描述的这样,细节还是在于对创建单元格写入数据后的格式进行设置为只读 (其目的就是为了规范化用户的操作,防止误改)

我的处理方式是这样的:为方便和规范用户的使用,在项目里就先创建一个excel的模板,设置两行标题,第一行标题用中文,第二行标题用英文(设置英文的目的是可以用java反射来按字段的方式以便导入导出功能的编写),并将这两行标题设置为锁定,和保护,出这两行外的单元格不锁定,等在写入数据后再根据需要进行是否锁定,在获取数据库的数据后,先对模板文件进行复制,再把数据写入模板的复制文件中,最后再把复制文件以输出流的形式传给前端,再删除复制文件。excel模板文件的手动锁定保护在文章结尾给出。

1.先添加poi的依赖

<dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>4.1.2</version>
        </dependency>

2.service层,调用自己写的ExcelUtil类的exportExcel静态方法

/**
     * excel导出,导出当天最新的项目信息,这里提供给controller层调用
     * @param request
     * @param response
     * @return
     */
    @Override
    @RequestMapping(method = RequestMethod.GET)
    @ResponseBody
    public String exportExcelMethod(HttpServletRequest request, HttpServletResponse response) {
        //这里的List<bean>就是你的数据库取出对应的数据,这里有些不方便展示就以此代指了
        List<Bean> ucmList = getBeanList();
        try {
            ExcelUtil.exportExcel(ucmList, response);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "导出成功!";
    }

3.ExcelUtil类的exportExcel静态方法:功能先复制模板一份(不对模板进行操作),然后操作复制体的模板文件,对其进行数据写入,单元格的锁定和解锁设置,再通过流发送给前端,发送完后删除复制体模板文件。

public static void exportExcel(List<Bean> ucmBoList, HttpServletResponse response) {
        String templatePath = System.getProperty("user.dir") + File.separator + "report/exceltemplate/";
        String templateName = "template.xlsx";
        String templatePathAndName = templatePath + templateName;
        File templateFile = new File(templatePathAndName);
        File copyFile = null;
        if (templateFile != null && templateFile.exists()) {
            copyFile = copyExcelTemplateByXSSF(templatePath, templateName);
        } else {
            return;
        }

        if (copyFile != null && copyFile.exists()) {
            //创建一个工作簿
            XSSFWorkbook xssfWorkbook = null;
            //创建工作表
            XSSFSheet xssfSheet = null;
            XSSFCellStyle lockCellStyle = null;
            XSSFCellStyle unLockCellStyle = null;
            try {
                xssfWorkbook = new XSSFWorkbook(copyFile);
                // xssfSheet = xssfWorkbook.createSheet();
                //这里是用自己已创建好的模板,所以就是getSheet(index)
                xssfSheet = xssfWorkbook.getSheetAt(0);
                //创建单元格
                XSSFCell xssfCell;
                //创建单元格样式,这里设置是否锁定
                lockCellStyle = xssfWorkbook.createCellStyle();
                lockCellStyle.setLocked(true);
                //创建单元格样式,这里设置不锁定
                unLockCellStyle = xssfWorkbook.createCellStyle();
                unLockCellStyle.setLocked(false);

                if (ucmBoList != null && ucmBoList.size() > 0) {

                    for (int i = 0; i < ucmBoList.size(); i++) {
                        UcmBean ucm = ucmBoList.get(i);
                        //细节,前两行为标题
                        XSSFRow xssfRow = xssfSheet.createRow(i + 2);

                        //录入日期
                        XSSFCell cell0 = xssfRow.createCell(0);
                        cell0.setCellValue(ucm.getOcDate());

                        //业务部门
                        XSSFCell cell1 = xssfRow.createCell(1);
                        cell1.setCellValue(ucm.getBusinessUnit());

                        //项目类别编号
                        XSSFCell cell2 = xssfRow.createCell(2);
                        cell2.setCellValue(ucm.getProjectTypeCode());

                        //项目类别名称
                        XSSFCell cell3 = xssfRow.createCell(3);
                        cell3.setCellValue(ucm.getProjectTypeName());

                        //项目编号
                        XSSFCell cell4 = xssfRow.createCell(4);
                        cell4.setCellValue(ucm.getProjectNo());

                        //项目名称
                        XSSFCell cell5 = xssfRow.createCell(5);
                        cell5.setCellValue(ucm.getProjectName());

                        //项目评级
                        XSSFCell cell6 = xssfRow.createCell(6);
                        cell6.setCellValue(ucm.getProjectRating());

                        //融资主体
                        List<FinancierBO> financierBOList = ucm.getFinancierInfo();
                        String finName = "", finCode = "", finRating = "";
                        if (financierBOList != null && financierBOList.size() > 0) {
                            for (FinancierBO financierBO : financierBOList) {
                                if (financierBO != null) {
                                    if (financierBO.getName() != null) {
                                        finName = finName + financierBO.getName() + "\n";
                                    } else {
                                        finName = finName + "" + "\n";
                                    }
                                    if (financierBO.getUniformCreditCode() != null) {
                                        finCode = finCode + financierBO.getUniformCreditCode() + "\n";
                                    } else {
                                        finCode = finCode + "" + "\n";
                                    }
                                    if (financierBO.getRating() != null) {
                                        finRating = finRating + financierBO.getRating() + "\n";
                                    } else {
                                        finRating = finRating + "" + "\n";
                                    }
                                }
                            }
                        }
                }
                //是否体系内业务
                        XSSFCell cell7 = xssfRow.createCell(7);
                        cell7.setCellStyle(unLockCellStyle);
                        if (ucm.getSystemBusinessFlag() != null) {
                            if (ucm.getSystemBusinessFlag()) {
                                cell7.setCellValue("是");
                            } else {
                                cell7.setCellValue("否");
                            }
                        } else {
                            cell7.setCellValue("");
                        }

                        //行业分类
                        XSSFCell cell8 = xssfRow.createCell(8);
                        cell8.setCellStyle(unLockCellStyle);
                        cell8.setCellValue(ucm.getIndtNum());

                        //担保机构评级
                        XSSFCell cell9 = xssfRow.createCell(9);
                        cell9.setCellStyle(unLockCellStyle);
                        cell9.setCellValue(ucm.getGuarantorInstitutionRating());

                setResponseHeader(response, copyFile.getName());

                //锁定不锁定只有加了这个才有用(默认都是锁定后就不可以对单元格内容进行更改)
                xssfSheet.protectSheet("123*456");
                OutputStream out = response.getOutputStream();
                xssfWorkbook.write(out);
                out.flush();
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (InvalidFormatException e) {
                e.printStackTrace();
            } finally {
                if (copyFile.exists()) {
                    copyFile.delete();
                }
                System.out.println("成功之后需要,删除复制的模板源文件,以免占用服务器的内存!");
            }
        } else {
            return;
        }
    }

4. ExcelUtil类的copyExcelTemplateByXSS静态方法,复制模板文件,并以日期的形式作为文件名

/**
     * 复制excel的模板
     *
     * @param excelFilePath 模板路径
     * @param fileName      模板名称
     * @return 复制后的模板副本文件,或null
     */
    public static File copyExcelTemplateByXSSF(String excelFilePath, String fileName) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        String now = dateFormat.format(new Date());
        String templateFilePathAndName = excelFilePath + fileName;
        String copyFilePathAndName = excelFilePath + "/XXX模板" + now + ".xlsx";

        File templateFile = new File(templateFilePathAndName);
        File copyFile = null;
        XSSFWorkbook xssfWorkbook = null;
        if (templateFile.exists()) {
            copyFile = new File(copyFilePathAndName);
            try {
                xssfWorkbook = new XSSFWorkbook(templateFile);
            } catch (InvalidFormatException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            return copyFile;
        }
        try {
            OutputStream out = new FileOutputStream(copyFile);
            xssfWorkbook.write(out);
            out.flush();
            out.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //file.delete();
        }
        return copyFile;
    }

5. ExcelUtil类的setResponseHeader方法,用来设置respond的响应体形象,包括编码格式和以附件的形式进行下载

// 发送响应流方法
    public static void setResponseHeader(HttpServletResponse response, String fileName) {

        try {
            try {
                fileName = new String(fileName.getBytes("gbk"), "ISO8859-1");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            //response.setCharacterEncoding("utf-8");
            response.reset();// 清空输出流

        //告诉浏览器这个文件的名字和类型,attachment:作为附件下载;inline:直接打开
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);

        // response.setContentType("application/vnd.ms-excel");如果设置为这种就是生成.xls文件
            response.setContentType("application/msexcel");
            response.addHeader("Pargam", "no-cache");
            response.addHeader("Cache-Control", "no-cache");
            response.setCharacterEncoding("ISO8859-1");
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

6.control层调用service层

@Controller("/file")
public class ExcelController {

    @Autowired
    UcmService ucmService;

    @RequestMapping("/downLoad")
    //@ResponseBody
    public void excletest(HttpServletRequest request, HttpServletResponse response){
          ucmService.exportExcelMethod(request, response);
    }

以上就是整个处理过程的的大致代码。下面给出excel模板的标题设置为不可修改。选中标题行右键单元格设置-->保护->锁定

-->确定

 

Java使用easyExcel导出Excel显示有不可读取内容 java导出excel只读_poi

     

Java使用easyExcel导出Excel显示有不可读取内容 java导出excel只读_ci_02

再到审阅,点击保护工作表-->购上下面的钩子,输入密码,再次确认密码即可。然后你想修改就必须输入密码才能更改了。

Java使用easyExcel导出Excel显示有不可读取内容 java导出excel只读_ci_03

    

Java使用easyExcel导出Excel显示有不可读取内容 java导出excel只读_excel_04