Java 可以通過 Apache POI 操作 Excel 的導(dǎo)入導(dǎo)出
Apache POI 是一套操作 Microsoft Office 套件的開源 Java API
更多精彩
- 更多技術(shù)博客还棱,請移步 IT人才終生實(shí)訓(xùn)與職業(yè)進(jìn)階平臺
JAR 包依賴及介紹
實(shí)現(xiàn)步驟
創(chuàng)建 Excel 實(shí)體類立润,用于同一接收導(dǎo)出數(shù)據(jù)
-
headers
用于存儲導(dǎo)出數(shù)據(jù)時(shí)規(guī)定的表格頭部內(nèi)容 -
cells
是一個(gè)在 List 中嵌套 List 的結(jié)構(gòu)- 外層的 List 表示行數(shù)據(jù)
- 內(nèi)層的 List 表示列數(shù)據(jù)
- 結(jié)合起來也就是有多少行多少列的數(shù)據(jù)
- 如果導(dǎo)出的內(nèi)容存在多個(gè) sheet ,只需要使用一個(gè) Map 咆课,通過 key-value 的形式包裝 Excel 實(shí)體類即可
- 例如
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í)體類使用的例子
- 傳入的數(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)換異常,請咨詢管理員");
}
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 工具類
-
Map<String, Excel> excel
是通過上述操作構(gòu)建好的數(shù)據(jù)結(jié)構(gòu) -
String filePath
是生成 Excel 后,存放文件的地址 -
initHeaderStyle()
和initCellStyle()
是對表格樣式的初始化述呐,在后續(xù)步驟中提供 -
formatLongValue()
是為了防止單元格內(nèi)容過長,而設(shè)置的超過一定量長度添加換行符
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);
}
}
// 自動撐開列寬
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() 初始化表頭樣式
- 對表頭單元格的字體市埋、顏色、背景做一些自定義操作
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)恕刘,單元格背景色才會生效
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 格式化超長內(nèi)容
- 需要單元格啟用
setWrapText = true
才會生效
private static String formatLongValue(String value) {
// 長度限制
int limit = 50;
// 沒有達(dá)到限制直接返回
if (value.length() < 50) {
return value;
}
StringBuilder stringBuilder = new StringBuilder();
// 設(shè)置長度限制的正則匹配
Pattern p = Pattern.compile("(.{" + limit + "}|.*)");
Matcher m = p.matcher(value);
while (m.find()) {
String group = m.group();
// 字符不存在則跳過
if (group == null || group.trim().equals("")) {
continue;
}
// 超過限制添加換行符
stringBuilder.append(group);
stringBuilder.append("\n");
}
return stringBuilder.toString();
}