首页 > 其他分享 >Poi Excel 动态变化行高,动态创建Sheet

Poi Excel 动态变化行高,动态创建Sheet

时间:2023-07-05 16:37:10浏览次数:36  
标签:Sheet Excel 动态创建 标题 模板 workbook sheet 行高

需求

  • Excel 最终需要由A4纸打印出来
  • 标题名称需要动态变化
  • 行高自动变化
  • 每页都需要保留标题

分析

基础需求即填充标题填充数据,设置样式,基础需求可以通过easyExcel或者Poi的API来实现,但是由于需求3、4,easyExcel并不支持,只能选择使用Apache Poi。

Apache POI没有直接的API来自动调整行高,所以行高需要手动计算

每页都需要保留标题,这个需求导致不能使用excel软件默认的分页,所以要求控制每页的数据总量填充后整体高度需要小于一张A4纸的高度,否则数据将被分页。

那么大量的数据手动分页,可以通过多sheet来实现,确保每个sheet只存一张A4纸能放下的数据,超过了则复制一个sheet然后继续填充。

代码

​ 以下是一个实现的示例,根据自己的需求进行参考变动即可

  1. 获取要填充的数据

    List<ExcelEthicRecordData> records = this.getExcelEthicRecord(ethIds);
    
    
  2. 获取模板文件创建workbook对象

    // 加载模板文件 获取模板文件流
            ClassPathResource templateResource = new ClassPathResource("excel-template/template.xlsx");
            InputStream templateStream = templateResource.getInputStream();
            Workbook workbook = WorkbookFactory.create(templateStream);
    
  3. 设置标题样式以及拷贝样式(如果需要的话)

    /**
         * 设置标题以及将样式拷贝出来
         * @param records 记录 用于计算标题类型
         * @param workbook workbook
         * @return 样式
         */
        private static CellStyle setStyle(List<ExcelEthicRecordData> records, Workbook workbook) {
            // 计算总Sheet高度 后面需要保持总高不变
            Sheet templateSheet = workbook.getSheetAt(0);
    
            // 获取标题单元格
            Row titleRow = templateSheet.getRow(1);  // 第二行的索引为1
            Cell titleCell = titleRow.getCell(0);  // 假设标题在第一列
    
            // 替换标题的“【类型】”为type变量
            String title = titleCell.getStringCellValue();
            title = title.replace("类型", calculateType(records));
            titleCell.setCellValue(title);
    
    		// 从模板文件的标题列中获取样式,主要是边框
            CellStyle borderStyle = templateSheet.getRow(3).getCell(0).getCellStyle();
            // 创建新的字体样式
            Font font = workbook.createFont();
            font.setFontHeightInPoints((short) 9);  // 缩小字号为9号字
            borderStyle.setFont(font);
            borderStyle.setWrapText(true); // 自动换行
            return borderStyle;
        }
    
  4. 动态变化行高和创建Sheet并且填充数据

    CellStyle borderStyle = setStyle(records, workbook);
    
            int currentSheetIndex = 0;
            int currentRowNumber = 4;  // 从第五行开始填充数据
            short defaultHeight = 40 * 20;  // 默认行高为40 可根据自己需要进行设置
    
            // 获取当前Sheet
            Sheet currentSheet = workbook.getSheetAt(currentSheetIndex);
            // 在POI库中,Excel的行高是以1/20个点为单位进行设定的, A4 纸包含边距 1150个点数,模板文件默认行高设置大约40个点数
            // 根据打印结果计算,行高40的情况下大概能打印12行 根据自己需要计算
            int maxRowsPerPage = defaultHeight * 12;
    
            int totalHeight = 0; // 记录当前页已使用的高度
    
            for (ExcelEthicRecordData record : records) {
                // 计算行高,这里假设每14个字符占一行
                int recordHeight = Math.max(record.getNum().length(), record.getSchemeName().length()) / 14 + 1;
                // 根据实际内容长度调整行高
                short height = (recordHeight > 1) ? (short) (256 * recordHeight) : defaultHeight;
    
                // 如果这条记录的高度使得当前Sheet的高度超过了最大高度,那么就创建一个新的Sheet
                if (totalHeight + height > maxRowsPerPage) { // 如果添加新的行会超过总高度
                    // 创建新的Sheet,并将模板Sheet的格式复制到新的Sheet
                    String sheetName = "Sheet" + ++currentSheetIndex;
                    cloneSheetStyle(workbook, sheetName);
                    // 重置当前高度和行数
                    totalHeight = 0;
                    currentRowNumber = 4; // 如果你的标题占用了4行,那么数据从第5行开始
                    currentSheet = workbook.getSheetAt(currentSheetIndex);
                }
                // 在当前Sheet的指定行创建新的行
                Row newRow = currentSheet.createRow(currentRowNumber);
                newRow.setHeight(height);
    
                // 应用样式到新的单元格上 填充数据
                for (int i = 0; i < 8; i++) {
                    Cell cell = newRow.createCell(i);
                    cell.setCellStyle(borderStyle);
                    if (i == 0) {
                        cell.setCellValue(record.getNum());
                    } else if (i == 1) {
                        cell.setCellValue(record.getSchemeName());
                    }
                }
                // 更新当前高度和行数
                totalHeight += height;
                currentRowNumber++;
            }
    
  5. 克隆样式代码

    private void cloneSheetStyle(Workbook workbook, String sheetName) {
            // 获取模板sheet
            Sheet templateSheet = workbook.getSheetAt(0);
    
            // 复制模板sheet到目标sheet
            Sheet newSheet = workbook.cloneSheet(workbook.getSheetIndex(templateSheet));
    
            // 保留前四行,移除其他所有行
            for (int i = newSheet.getLastRowNum(); i >= 4; i--) {
                Row row = newSheet.getRow(i);
                if (row != null) {
                    newSheet.removeRow(row);
                }
            }
    
            // 重命名新建的sheet
            workbook.setSheetName(workbook.getSheetIndex(newSheet), sheetName);
        }
    
  6. 相应代码

    private static ResponseEntity<byte[]> getResponseEntity(Workbook workbook) throws IOException {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            workbook.write(outputStream);
    
            // 构建下载响应
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            headers.setContentDispositionFormData("attachment", "xxxx.xlsx");
            byte[] fileBytes = outputStream.toByteArray();
    
            return ResponseEntity.ok()
                    .headers(headers)
                    .contentLength(fileBytes.length)
                    .body(fileBytes);
        }
    

