Java導(dǎo)出Excel統(tǒng)計報表合并單元格的方法詳解
前言
Apache POI是一種流行的API,允許程序員使用Java程序創(chuàng)建,修改和顯示MS Office文件。 它是由Apache Software Foundation開發(fā)和分發(fā)的開源庫,用于使用Java程序設(shè)計或修改Microsoft Office文件。 它包含將用戶輸入數(shù)據(jù)或文件解碼為MS Office文檔的類和方法。
HSSF - 用于讀取和寫入MS-Excel文件的xls格式
示例

類似上面的需要合并表頭的報表在日常的開發(fā)中也是經(jīng)常遇到,這里總結(jié)下關(guān)于類似的報表開發(fā)整理。
對于這種的報表看起來很麻煩,但其實掌握了技巧開發(fā)起來也是很簡單的。下面的代碼僅供參考,有些字段為了脫敏都以數(shù)字顯示了,見諒。
// 創(chuàng)建sheet
Sheet sheet = wb.createSheet("當(dāng)月");
//表頭字體
Font headerFont = wb.createFont();
headerFont.setFontName("宋體");
headerFont.setFontHeightInPoints((short) 18);
headerFont.setBold(true);
headerFont.setColor(Font.COLOR_NORMAL);
//正文字體
Font contextFont = wb.createFont();
contextFont.setFontName("宋體");
contextFont.setFontHeightInPoints((short) 12);
headerFont.setBold(true);
//表頭樣式,左右上下居中
CellStyle headerStyle = wb.createCellStyle();
headerStyle.setFont(headerFont);
// 左右居中
headerStyle.setAlignment(HorizontalAlignment.CENTER);
// 上下居中
headerStyle.setVerticalAlignment(VerticalAlignment.CENTER);
headerStyle.setLocked(true);
// 自動換行
headerStyle.setWrapText(false);
//單元格樣式,左右上下居中 邊框
CellStyle commonStyle = wb.createCellStyle();
commonStyle.setFont(contextFont);
// 左右居中
commonStyle.setAlignment(HorizontalAlignment.CENTER);
// 上下居中
commonStyle.setVerticalAlignment(VerticalAlignment.CENTER);
commonStyle.setLocked(true);
// 自動換行
commonStyle.setWrapText(false);
//單元格樣式,左右上下居中 邊框
CellStyle commonWrapStyle = wb.createCellStyle();
commonWrapStyle.setFont(contextFont);
//單元格樣式,豎向 邊框
CellStyle verticalStyle = wb.createCellStyle();
verticalStyle.setFont(contextFont);
CellStyle commonStyleNoBorder = wb.createCellStyle();
commonStyleNoBorder.setFont(contextFont);
commonStyleNoBorder.setLocked(true);
// 自動換行
commonStyleNoBorder.setWrapText(false);
CellStyle alignLeftStyle = wb.createCellStyle();
alignLeftStyle.setFont(contextFont);
alignLeftStyle.setLocked(true);
// 自動換行
alignLeftStyle.setWrapText(false);
//單元格樣式,左對齊 無邊框
CellStyle alignLeftNoBorderStyle = wb.createCellStyle();
alignLeftNoBorderStyle.setFont(contextFont);
alignLeftNoBorderStyle.setLocked(true);
// 自動換行
alignLeftNoBorderStyle.setWrapText(false);
//單元格樣式,右對齊
CellStyle alignRightStyle = wb.createCellStyle();
alignRightStyle.setFont(contextFont);
alignRightStyle.setLocked(true);
// 自動換行
alignRightStyle.setWrapText(false);
// 行號
int rowNum = 0;
//設(shè)置列寬
for (int i = 0; i < 11; i++) {
sheet.setColumnWidth(i, 3000);
}
//第一行
Row r0 = sheet.createRow(rowNum++);
r0.setHeight((short) 800);
Cell c00 = r0.createCell(0);
c00.setCellValue("表二:");
c00.setCellStyle(alignLeftNoBorderStyle);
//合并單元格
sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 8));
//第二行城市對象綜合統(tǒng)計表
Row r1= sheet.createRow(rowNum++);
r1.setHeight((short) 800);
Cell r10 = r1.createCell(0);
r10.setCellValue("城市對象管理情況統(tǒng)計表");
r10.setCellStyle(headerStyle);
//合并單元格
sheet.addMergedRegion(new CellRangeAddress(1, 1, 0, 8));
//第三行
Row r2 = sheet.createRow(rowNum++);
r2.setHeight((short) 800);
Cell r20 = r2.createCell(0);
r20.setCellValue("填表單位:XXX街道");
r20.setCellStyle(alignLeftNoBorderStyle);
//合并單元格
sheet.addMergedRegion(new CellRangeAddress(2, 2, 0, 4));
//第四行
Row r3 = sheet.createRow(rowNum++);
r3.setHeight((short) 700);
String[] rowSecond = {"地 區(qū)", "對象情況1", "","對象情況2","" ,"調(diào)增情況3","","情況4",""};
for (int i = 0; i < rowSecond.length; i++) {
Cell tempCell = r3.createCell(i);
tempCell.setCellValue(rowSecond[i]);
tempCell.setCellStyle(commonStyle);
}
//第5行
Row r4 = sheet.createRow(rowNum++);
String[] rowSecond5 = {"1", "2", "3","4","5","6","7","8"};
for (int i = 0; i < rowSecond5.length; i++) {
Cell tempCell = r4.createCell(i+1);
tempCell.setCellValue(rowSecond5[i]);
tempCell.setCellStyle(commonStyle);
}
//合并單元格
sheet.addMergedRegion(new CellRangeAddress(3, 4, 0, 0));
sheet.addMergedRegion(new CellRangeAddress(3, 3, 1, 2));
sheet.addMergedRegion(new CellRangeAddress(3, 3, 3, 4));
sheet.addMergedRegion(new CellRangeAddress(3, 3, 5, 6));
sheet.addMergedRegion(new CellRangeAddress(3, 3, 7, 8));
//查詢數(shù)據(jù)
List<Map<String, Object>> dataList = XXX.list(XXX);
//統(tǒng)計合計數(shù)據(jù)
Map<String,Object> mapTotal = new HashMap<>();
for (Map<String, Object> map : dataList) {
Row tempRow = sheet.createRow(rowNum++);
//列表數(shù)據(jù)
Cell tempCell0 = tempRow.createCell(0);
String sqmc = (String) map.get("XXX");
tempCell0.setCellValue(sqmc);
tempCell0.setCellStyle(commonStyle);
}
//導(dǎo)出
response.setContentType("application/vnd.ms-excel");
// 文件名
String fileName = "報表名稱.xls";
response.setHeader("Content-disposition", "attachment;filename=\"" + fileName + "\"");
OutputStream stream = response.getOutputStream();
try {
if (null != wb && null != stream) {
wb.write(stream);
stream.close();
}
} catch (Exception e) {
log.error("excel文檔導(dǎo)出錯誤-異常信息:", e);
}
注意事項
【1】POI操作的行和列都是從0位置開始的
【2】所有的復(fù)雜表頭無非是合并單元格,這里都可以通過下面的API實現(xiàn)
int addMergedRegion(CellRangeAddress region) 添加合并的單元格區(qū)域

