iT邦幫忙

2024 iThome 鐵人賽

DAY 29
0

圖表也是使用Excel最常使用的核心功能之一,Apache POI可以建立Excel的圖表,比起JasperReports的圖片格式的圖表還要有更多彈性,且也不會有解析度低的問題。
今天就以上一篇中使用公式算出各課程的平均成績來做圖表:

建立圖表的步驟

  1. 創建繪圖區域: 使用createDrawingPatriarch()方法創建繪圖區域。要注意在處理不同Excel檔案格式時,要注意回傳的物件型別,以「.xlsx」為例,回傳物件不能使用Drawing介面作為型別,需要轉型為「XSSFDrawing」,後續的步驟中才能使用XSSFDrawing才有的方法

  2. 設置圖表的位置:createAnchor()方法設定圖表放置的位置。這個方法的參數有8個,前四個(int dx1, int dy1, int dx2, int dy2)是設定與Cell的偏移量,單位是EMU,1EMU為1/360,000公分。後四個(col1, row1, col2, row2)是設定跨越的Cell範圍

    • dx1, dy1:上左角的偏移量,分別表示距離第一個儲存格左邊界和上邊界的偏移單位為跨越的儲存格範圍
    • dx2, dy2:下右角的偏移量,表示距離第二個儲存格右邊界和下邊界的偏移
  3. 創建圖表: createChart()是生成圖表物件的方法,並可以透過setTitleText()設定圖表標題。

  4. 設定圖例: 想顯示圖例的話可以用getOrAddLegend()方法取得XDDFChartLegend物件,也可以設定圖例顯示的位置

  5. 設置DataSources: 使用XDDFDataSourcesFactory來指定X軸和Y軸的數據來源。X軸通常為資料類別,Y 軸則為對應的數值。在此範例中,X軸表示不同的課程名稱,而Y軸則表示每個課程的平均成績。 注意如果是匯出「.xlsx」檔案格式的話,第一個參數Sheet要轉型為XSSFSheet。 第二個參數是設定資料範圍,同樣利用CellRangeAddress()來選取。

  6. 設定軸標籤: 可利用createCategoryAxis()createValueAxis()設定X軸(類別)和Y軸(數值)的標籤及其位置。

  7. 生成圖表: createData()方法創建一個圖表的資料物件,由第一個參數「ChartTypes」來設定圖表類型。原始回傳型別XDDFChartData要轉型為XDDFBarChartData,才能進行直條圖相關的設定。

  8. 加入X和Y軸資料到圖表: 使用addSeries()方法將X和Y軸的資料加入到圖表中,回傳的XDDFChartData.Series要轉型為XDDFBarChartData.Series,才能進行直條圖相關的設定。

  9. 最後使用plot()方法將這些數據繪製到圖表上,就完成啦

private void createBarChart(Sheet sheet) {
    // 1. 創建繪圖區域,匯出 .xlsx 格式,要將回傳物件轉型為 XSSFDrawing
    XSSFDrawing drawing = (XSSFDrawing) sheet.createDrawingPatriarch();
    // 2. 圖表的位置
    XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 11, 1, 17, 15);

    // 3. 創建圖表
    XSSFChart chart = drawing.createChart(anchor);
    chart.setTitleText("學生課程平均成績");
    // 4. 設定圖例與位置
    XDDFChartLegend legend = chart.getOrAddLegend();
    legend.setPosition(LegendPosition.RIGHT);

    // 5. 設定圖表DataSource
    // X 軸
    XDDFDataSource<String> categories = XDDFDataSourcesFactory.fromStringCellRange((XSSFSheet) sheet,
            new CellRangeAddress(2, 5, 8, 8));
    // Y 軸
    XDDFNumericalDataSource<Double> values = XDDFDataSourcesFactory.fromNumericCellRange((XSSFSheet) sheet,
            new CellRangeAddress(2, 5, 9, 9));

    // 6. 設定軸標籤
    // X軸標籤
    XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
    bottomAxis.setTitle("課程");

    // Y軸標籤
    XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
    leftAxis.setTitle("平均成績");

    // 7. 創建圖表資料
    // 設定圖表類型為Bar chart,設定軸標籤資料
    XDDFBarChartData barChartData = (XDDFBarChartData) chart.createData(ChartTypes.BAR, bottomAxis, leftAxis);
    // 設定Bar方向
    barChartData.setBarDirection(BarDirection.COL);

    // 8. 加入圖表資料
    XDDFBarChartData.Series series = (XDDFBarChartData.Series) barChartData.addSeries(categories, values);
    // 設定圖例標題
    series.setTitle("課程平均成績", null);

    // 9. 繪製到圖表
    chart.plot(barChartData);
}

匯出的圖表結果
檢查我們匯出的圖表,雖然大致上沒有錯,但還有優化空間:

  • 國文和體育的資料是在頭尾處,但直條的寬度被切掉一半了
  • 有時候不想使用預設值,想自訂義Y軸的刻度

優化圖表

  1. 頭尾處資料直條的寬度被切掉一半,原因是現在直條中心是對齊在X軸刻度線上,但頭尾的刻度線都在最邊界,直條只有一半的區域是在顯示範圍內。因此可以用setCrossBetween()方法設定排列方式為AxisCrossBetween.BETWEEN,就是直條是排列在X軸刻度線之間的區域,讓直條能完整顯示。

  2. 想自行設定Y軸的最大值與最小值,可以直接以setMinimum()setMaximum()設定。

// 6. 設定軸標籤
// X軸標籤
XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
bottomAxis.setTitle("課程");

// Y軸標籤
XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
leftAxis.setTitle("平均成績");

// 設定Bar在刻度之間
leftAxis.setCrossBetween(AxisCrossBetween.BETWEEN);
// 設定Y軸的最大值與最小值
leftAxis.setMinimum(50);
leftAxis.setMaximum(90);

調整後的圖表結果:

整體而言Apache POI繪製圖表能設定滿多細節的,只是要注意匯出的Excel檔案類型以及圖表類型,物件必須跟著轉型,才能設定此檔案類型與圖表類型的功能。Excel有辦法做出的圖Apache POI都可以繪製,其他圖表有機會再來研究了。


Reference


上一篇
Apache POI-Excel公式與FormulaEvaluator
下一篇
JFreeChart(直條圖)與完賽心得
系列文
Java工程師的報表入門與實作30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言