动态透视报表 + 查询接口 + Excel导出

下面给你一套 企业报表常用的 EasyExcel 完整样式方案 ,在你现在的
SpringBoot + MyBatis + GaussDB + EasyExcel + SQL透视 的基础上增加:

实现效果:

  • ✔ 动态表头
  • ✔ a / f 子表头
  • ✔ 最后一行合计(Java计算)
  • ✔ 合计单元格合并
  • ✔ 合计居中
  • ✔ 表头居中
  • ✔ 自动列宽
  • ✔ 冻结表头
  • ✔ 数值千分位
  • ✔ 导出 Excel 类似数据透视表效果

一、Excel导出效果

最终 Excel:

复制代码
产品  型号  项目  1月  2月  3月  4月  5月  合计
               a   a   a   f   f
A     A1   P1  10  20  30  40  50  150
B     B1   P1  20  40  60  80 100  300
合计           30  60  90 120 150  450

特点:

  • 前三列合并为"合计"
  • 数值自动格式
  • 表头冻结

二、合计行计算(Java)

java 复制代码
public static List<Object> buildTotalRow(
        List<String> rowDims,
        List<String> cols,
        List<Map<String,Object>> data){

    List<Object> row = new ArrayList<>();

    for(int i=0;i<rowDims.size();i++){
        row.add("");
    }

    row.set(0,"合计");

    Map<String,Double> sum=new HashMap<>();

    for(String c:cols){
        sum.put(c,0.0);
    }

    double total=0;

    for(Map<String,Object> r:data){

        for(String c:cols){

            double v = r.get(c)==null ?
                    0 : Double.parseDouble(r.get(c).toString());

            sum.put(c,sum.get(c)+v);
        }

        total += Double.parseDouble(r.get("total").toString());
    }

    for(String c:cols){
        row.add(sum.get(c));
    }

    row.add(total);

    return row;
}

三、合计行单元格合并

创建合并策略:

java 复制代码
public class TotalMergeStrategy extends AbstractMergeStrategy {

    private int totalRow;
    private int mergeCol;

    public TotalMergeStrategy(int totalRow,int mergeCol){
        this.totalRow=totalRow;
        this.mergeCol=mergeCol;
    }

    @Override
    protected void merge(
            Sheet sheet,
            Cell cell,
            Head head,
            Integer relativeRowIndex){

        if(cell.getRowIndex()==totalRow
                && cell.getColumnIndex()==0){

            CellRangeAddress region =
                    new CellRangeAddress(
                            totalRow,
                            totalRow,
                            0,
                            mergeCol);

            sheet.addMergedRegion(region);
        }
    }
}

四、表头居中样式

java 复制代码
public class HeadStyleStrategy
        extends AbstractCellStyleStrategy {

    @Override
    protected void setHeadCellStyle(
            CellWriteHandlerContext context){

        CellStyle style =
                context.getCell()
                .getSheet()
                .getWorkbook()
                .createCellStyle();

        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);

        Font font =
                context.getCell()
                .getSheet()
                .getWorkbook()
                .createFont();

        font.setBold(true);

        style.setFont(font);

        context.getCell().setCellStyle(style);
    }
}

五、数值千分位格式

java 复制代码
public class NumberStyleStrategy
        extends AbstractCellStyleStrategy {

    @Override
    protected void setContentCellStyle(
            CellWriteHandlerContext context){

        if(context.getCell().getColumnIndex()>2){

            CellStyle style =
                    context.getCell()
                    .getSheet()
                    .getWorkbook()
                    .createCellStyle();

            style.setDataFormat(
                    context.getCell()
                    .getSheet()
                    .getWorkbook()
                    .createDataFormat()
                    .getFormat("#,##0"));

            style.setAlignment(HorizontalAlignment.RIGHT);

            context.getCell().setCellStyle(style);
        }
    }
}

六、自动列宽

EasyExcel自带策略:

java 复制代码
LongestMatchColumnWidthStyleStrategy

使用:

java 复制代码
.registerWriteHandler(
    new LongestMatchColumnWidthStyleStrategy()
)

七、冻结表头

java 复制代码
public class FreezePaneHandler
        implements SheetWriteHandler {

    @Override
    public void afterSheetCreate(
            WriteWorkbookHolder holder,
            WriteSheetHolder sheetHolder){

        sheetHolder.getSheet()
                .createFreezePane(0,2);
    }
}

说明:

复制代码
冻结前2行表头

八、完整导出代码

java 复制代码
@PostMapping("/export")
public void export(HttpServletResponse response) throws Exception{

    Map<String,Object> result = service.query();

    List<String> cols =
            (List<String>)result.get("cols");

    List<Map<String,Object>> data =
            (List<Map<String,Object>>)result.get("rows");

    List<List<String>> head =
            ExcelBuilder.buildHead(rowDims,cols,typeMap);

    List<List<Object>> rows =
            ExcelBuilder.buildRows(rowDims,cols,data);

    rows.add(buildTotalRow(rowDims,cols,data));

    int totalRowIndex = rows.size()+1;

    EasyExcel.write(response.getOutputStream())
            .head(head)
            .registerWriteHandler(
                    new LongestMatchColumnWidthStyleStrategy())
            .registerWriteHandler(
                    new FreezePaneHandler())
            .registerWriteHandler(
                    new HeadStyleStrategy())
            .registerWriteHandler(
                    new NumberStyleStrategy())
            .registerWriteHandler(
                    new TotalMergeStrategy(
                            totalRowIndex,
                            rowDims.size()-1))
            .sheet("报表")
            .doWrite(rows);
}

九、最终报表能力

功能 支持
动态表头
a/f子表头
SQL透视
Java合计
合计单元格合并
自动列宽
冻结表头
数值格式
Excel导出

十、企业级再升级(非常推荐)

很多 BI 报表还会加:

1️⃣ 分组小计

复制代码
产品A
   型号1
      项目1
      项目2
   小计

2️⃣ 动态排序

3️⃣ 百万行导出

4️⃣ 分页查询 + 全量导出

5️⃣ 动态筛选条件


如果你需要,我可以再给你一套 真正企业 BI 报表级方案

  • 动态行分组(产品→型号→项目)自动合并单元格
  • 自动生成小计
  • 类似 Excel 数据透视表
  • EasyExcel 完整实现

代码大约 400 行核心代码,很多公司报表系统都是这样实现的。

相关推荐
心中有国也有家1 小时前
GE图引擎深度解析——CANN的计算图优化与执行引擎
人工智能·pytorch·python·学习·numpy
卷毛的技术笔记3 小时前
告别硬编码!Spring AI Alibaba 实现 AI Agent 智能工具调用(Tool Calling)
java·人工智能·后端·python·spring·ai编程
编程大师哥3 小时前
匿名函数 lambda + 高阶函数
java·python·算法
isyangli_blog3 小时前
OpenDayLight (Carbon 版本) 启动与组件安装
开发语言·php
vb2008113 小时前
FastAPI APIRouter
开发语言·python
Benszen3 小时前
KVM虚拟化解决方案
开发语言·perl
会编程的土豆3 小时前
Go 语言反射(Reflection)详解
开发语言·后端·golang
東雪木3 小时前
多线程与并发编程 专属复习笔记
java·开发语言·笔记·java面试
adrninistrat0r3 小时前
Java调用链MCP分析工具
java·python·ai编程
杨充3 小时前
1.3 浮点型数据设计灵魂
开发语言·python·算法