創(chuàng)建新的單元格范圍。索引是從零開始的。
參數(shù):
firstRow—第一行的索引
lastRow—最后一行(含)的索引必須等于或大于第一行
firstCol—第一列的索引
lastCol—最后一列(包括)的索引必須等于或大于firstCol
示例
sheet.addMergedRegion(new CellRangeAddress(3, 3, 1, 2));
合并第四行第1列和第2列

【3】對于空的單元格,直接在數(shù)組或者列表中給個空值就可以了。對于下面的圖片中第5行的[本月人次]這種如果是數(shù)組直接在創(chuàng)建列的時候指定起始位置為1就可以了,注意不要影響合并的位置,而且合并的單元格不要有沖突否則會拋出異常,注意些就可以了.

總結(jié)
到此這篇關(guān)于Java導(dǎo)出Excel統(tǒng)計報表合并單元格的文章就介紹到這了,更多相關(guān)Java導(dǎo)出Excel統(tǒng)計報表內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解決使用@Value(${×××))從properties文件取值的坑
這篇文章主要介紹了解決使用@Value(${×××))從properties文件取值的坑,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07
SpringBoot使用ResponseBodyEmitter處理流式日志和進(jìn)度條
這篇文章主要為大家詳細(xì)介紹了SpringBoot如何使用ResponseBodyEmitter處理流式日志和進(jìn)度條,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2025-02-02
Spring Boot + FreeMarker 實現(xiàn)動態(tài)Word文檔導(dǎo)出功能
Spring Boot與FreeMarker的組合,為開發(fā)者提供了一個強大的平臺,可以輕松實現(xiàn)動態(tài)Word文檔的導(dǎo)出,本文將指導(dǎo)你如何使用Spring Boot與FreeMarker模板引擎,創(chuàng)建一個簡單的應(yīng)用,用于根據(jù)數(shù)據(jù)庫數(shù)據(jù)動態(tài)生成Word文檔并下載,感興趣的朋友一起看看吧2024-06-06
Java 中的CharArrayReader 介紹_動力節(jié)點Java學(xué)院整理
CharArrayReader 是字符數(shù)組輸入流。它和ByteArrayInputStream類似,只不過ByteArrayInputStream是字節(jié)數(shù)組輸入流,而CharArray是字符數(shù)組輸入流。CharArrayReader 是用于讀取字符數(shù)組,它繼承于Reader2017-05-05
Runtime.getRuntime().exec 路徑包含空格的解決
這篇文章主要介紹了Runtime.getRuntime().exec 路徑包含空格的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11
SpringBoot項目部署到阿里云服務(wù)器的實現(xiàn)步驟
本文主要介紹了SpringBoot項目部署到阿里云服務(wù)器的實現(xiàn)步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06

