使用poi生成复杂多行表头

  最近公司的项目需要添加导出报表的功能,报表都是多行表头,最初是使用事先创建模板然后导出的方式,但是随着报表数量的增加和模板表头的变动,这种导出方案就不合适了。因此尝试使用了poi动态生成复杂多行表头的方式导出。说明一下,表头格式来源是根据页面表格属性生成的,其中页面表格是使用了jqgrid框架。以下是代码实现过程:

  一、js获取表格属性的共用方法:

  1、获取表格的行和列属性;

  2、获取数据行的属性和数据格式,方便动态添加数据行;

  3、获取导出文件名,把菜单名作为导出的excel文件名。

  

/**
 * 下载报表,使用poi,并根据页面报表动态创建表头,不需要事先创建模板
 * @param gridId 页面表格ID
 * @param formId
 */
function downloadReport(gridId, formId) {
    var downloadReportUrl = "downloadReport";
    var exportHeader = $("#gview_" + gridId).find(‘div.ui-jqgrid-hdiv‘).find(‘table‘).eq(0).find(‘tr‘);
    //获取表头行列属性(为了生成多行表头)
    var mergedRegions = "";
    for(var i = 0;i<exportHeader.length;i++){
        var mergedRegion = "";
        exportHeader.eq(i).find(‘th:visible‘).each(function(){
            if($(this).text() != null && $(this).text() != ‘‘){
                var rowspan = $(this).attr(‘rowspan‘);
                var colspan = $(this).attr(‘colspan‘);
                if(rowspan == null || rowspan == undefined){
                    rowspan = 0;
                }
                if(colspan == null || colspan == undefined){
                    colspan = 0;
                }
                mergedRegion += $(this).text() + "," +rowspan + "," + colspan + ":"
            }
        });
        if(mergedRegion != ""){
            mergedRegion = mergedRegion.substring(0, mergedRegion.length-1);
            mergedRegions += mergedRegion + ";";
        }
    }
    if(mergedRegions != ""){
        mergedRegions = mergedRegions.substring(0, mergedRegions.length-1);
    }
    //获取数据行
    var exportBody = $("#gview_" + gridId).find(‘div.ui-jqgrid-bdiv‘).find(‘table‘).eq(0).find(‘tr‘);
    if(exportBody.length <= 1){
        showAlert("不能导出空报表,请点击查询后再导出!", "信 息");
        return;
    }
    //获取首行数据行(获取name和value,为了导出excel的数据和格式的填充)
    var columnNames = "";
    exportBody.eq(1).find(‘td:visible‘).each(function(){
        var key = $(this).attr(‘aria-describedby‘);
        var value = $(this).text();
        if(key){
            if(key == ""){
                showAlert("报表下载出错,请联系系统管理员!", "信 息");
                return;
            }
            key = key.replace(gridId + ‘_‘,‘‘);
            columnNames += key + "=" + value +"^_^";
        }
    });
    if(columnNames != ""){
        columnNames = columnNames.substring(0, columnNames.length-3);
    }

    //获取表格所在页面的菜单名,为了生成导出报表的文件名
    var fileName = "";
    var labelledby = $("#gview_" + gridId).parents(‘div.ui-tabs-panel‘).attr(‘aria-labelledby‘);
    if(labelledby){
        fileName = $(‘#‘+labelledby).text();
    }
    if(fileName == ""){
        fileName = "报表";
    }
    try {
        $(‘#loading-msk‘).show().find(‘span‘).html(‘正在下载...‘);
        getDownLoadStatu();

        //表头信息
        if($("#" + formId).find(‘input[name="excel_mergedRegions"]‘).length == 0){
            $("#" + formId).append(‘<input name="excel_mergedRegions" type="hidden"/>‘);
        }
        $("#" + formId).find("input[name=‘excel_mergedRegions‘]").val(mergedRegions);

        //数据信息
        if($("#" + formId).find(‘input[name="excel_columnNames"]‘).length == 0){
            $("#" + formId).append(‘<input name="excel_columnNames" type="hidden"/>‘);
        }
        $("#" + formId).find("input[name=‘excel_columnNames‘]").val(columnNames);

        //报表信息
        if($("#" + formId).find(‘input[name="excel_fileName"]‘).length == 0){
            $("#" + formId).append(‘<input name="excel_fileName" type="hidden"/>‘);
        }
        $("#" + formId).find("input[name=‘excel_fileName‘]").val(fileName);

        if($("#" + formId).find(‘input[name="gridParam"]‘).length == 0){
            $("#" + formId).append(‘<input name="gridParam" type="hidden"/>‘);
        }

        var $grid    = $(‘#‘ + gridId + ‘‘);
        var postData = $grid.jqGrid("getGridParam", "postData");

        $.extend(postData, {rpt_parameters:$(‘#‘ + formId).serializeJson()});

        $("#" + formId).find("input[name=‘gridParam‘]").val(JSON.stringify(postData));
        $("#" + formId).attr("action", downloadReportUrl).submit();
    } catch(e) {
        $(‘#loading-msk‘).hide();
        showAlert("报表下载出错,请联系系统管理员!", "信 息");
    } finally {
    //    $("#" + formId).attr("action", "#");
        $("#" + formId).find("input[name=‘gridParam‘]").val("");
    }
}

2、后台处理:

 获取表格属性参数

//获取前端传递的表格属性参数
String mergedRegion = p.getParameters().get("excel_mergedRegions");
String columnNames = p.getParameters().get("excel_columnNames");
String fileName = p.getParameters().get("excel_fileName");

动态生成多行表头

/**
     * 根据poi导出excel,并根据页面自动创建表头信息
     * @param mergedRegion 表头格式信息
     * @param columnNames 字段信息
     * @param fileName 报表名
     * @return
     */
    public static HSSFWorkbook createWorkBook(String mergedRegion, String columnNames, String fileName) {
        // 创建新的Excel 工作簿
        HSSFWorkbook workbook = new HSSFWorkbook();

        // 设置字体
        HSSFFont font = workbook.createFont();
        font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        font.setFontHeightInPoints((short) 14);

        // 设置样式
        HSSFCellStyle cellStyle = workbook.createCellStyle();
        cellStyle.setFont(font);
        cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        cellStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);

        HSSFCellStyle cellLeftStyle = workbook.createCellStyle();
        cellLeftStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
        cellLeftStyle.setAlignment(HSSFCellStyle.ALIGN_LEFT);

        HSSFCellStyle cellRightStyle = workbook.createCellStyle();
        cellRightStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
        cellRightStyle.setAlignment(HSSFCellStyle.ALIGN_RIGHT);

        HSSFCellStyle cs = workbook.createCellStyle();
        HSSFFont f = workbook.createFont();
        f.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        f.setFontHeightInPoints((short) 10);
        cs.setFont(f);
        cs.setAlignment(CellStyle.ALIGN_CENTER);
        cs.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
        cs.setWrapText(true);

        //获取数据行的列数
        int length = columnNames.split("\\^\\_\\^").length;

        // 第一行
        // 在索引0的位置创建行(最顶端的行)
        HSSFSheet sheet = workbook.createSheet(fileName);
        HSSFRow row = sheet.createRow(0);
        CellRangeAddress cellRangeAddress = new CellRangeAddress(0, 0, 0, length - 1);
        sheet.addMergedRegion(cellRangeAddress);
        // 在索引0的位置创建单元格(左上端)
        HSSFCell cell = row.createCell(0);
        // 定义单元格为字符串类型
        cell.setCellType(HSSFCell.CELL_TYPE_STRING);
        cell.setCellStyle(cellStyle);
        // 在单元格中输入一些内容
        cell.setCellValue(fileName + "报表");

        // 第二行
        row = sheet.createRow(1);
        cellRangeAddress = new CellRangeAddress(1, 1, 0, length - 1);
        sheet.addMergedRegion(cellRangeAddress);
        cell = row.createCell(0);
        cell.setCellStyle(cellRightStyle);
        cell.setCellValue("制表时间:"+ new SimpleDateFormat("yyyy-MM-dd HH:mm").format(new Date()));

        // 处理表头,第三行开始
        String[] mergedRegions = mergedRegion.split(";");
        //创建一个虚拟表头,并使用false标识这个单元格没有被占用
        List<Map<Integer, Boolean>> headerLists = new ArrayList<Map<Integer, Boolean>>();
        for (int i = 0; i <= mergedRegions.length + 1; i++) {
            Map<Integer, Boolean> headerMap = new HashMap<Integer, Boolean>();
            for (int j = 0; j < length; j++) {
                headerMap.put(j, false);
                if (i == 0) {
                    sheet.setColumnWidth(j, (short) (16 * 256));
                }
            }
            headerLists.add(headerMap);
        }
        for (int i = 0; i < mergedRegions.length; i++) {
            String mergedRegionss = mergedRegions[i];
            int x = 2 + i;
            int y = 2 + i;
            int m = 0;
            int n = 0;
            row = sheet.createRow(2 + i);
            row.setHeight((short) (2 * 256));
            String[] _mergedRegionss = mergedRegionss.split(":");
            for (int j = 0; j < _mergedRegionss.length; j++) {
                String mergedRegionsss = _mergedRegionss[j];
                String[] _mergedRegionsss = mergedRegionsss.split(",");
                //获取最小行中未被占用的单元格
                List<Integer> cellNum = new ArrayList<Integer>();
                for (int mm = 0; mm < headerLists.size(); mm++) {
                    Map<Integer, Boolean> headerMap = headerLists.get(mm);
                    for (Integer key : headerLists.get(mm).keySet()) {
                        if (!headerMap.get(key)) {
                            cellNum.add(key);
                        }
                    }
                    if (cellNum.size() > 0) {
                        break;
                    }
                }
                Collections.sort(cellNum);
                m = cellNum.get(0);

                int _y = y + (Integer.parseInt(_mergedRegionsss[1])) - 1;
                if (Integer.parseInt(_mergedRegionsss[1]) == 0) {
                    _y = y;
                }

                n = n + (Integer.parseInt(_mergedRegionsss[2]));
                if (Integer.parseInt(_mergedRegionsss[2]) == 0) {
                    n = m;
                }

                // String cra = x + ", " + _y + ", " + m + ", " + n;
                for (int t = x - 2; t <= _y - 2; t++) {
                    for (int k = m; k <= n; k++) {
                        headerLists.get(t).put(k, true);
                    }
                }
                cellRangeAddress = new CellRangeAddress(x, _y, m, n);
                sheet.addMergedRegion(cellRangeAddress);
                cell = row.createCell(m);
                cell.setCellStyle(cs);
                cell.setCellValue(_mergedRegionsss[0]);
                m = n + 1;
            }
        }

        return workbook;
    }

最后就是数据和行格式的填充、导出流的处理。

  

时间: 2024-11-10 15:15:06

使用poi生成复杂多行表头的相关文章

三步轻松搞定delphi中CXGRID手动添加复表头(多行表头,报表头)

网上有代码动态生成cxgrid多行表头的源码,地址为:http://mycreature.blog.163.com/blog/static/556317200772524226400/ 如果要手动设计多行表头的话,有下面三步搞定: 1.新建一个工程.将CXGRID控件放在上面,Customize创建一个banded table 或者DB BANDED table.操作方法一样. 2.增加BANDS 和columns.加两个BANDS和5个columns.这里看下图红框内的内容为默认这个colum

Java利用poi生成word(包含插入图片,动态表格,行合并)

转: Java利用poi生成word(包含插入图片,动态表格,行合并) 2018年12月20日 09:06:51 wjw_11093010 阅读数:70 Java利用poi生成word(包含插入图片,动态表格,行合并) 测试模板样式: Word生成结果: 图表 2需要的jar包:(具体jar可自行去maven下载) 注意:需要严格按照上面版本下载jar包,否则可能出现jar包之间不能匹配的导致代码报错 各种 jar包都可以在这里下载: https://mvnrepository.com/ Tes

Java基础系列19:使用JXL或者POI生成和解析Excel文件

一 简介 如题所示,当我们需要在Java中解析Excel文件时,可以考虑使用JXL或POI的API来解析. 二者的区别如下: jxl现在基本上没被维护了,最近一次更新时间还是几年前.相反,poi属于Apache开源项目的一部分,更新维护得比较好,最新稳定版 POI 3.15 是今年(2016年)9月更新的,同时poi可以支持更高版本的excel,而jxl只能支持excel2003以及之前的版本 小文件使用jxl解析效率比较高,但是因为支持的excel版本的限制,导致不能导出65535以上量级的数

POI生成EXCEL文件

POI生成EXCEL文件 一.背景 根据指定格式的JSON文件生成对应的excel文件,需求如下 支持多sheet 支持单元格合并 支持插入图片 支持单元格样式可定制 需要 标题(title),表头(head),数据(data) ,表尾(foot) 明确区分 二.效果预览 三.数据格式 由于是生成Excel文件,这里值考虑生成xlsx格式的Excel文件,数据多表头默认考虑使用 | 表示,不在使用colspan rowspan作为.如需要表示两列两行,第一列合并表头格式为: A|B,A|C生成的

Java中用Apache POI生成excel和word文档

概述: 最近在做项目的过程中遇到了excel的数据导出和word的图文表报告的导出功能,最后决定用Apache POI来完成该项功能.本文就项目实现过程中的一些思路与代码与大家共享,同时,也作为自己的一个总结,以备后用. 功能: 1.从数据库查询数据导出为excel: 2.导出word的包括,内容有文字,图片,表格等. 效果: 导出excel 导出word 实现代码: 1.导出excel package beans.excel; import java.io.FileOutputStream;

【转】C# DataTable 导出 Excel 进阶 多行表头、合并单元格、中文文件名乱码

本文原创地址:http://blog.csdn.net/ranbolwb/article/details/8083983 ,转载请保留本行. 本例子是上一篇 DataTable 导出 Excel 的进阶,除了上一篇提到的处理乱码问题,本例还添加了处理多行表头.合并单元格的功能及处理中文文件名乱码问题,应该可以满足日常开发的需要了. 废话不多说了,直接上代码: [C#] 可以写单独类 1 using System; 2 using System.Collections.Generic; 3 usi

poi导出Excel报表多表头双层表头、合并单元格

效果图: controller层方法: /**     *      * 导出Excel报表     * @param request     * @return     *      */    @RequestMapping("/export")    @ResponseBody    public void export(HttpServletRequest request,            HttpServletResponse response, String year

java 利用 poi 生成 Excel文件的例子

在用java 写数据库应用的时候, 通常会生成各种报表,而这些报表可能会被导出为各种格式的文件,比如Excel文档,pdf 文档等等. 今天先做了一个生成Excel 文档的例子,主要解决以下问题: 1. 生成 Excel 文档. 2. 保护生成Excel文档,设置密码访问. 3. 自动对生成的Excel 文档第一行标题栏设置成filter 过滤形式, 方便用户使用. 用 apache  POI 生成 Excel 文档公用类  程序代码 package com.yihaomen.poi.sampl

POI生成EXCEL文件(字体、样式、单元格合并、计算公式)

创建一个封装类: 1 package com.jason.excel; 2 3 import java.io.FileNotFoundException; 4 import java.io.FileOutputStream; 5 import java.io.IOException; 6 7 import org.apache.poi.hssf.usermodel.HSSFCell; 8 import org.apache.poi.hssf.usermodel.HSSFCellStyle; 9