标签:Sheet,Excel,动态创建,标题,模板,workbook,sheet,行高
From: https://www.cnblogs.com/oyoung/p/17528886.html

相关文章

  • VUE 2项目使用vue-json-excel导出数据
    记录一下后端返回的json数据转成excel导出这里外面使用的是vue-json-excel1.安装包npminstallvue-json-excel2.组件中使用<download-excelclass="btnbtn-default":data="json_data":fields="json_fields"worksheet="MyWorksheet"name=&......
  • Java批量操作Excel文件实践
    摘要:本文由葡萄城技术团队于博客园原创并首发。转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。前言|问题背景在操作Excel的场景中,通常会有一些针对Excel的批量操作,批量的意思一般有两种:对批量的Excel文件进行操作。如导入多个Excel......
  • 通过 openpyxl 操作 excel 表格
    博客地址:https://www.cnblogs.com/zylyehuo/STEP1:导入相关库importosfromopenpyxlimportload_workbookSTEP2:构建存放路径,将上传文件下载到服务器该路径下excel_stus=request.FILES.get("excel_stus")#获取文件path=os.path.join("media","files",excel_s......
  • 18个Excel中最常用的统计函数
    在日常工作中,数据统计是工作中最重要的一部分。今天兰色把Excel中最常用的统计函数整理了出来,共18个。为了方便同学们理解,选取的全是贴近应用的示例。 1、Count函数 作用:统计数字的个数示例:使用公式生成A列的序号=COUNT(A$1:A1)+1注:大小不一的合并单元格填充公式,要使用C......
  • python给多页excel工作表写跳转目录及回转链接
    1fromopenpyxlimportload_workbook2#fromopenpyxl.drawing.textimportParagraph,RegularTextRun3fromopenpyxl.worksheet.hyperlinkimportHyperlink4#fromopenpyxl.utilsimportget_column_letter56#打开现有的工作簿7workbook=load_workbo......
  • python接口自动化封装导出excel方法和读写excel数据
    一、首先需要思考,我们在页面导出excel,用python导出如何写入文件的封装前需要确认python导出excel接口返回的是一个什么样的数据类型如下:我们先看下不对返回结果做处理,直接接收数据类型是一个对象,无法获取返回值此时我们需要对返回数据做处理,如下;response.text#响应文本数据......
  • Camstar SSL需要证书下载才能导入excel
    谷歌浏览器F12,点击security,点击ViewCertificate.  下载好了,双击,进行安装 设置:注册表 ......
  • EasyExcel 根据模板复制Sheet并将数据分页填充
    需求指定Excel模板文件,只给一个Sheet每个Sheet填充指定数量的数据,超过指定条数,根据模板Sheet复制并且追加数据准备工作引入easyExcelpom依赖<!--https://mvnrepository.com/artifact/com.alibaba/easyexcel--><dependency><groupId>com.alibaba</group......
  • python如何操作读取excel表格数据之xlrd模块
    xlrd模块支持读取xlsx和xls两种格式的excel表格数据,使用之前需要先安装(可以通过pip安装) importxlrd#读取excel文件路径readfile=xlrd.work_bork(r'excel文件所在路径') #获取sheetsheet=readfile.sheet_names()obj_sheet=readfile.sheet_by_name('sheet1') #......
  • 当使用POI打开Excel文件遇到out of memory时该如何处理?
    摘要:本文由葡萄城技术团队于博客园原创并首发。转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。当我们开发处理Excel文件时,ApachePOI是许多人首选的工具。但是,随着需求的增加、工程复杂,在打开复杂的Excel文件的时候可能会出现一些异......