圖表也是使用Excel最常使用的核心功能之一,Apache POI可以建立Excel的圖表,比起JasperReports的圖片格式的圖表還要有更多彈性,且也不會有解析度低的問題。
今天就以上一篇中使用公式算出各課程的平均成績來做圖表:
創建繪圖區域: 使用createDrawingPatriarch()
方法創建繪圖區域。要注意在處理不同Excel檔案格式時,要注意回傳的物件型別,以「.xlsx」為例,回傳物件不能使用Drawing介面作為型別,需要轉型為「XSSFDrawing」,後續的步驟中才能使用XSSFDrawing才有的方法。
設置圖表的位置: 以createAnchor()
方法設定圖表放置的位置。這個方法的參數有8個,前四個(int dx1, int dy1, int dx2, int dy2)是設定與Cell的偏移量,單位是EMU,1EMU為1/360,000公分。後四個(col1, row1, col2, row2)是設定跨越的Cell範圍
創建圖表: createChart()
是生成圖表物件的方法,並可以透過setTitleText()
設定圖表標題。
設定圖例: 想顯示圖例的話可以用getOrAddLegend()
方法取得XDDFChartLegend物件,也可以設定圖例顯示的位置
設置DataSources: 使用XDDFDataSourcesFactory來指定X軸和Y軸的數據來源。X軸通常為資料類別,Y 軸則為對應的數值。在此範例中,X軸表示不同的課程名稱,而Y軸則表示每個課程的平均成績。 注意如果是匯出「.xlsx」檔案格式的話,第一個參數Sheet要轉型為XSSFSheet。 第二個參數是設定資料範圍,同樣利用CellRangeAddress()
來選取。
設定軸標籤: 可利用createCategoryAxis()
與createValueAxis()
設定X軸(類別)和Y軸(數值)的標籤及其位置。
生成圖表: createData()
方法創建一個圖表的資料物件,由第一個參數「ChartTypes」來設定圖表類型。原始回傳型別XDDFChartData要轉型為XDDFBarChartData,才能進行直條圖相關的設定。
加入X和Y軸資料到圖表: 使用addSeries()
方法將X和Y軸的資料加入到圖表中,回傳的XDDFChartData.Series要轉型為XDDFBarChartData.Series,才能進行直條圖相關的設定。
最後使用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);
}
匯出的圖表結果
檢查我們匯出的圖表,雖然大致上沒有錯,但還有優化空間:
頭尾處資料直條的寬度被切掉一半,原因是現在直條中心是對齊在X軸刻度線上,但頭尾的刻度線都在最邊界,直條只有一半的區域是在顯示範圍內。因此可以用setCrossBetween()
方法設定排列方式為AxisCrossBetween.BETWEEN,就是直條是排列在X軸刻度線之間的區域,讓直條能完整顯示。
想自行設定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都可以繪製,其他圖表有機會再來研究了。