Java 可以通過(guò) Apache POI 操作 Excel 的導(dǎo)入導(dǎo)出
Apache POI 是一套操作 Microsoft Office 套件的開(kāi)源 Java API
更多精彩
- 更多技術(shù)博客,請(qǐng)移步 IT人才終生實(shí)訓(xùn)與職業(yè)進(jìn)階平臺(tái)
JAR 包依賴及介紹
- 請(qǐng)參見(jiàn) Java Apache POI 操作 Excel 導(dǎo)入
實(shí)現(xiàn)步驟
創(chuàng)建 Excel 實(shí)體類(lèi),用于同一接收導(dǎo)出數(shù)據(jù)
-
headers用于存儲(chǔ)導(dǎo)出數(shù)據(jù)時(shí)規(guī)定的表格頭部?jī)?nèi)容 -
cells是一個(gè)在 List 中嵌套 List 的結(jié)構(gòu)- 外層的 List 表示行數(shù)據(jù)
- 內(nèi)層的 List 表示列數(shù)據(jù)
- 結(jié)合起來(lái)也就是有多少行多少列的數(shù)據(jù)
- 如果導(dǎo)出的內(nèi)容存在多個(gè) sheet ,只需要使用一個(gè) Map ,通過(guò) key-value 的形式包裝 Excel 實(shí)體類(lèi)即可
- 例如
Map<String, Excel> excels,Map 中的 key 就是 sheet 的名稱
- 例如
public class Excel {
// 表頭
private List<String> headers = Lists.newArrayList();
// 內(nèi)容
private List<List<String>> cells = Lists.newArrayList();
// 省略 Getter/Setter 方法
}
舉一個(gè)上述實(shí)體類(lèi)使用的例子
- 傳入的數(shù)據(jù)本身就很復(fù)雜,需要導(dǎo)出的數(shù)據(jù)也存在多個(gè) sheet
private Map<String, Excel> wrapFeedbackQuestions(Map<String, ArrayList<FeedbackQuestion>> feedbackQuestionMap) {
Map<String, Excel> excels = Maps.newHashMap();
if (feedbackQuestionMap.isEmpty()) {
throw new TSharkException("統(tǒng)計(jì)數(shù)據(jù)轉(zhuǎn)換異常,請(qǐng)咨詢管理員");
}
List<String> divide = Lists.newArrayList();
feedbackQuestionMap.forEach((k, v) -> {
Excel excel = new Excel();
excel.addHeader("題目");
excel.addHeader("小計(jì)");
v.forEach(feedbackQuestion -> {
// 按照約定格式每行添加數(shù)據(jù)
List<String> row = Lists.newArrayList();
row.add(feedbackQuestion.getContent());
row.add(feedbackQuestion.getCount().toString());
excel.addCell(row);
});
excels.put(k, excel);
});
return excels;
}
構(gòu)建 ExcelExportUtil 工具類(lèi)
-
Map<String, Excel> excel是通過(guò)上述操作構(gòu)建好的數(shù)據(jù)結(jié)構(gòu) -
String filePath是生成 Excel 后,存放文件的地址 -
initHeaderStyle()和initCellStyle()是對(duì)表格樣式的初始化,在后續(xù)步驟中提供 -
formatLongValue()是為了防止單元格內(nèi)容過(guò)長(zhǎng),而設(shè)置的超過(guò)一定量長(zhǎng)度添加換行符
public static String export(Map<String, Excel> excel, String filePath) {
HSSFWorkbook workbook = new HSSFWorkbook();
// 表頭樣式
HSSFCellStyle headerStyle = initHeaderStyle(workbook);
// 單元格樣式
HSSFCellStyle cellStyle = initCellStyle(workbook);
excel.forEach((key, value) -> {
HSSFSheet sheet = workbook.createSheet(key);
List<String> headers = value.getHeaders();
List<List<String>> cells = value.getCells();
// 表頭包裝
HSSFRow headerRow = sheet.createRow(0);
for (int i = 0; i < headers.size(); i++) {
HSSFCell cell = headerRow.createCell(i);
cell.setCellValue(headers.get(i));
cell.setCellStyle(headerStyle);
}
// 內(nèi)容包裝
for (int j = 0; j < cells.size(); j++) {
HSSFRow row = sheet.createRow(j + 1);
List<String> child = cells.get(j);
for (int k = 0; k < child.size(); k++) {
HSSFCell cell = row.createCell(k);
cell.setCellValue(formatLongValue(child.get(k)));
cell.setCellStyle(cellStyle);
}
}
// 自動(dòng)撐開(kāi)列寬
sheet.autoSizeColumn((short) 0);
sheet.autoSizeColumn((short) 1);
});
// 保存文件并返回名稱
String fileName = FileUtil.getRandomFileNameByDate();
try {
String fullFileName = filePath + fileName + FILE_SUFFIX;
FileOutputStream stream = new FileOutputStream(fullFileName);
workbook.write(stream);
stream.flush();
} catch (Exception e) {
logger.error("Excel導(dǎo)出失敗,", e);
}
return fileName;
}
initHeaderStyle() 初始化表頭樣式
- 對(duì)表頭單元格的字體、顏色、背景做一些自定義操作
private static HSSFCellStyle initHeaderStyle(HSSFWorkbook workbook) {
// 表頭字體
HSSFFont font = workbook.createFont();
font.setFontHeightInPoints((short) 15);
font.setColor(HSSFColor.WHITE.index);
// 表頭樣式
HSSFCellStyle headerStyle = workbook.createCellStyle();
headerStyle.setFont(font);
headerStyle.setWrapText(true);
headerStyle.setFillBackgroundColor(HSSFColor.GREEN.index);
headerStyle.setFillForegroundColor(HSSFColor.GREEN.index);
// 需要設(shè)置此項(xiàng),單元格背景色才會(huì)生效
headerStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
return headerStyle;
}
initCellStyle 初始化單元格樣式
private static HSSFCellStyle initCellStyle(HSSFWorkbook workbook) {
// 單元格字體
HSSFFont font = workbook.createFont();
font.setFontHeightInPoints((short) 15);
// 單元格樣式
HSSFCellStyle cellStyle = workbook.createCellStyle();
cellStyle.setFont(font);
cellStyle.setWrapText(true);
return cellStyle;
}
formatLongValue 格式化超長(zhǎng)內(nèi)容
- 需要單元格啟用
setWrapText = true才會(huì)生效
private static String formatLongValue(String value) {
// 長(zhǎng)度限制
int limit = 50;
// 沒(méi)有達(dá)到限制直接返回
if (value.length() < 50) {
return value;
}
StringBuilder stringBuilder = new StringBuilder();
// 設(shè)置長(zhǎng)度限制的正則匹配
Pattern p = Pattern.compile("(.{" + limit + "}|.*)");
Matcher m = p.matcher(value);
while (m.find()) {
String group = m.group();
// 字符不存在則跳過(guò)
if (group == null || group.trim().equals("")) {
continue;
}
// 超過(guò)限制添加換行符
stringBuilder.append(group);
stringBuilder.append("\n");
}
return stringBuilder.toString();
}