POI无法创建xlsm文件

这篇博客探讨了使用Apache POI和EasyExcel处理xlsm(带宏的Excel)文件时遇到的问题。作者指出,这两个库无法直接创建xlsm文件,会导致打开时显示文件损坏。解决方法是在服务器上预先存放一个正常的xlsm文件,然后利用POI清空内容并填充新数据。源代码展示了如何实现这一过程,包括读取模板文件、清空内容、写入新数据,最后通过响应流提供下载。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

xlsm文件就是带宏的Excel文件
  POI和EasyExcel都是无法创建xlsm文件的。xlsm文件只能在Excel里面另存为xlsm文件。我通过自己的尝试,发现POI和EasyExcel创建xlsm虽然不会报错,但是打开文件都是提示损坏,而wps又能正常打开。
  POI和EasyExcel创建xlsm本质上应该都是把文件的后缀改为.xlsm,因为我把生成的损坏的xlsm文件后缀改为xlsx,可以正常打开。
POI创建xlsm文件不会报错,但是打开下载的文件时候会报错文件已损坏
这是因为POI只能对已有的xlsm文件进行查询与更改,而不能创建xlsm文件
当需求需要能下载xlsm文件时,解决办法就是在服务器中放一个正常的xlsm文件,然后用POI对文件进行清空,放上需要的数据传给接口再下载到本地。

以下是部分源码

@Permission("")
    @RequestMapping("/exportData")
    public void exportData(@RequestParam(value = "table") String table,
                           @RequestParam(value = "uploadTime", required = false) String uploadTime,
                           @RequestParam("tid") Integer tid
            , @RequestParam(value = "ym", required = false) String ym) {
        File file1 = new File(uploadPath + table + ".xlsm");
        table = table.trim().toUpperCase();
        User user = (User) session.getAttribute("login");


        List<Mapping> mapping = insertConfigService.findMappingList(table, db);
        //List<com.gr.entity.master.Mapping> mapping = dataMappingService.findMappingByTable(table);
        //模板表中文名
        String excelname = mapping.get(0).getTableNote();
        if (file1.exists()) {//存在

            //将数据放入服务器上的excel
            Path filePath = Paths.get(file1.toString());
            // declare a workbook
            XSSFWorkbook workbook;
            try {
                /*
                 * READING from the .xlsx file:
                 */
                FileInputStream in = new FileInputStream(filePath.toFile());
                workbook = XSSFWorkbookFactory.createWorkbook(in);
                XSSFSheet sheet = workbook.getSheetAt(0);


                FileOutputStream out1 = new FileOutputStream(filePath.toAbsolutePath().toString());
                sheet = workbook.getSheetAt(0);
                // create new cells and write the words into them
                //清空标题和数据
                for (int i = 1; i <= sheet.getLastRowNum(); i++) {
                    XSSFRow row3 = sheet.getRow(i);
                    for (int j = 0; j < row3.getLastCellNum(); j++) {
                        XSSFCell cell = row3.getCell(j);
                        cell.setCellValue("");
                    }
                }
                //添加标题
                XSSFRow row1 = sheet.createRow(0);
                for (int j = 0; j < cols.size(); j++) {
                    XSSFCell cell = row1.createCell(j);
                    cell.setCellValue(cols.get(j));
                }

                //添加数据
                for (int i = 1; i <= data.size(); i++) {
                    XSSFRow row = sheet.createRow(i);
                    for (int j = 0; j < data.get(0).size(); j++) {
                        XSSFCell cell = row.createCell(j);
                        cell.setCellValue(data.get(i - 1).get(j).toString());
                    }
                }
                // close the FileInputStream
                in.close();
                // write the workbook using the FileOutputStream
                workbook.write(out1);
                // force the FileOutputStream to write everything until it is empty
                out1.flush();
                // close the FileOutputStream
                out1.close();
                // close the workbook.
                workbook.close();
            } catch (FileNotFoundException e) {
                System.err.println(
                        "The file \"" + filePath.toAbsolutePath().toString() + "\" could not be found.");
                e.printStackTrace();
            } catch (IOException e) {
                System.err.println("Error while reading the file \"" + filePath.toAbsolutePath().toString() + "\"");
                e.printStackTrace();
            } catch (EmptyFileException e) {
                System.err.println("The supplied file \"" + filePath.toAbsolutePath().toString() + "\" is empty.");
                e.printStackTrace();
            }
            //从服务器上下载
            response.setCharacterEncoding("UTF-8");
            response.setHeader("content-Type", "application/vnd.ms-excel");
            response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(excelname, "UTF-8") + ".xlsm");
            response.setHeader("Pragma", URLEncoder.encode(excelname, "UTF-8"));
            byte[] buffer = new byte[1024];
            FileInputStream fis = null; //文件输入流
            BufferedInputStream bis = null;
            OutputStream os = null; //输出流
            os = response.getOutputStream();

            fis = new FileInputStream(file1);
            bis = new BufferedInputStream(fis);

            int len = 0;
            while ((len = bis.read(buffer)) > 0) {
                os.write(buffer, 0, len);
            }
            bis.close();
            fis.close();
            return;
        }
        //写文件
        EasyExcel.write(response.getOutputStream()).head(heads).registerWriteHandler(new HeadWriteHandlerImpl(mapping.size(), mm)).registerWriteHandler(new Custemhandler()).sheet("Sheet1").doWrite(data);
        //将文件下载到固定地址
        EasyExcel.write(file1.toString()).head(heads).registerWriteHandler(new HeadWriteHandlerImpl(mapping.size(), mm)).registerWriteHandler(new Custemhandler()).sheet("Sheet1").doWrite(data);
        //xlsx转xlsm
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值