动态透视报表 + 查询接口 + 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 行核心代码,很多公司报表系统都是这样实现的。

相关推荐
清水白石0082 小时前
pytest Fixture 设计实战指南:作用域、依赖链、自动清理与测试资源高效复用
python·pytest
BioRunYiXue2 小时前
Nature Methods:CellVoyager 自主 AI 智能体开启生物数据分析新时代
大数据·开发语言·前端·javascript·人工智能·数据挖掘·数据分析
tottoramen2 小时前
如何安装龙虾
python
QC·Rex2 小时前
AI Agent 任务规划实战:从 ReAct 到 Plan-and-Solve 的完整指南
人工智能·python·react
kcuwu.3 小时前
Python面向对象:封装、继承、多态
开发语言·python
YuanDaima20483 小时前
LangChain基础配置与对话模型实战
人工智能·python·langchain·大模型·智能体·langgraph
一定要AK3 小时前
Java流程控制
java·开发语言·笔记
河西石头3 小时前
分享python项目与开源python项目中的效率法宝--requirements文件的使用
开发语言·python·requirements文件·批量安装python依赖·python虚拟环境配置