POI(Poor Obfuscation Implementation)是一个强大的Java API,用于读写Microsoft Office格式的文件,如Excel (.xls, .xlsx)。以下是使用POI进行Excel操作的详细说明:
导出Excel文件
Apache POI库提供了两种主要的工作簿接口来处理不同版本的Excel文件:
- HSSFWorkbook:适用于老版的Excel .xls 文件格式,最大行数限制为65536行,最大列数为256列。
- XSSFWorkbook:适用于新版的Excel .xlsx 文件格式,采用XML方式存储数据,理论上没有行数和列数的硬性限制。
单元格类型与获取方法:根据单元格的不同类型调用对应的方法获取内容,例如:
- 数字类型:CELL_TYPE_NUMERIC,使用cell.getNumericCellValue()获取数值。
- 字符串类型:CELL_TYPE_STRING,使用cell.getStringCellValue()获取字符串。
- 布尔类型:CELL_TYPE_BOOLEAN,使用cell.getBooleanCellValue()获取布尔值。
- 公式类型:CELL_TYPE_FORMULA,使用cell.getCellFormula()获取公式。
创建并填充Excel文件
- 打开或创建一个工作簿,如果是基于模板,则需要读取模板文件:
//非模板的就不用引入这个
FileInputStream templateStream = new FileInputStream(templateFilePath + "/文件名称.xlsx");
Workbook workbook = new XSSFWorkbook(templateStream); // 若为.xslx格式
// 或
Workbook workbook = new HSSFWorkbook(templateStream); // 若为.xls格式
// 创建或获取工作表
Sheet sheet = workbook.getSheetAt(0); // 获取模板中的第一个工作表
// 或
Sheet sheet = workbook.createSheet("新工作表名称"); // 创建新的工作表
// 创建单元格样式
CellStyle cellStyle = createCellStyle(workbook);
for (int i = 0; i < tableData.size(); i++) {
Row row = sheet.createRow(i);
row.createCell(0).setCellValue(tableData.get(i)); // 填充单元格数据
row.getCell(0).setCellStyle(cellStyle); // 设置单元格样式
}
// 设置HTTP响应头以下载Excel文件
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8");
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("导出文件名称.xlsx", "UTF-8"));
OutputStream outputStream = response.getOutputStream();
workbook.write(outputStream);
outputStream.flush();
- 单元格样式设置
private HSSFCellStyle createCellStyle(HSSFWorkbook workbook) {
HSSFCellStyle cellStyle = workbook.createCellStyle();
cellStyle.setBorderBottom(BorderStyle.THIN); // 下边框
cellStyle.setBorderLeft(BorderStyle.THIN); // 左边框
cellStyle.setBorderRight(BorderStyle.THIN); // 右边框
cellStyle.setBorderTop(BorderStyle.THIN); // 上边框
cellStyle.setAlignment(HorizontalAlignment.CENTER); // 水平居中
cellStyle.setVerticalAlignment(VerticalAlignment.CENTER); // 垂直居中
HSSFFont font = workbook.createFont();
font.setBold(true);
cellStyle.setFont(font);
cellStyle.setWrapText(true); // 自动换行
return cellStyle;
}
- 单元格合并
CellRangeAddress cellRange = new CellRangeAddress(startRowIndex, endRowIndex, startColIndex, endColIndex);
sheet.addMergedRegion(cellRange);
- 复制单元格
//复制单元格
public void copyRows(Sheet fromsheet, Sheet newsheet ) {
//获得开始行
int firstrow = fromsheet.getFirstRowNum();
//获得结束行
int lastrow = fromsheet.getLastRowNum();
//如果开始或结束行为-1直接返回 不复制
if ((firstrow == -1) || (lastrow == -1) || lastrow < firstrow) {
return;
}
// 拷贝合并的单元格
for (int i = 0; i < fromsheet.getNumMergedRegions(); i++) {
CellRangeAddress mergedRegion = fromsheet.getMergedRegion(i);
newsheet.addMergedRegion(mergedRegion);
}
Row fromRow = null;
Row newRow = null;
Cell newCell = null;
Cell fromCell = null;
// 循环开始行到结束行
for (int i = firstrow; i <= lastrow; i++) {
//获得每一行
fromRow = fromsheet.getRow(i);
//判断行不为空
if (fromRow != null) {
//循环设置行宽
for (int j = fromRow.getLastCellNum(); j >= fromRow.getFirstCellNum(); j--) {
int colnum = fromsheet.getColumnWidth((short) j);
if (colnum > 50) {
newsheet.setColumnWidth((short) j, (short) colnum);
}
if (colnum == 0) {
newsheet.setColumnHidden((short) j, true);
} else {
newsheet.setColumnHidden((short) j, false);
}
}
break;
}
}
// 拷贝行并填充数据
for (int i = 0; i <= lastrow; i++) {
//获得每一行
fromRow = fromsheet.getRow(i);
//如果行为空跳过本次循环
if (fromRow == null) {
continue;
}
//创建行
newRow = newsheet.createRow(i - firstrow);
//设置行高
newRow.setHeight(fromRow.getHeight());
for (int j = fromRow.getFirstCellNum(); j < fromRow.getPhysicalNumberOfCells(); j++) {
//获得行内的格
fromCell = fromRow.getCell((short) j);
//格为空跳过本次循环
if (fromCell == null) {
continue;
}
//创建新的单元格
newCell = newRow.createCell((short) j);
//得到单元格样式
CellStyle cellStyle = fromCell.getCellStyle();
//设置单元样式 将老的样式赋给新的
newCell.setCellStyle(fromCell.getCellStyle());
newCell.setCellType(fromCell.getCellType());
int cType = fromCell.getCellType();
newCell.setCellType(cType);
//根据不同的类型填入不同的值
switch (cType) {
case HSSFCell.CELL_TYPE_STRING:
newCell.setCellValue(fromCell.getRichStringCellValue());
break;
case HSSFCell.CELL_TYPE_NUMERIC:
newCell.setCellValue(fromCell.getNumericCellValue());
break;
case HSSFCell.CELL_TYPE_FORMULA:
newCell.setCellFormula(fromCell.getCellFormula());
break;
case HSSFCell.CELL_TYPE_BOOLEAN:
newCell.setCellValue(fromCell.getBooleanCellValue());
break;
case HSSFCell.CELL_TYPE_ERROR:
newCell.setCellValue(fromCell.getErrorCellValue());
break;
default:
newCell.setCellValue(fromCell.getRichStringCellValue());
break;
}
}
}
}
导入Excel文件
导入Excel文件时,也需要根据文件扩展名创建适当的工作簿对象,然后读取各个单元格的内容并进行解析:
public void importExcel(MultipartFile file) throws IOException {
Workbook workbook;
if (file.getOriginalFilename().endsWith(".xlsx")) {
workbook = new XSSFWorkbook(file.getInputStream());
} else if (file.getOriginalFilename().endsWith(".xls")) {
workbook = new HSSFWorkbook(file.getInputStream());
} else {
throw new IllegalArgumentException("不支持的文件格式");
}
for (Sheet sheet : workbook) {
for (Row row : sheet) {
for (Cell cell : row) {
switch (cell.getCellType()) {
case STRING:
String textValue = cell.getStringCellValue();
// 处理文本数据
break;
// 其他类型处理...
}
}
}
}
workbook.close();
}