首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

ECharts 圖表匯出 Excel 完整方案:前端渲染、Base64 傳輸、後端 POI 寫入

     編輯:Java 相關知識

整體架構流程

  1. 前端:ECharts 渲染圖表 → getDataURL() 取得 Base64 PNG → 傳給後端。
  2. 後端:Base64 解碼存成圖片 → Apache POI 建立 Excel → 寫入標題、維度、數據、圖片 → 下載回前端。

前端核心程式碼(ExtJS + RequireJS)

1. 初始化 ECharts 模組路徑

initEChart: function() {
    require.config({
        paths: {
            'echarts': 'js/com/bhtec/echart/echarts',
            'echarts/chart/bar': 'js/com/bhtec/echart/echarts',
            'echarts/chart/line': 'js/com/bhtec/echart/echarts',
            'echarts/chart/pie': 'js/com/bhtec/echart/echarts'
        }
    });
}

2. 載入圖表並取得 Base64

loadChart: function(data, item) {
    var that = this;
    require(['echarts', 'echarts/chart/bar', 'echarts/chart/line', 'echarts/chart/pie'], function(ec) {
        that.body.setHeight(800);
        var myChart = ec.init(that.body.dom);
        myChart.showLoading({text: "圖表資料載入中..."});

        var option = {
            tooltip: {trigger: 'axis', axisPointer: {type: 'shadow'}},
            legend: {data: data.indis, x: 'left', y: 'top'},
            toolbox: {
                show: true, orient: 'vertical', x: 'right', y: 'center',
                feature: {
                    mark: {show: true},
                    dataView: {show: true, readOnly: true},
                    magicType: {show: true, type: ['line', 'bar', 'stack', 'tiled']},
                    restore: {show: true},
                    saveAsImage: {show: true}
                }
            },
            calculable: true,
            animation: false,
            xAxis: [{type: 'category', data: data.grp}],
            yAxis: [{type: 'value', splitArea: {show: true}}],
            series: data.bar.series
        };

        myChart.hideLoading();
        myChart.setOption(option);
        that.imgURL = myChart.getDataURL('png'); // 取得 Base64
    });
}

3. 匯出動作:傳圖片 + 維度 + 數據

doExport: function() {
    var url = this.chartPanel.getImageURL(); // Base64
    var title = Ext.fly('indi-display-title-id').first().dom.innerHTML;
    var left = Ext.getCmp("indi_pivotGrid_id").leftAxis.getTuples();
    var top = Ext.getCmp("indi_pivotGrid_id").topAxis.getTuples();

    // 1. 先把圖片 Base64 送後端存檔
    Ext.Ajax.request({
        url: 'indicator/exp2excl.mvc',
        params: {imgURL: url, left: getAxisStr(left)}
    });

    // 2. 再開新視窗下載 Excel(含標題、維度、數據)
    var data = Ext.getCmp("indi_pivotGrid_id").extractData();
    var arr = [];
    for (var i = 0; i < data.length; i++) arr.push(data[i]);

    window.open('indicator/exportList2Excel.mvc?title=' + encodeURIComponent(encodeURIComponent(title))
        + '&left=' + encodeURIComponent(encodeURIComponent(getAxisStr(left)))
        + '&top=' + encodeURIComponent(encodeURIComponent(getAxisStr(top)))
        + '&data=' + arr.join(';'));

    function getAxisStr(tuples) {
        var a = [];
        for (var i = 0; i < tuples.length; i++) a.push(IndiFn.getAxisStr(tuples[i]));
        return a.join(',');
    }
}

後端 Java 核心邏輯

1. Base64 解碼存圖

public void base64ToPic(String fileName, HttpServletRequest req) {
    if (imgsURL == null) return;
    try {
        String[] parts = imgsURL.split(",");
        String base64 = parts.length > 1 ? parts[1] : parts[0]; // 去掉 data:image/png;base64,
        byte[] buffer = new BASE64Decoder().decodeBuffer(base64);
        File outFile = new File(req.getRealPath("pic/" + fileName + ".jpg"));
        try (OutputStream out = new FileOutputStream(outFile)) {
            out.write(buffer);
        }
    } catch (Exception e) {
        log.error("Base64 解碼失敗", e);
    }
}

2. POI 寫入 Excel 並嵌入圖片


// 建立標題列
Row row = sheet.createRow(index + 3);
Cell cell = row.createCell(0);
cell.setCellType(CellType.BLANK);
cell.setCellValue(title);

// 圖片起始列
row = sheet.createRow(index + 6);
Cell imgCell = row.createCell(0);
imgCell.setCellType(CellType.BLANK);

// 讀取圖片轉 ByteArrayOutputStream
ByteArrayOutputStream bos = new ByteArrayOutputStream();
BufferedImage img = ImageIO.read(new File(req.getRealPath("pic/" + fileName + ".jpg")));
ImageIO.write(img, "PNG", bos);

// 寫入 Excel 圖片
Drawing patriarch = sheet.createDrawingPatriarch();
ClientAnchor anchor = new HSSFClientAnchor(5, 5, 5, 5, (short) 1, index + 6, (short) 6, 45);
patriarch.createPicture(anchor, workbook.addPicture(bos.toByteArray(), Workbook.PICTURE_TYPE_PNG));

// 輸出
try (OutputStream out = response.getOutputStream()) {
    workbook.write(out);
}

關鍵技術點總結

環節關鍵 API注意事項
前端取圖chart.getDataURL('png')回傳 Base64 Data URI,需去前綴
傳輸Ext.Ajax.request + window.open大量數據建議 POST 或分塊
後端解碼BASE64Decoder (Java 8 用 Base64.getDecoder())處理 Data URI 前綴
Excel 寫入Apache POI HSSF/XSSFHSSF 僅支援 .xls,大數據請用 SXSSF
圖片嵌入Drawing.createPicture(anchor, pictureIdx)錨點座標單位為 1/1024 字元寬度

現代化建議

  • 前端改用 echarts.min.js + xlsx-style 或 exceljs 純前端生成 Excel,省去後端往復。
  • 後端若保留,建議升級 POI 到 5.x,使用 SXSSFWorkbook 流式寫入避免 OOM。
  • Base64 解碼請用標準 java.util.Base64,移除舊 sun.misc.BASE64Decoder。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved