一. POI详解
1. 简介
Apache POI 简介是用Java编写的免费开源的跨平台的 Java API,Apache POI提供API给Java程式对Microsoft Office(Excel、WORD、PowerPoint、Visio等)格式档案读和写的功能。POI为“Poor Obfuscation Implementation”的首字母缩写,意为“可怜的模糊实现”。
Apache官网:https://www.apache.org/
POI网址:http://poi.apache.org/
POI文档:http://poi.apache.org/apidocs/index.html
本项目中使用的是poi-3.17.jar,相对来说比较稳定,并且有对应版本的文档。
2.常用类介绍
Workbook类和HSSFWorkbook类、Sheet类 和 HSSFSheet类、Row类 和 HSSFRow类、Cell类和HSSFCell类是继承关系,
1)Workbook类
Workbook workbook = WorkbookFactory.create(new File(filePath)); // 根据已有的Excel文件创建工作簿
workbook.write(out); // 工作簿写入,不加这句无法更改Excel文件
2)HSSFWorkbook类
HSSFWorkbook wb= new HSSFWorkbook();// 生成新的Excel文件
HSSFWorkbook workbook= new HSSFWorkbook(new FileInputStream(path)); // 根据已有的Excel文件创建工作簿
3)Sheet类 和 HSSFSheet类
Sheet sheet = wb.getSheetAt(sheetIndex); // 通过索引获得文件中指定sheet,从0开始
Sheet sheet = wb.getSheetAt("sheet1"); // 通过sheet名获得文件中指定sheet
Sheet sheet = wb.createSheet(String sheetname); // 创建一个新的Sheet
HSSFSheet sheet = workbook.getSheetAt(sheetIndex); // 通过索引获得文件中指定sheet,从0开始
HSSFSheet sheet = workbook.getSheetAt("sheet1"); // 通过sheet名获得文件中指定sheet
HSSFSheet sheet = workbook.createSheet("sheet1"); // 创建一个新的Sheet
int RowNum = sheet.getLastRowNum(); // 获得最大行数
sheet.addMergedRegion(new CellRangeAddress(firstRow, lastRow, firstCol, lastCol)); // 合并单元格
sheet.shiftRows(rowIndex, lastRowNo, n); // 插入某一行
4)Row类 和 HSSFRow类
Row row = sheet.getRow(i); // 获得指定行
HSSFRow row = sheet.getRow(i);
Row row = sheet.createRow(i); // 创建指定行
HSSFRow row = sheet.createRow(i); // 创建指定行
row.getCell(i); // 获得指定单元格
5)Cell类 和 HSSFCell类
cell.getRowIndex(); // 获取当前单元格的行数
cell.getColumnIndex(); // 获取当前单元格的列数
cell.setCellValue(""); // 给当前单元格赋值
cell.getRow() // 获取当前单元格所在的行对象
6)CellStyle类 和 HSSFCellStyle类
CellStyle style = wb.createCellStyle(); // 创建一个单元格格式对象
style.setFillForegroundColor(IndexedColors.PALE_BLUE.getIndex()); // 设置单元格填充颜色
style.setFillBackgroundColor(short bg); //设置背景颜色
style.setFillPattern(FillPatternType.SOLID_FOREGROUND); // 设置单元格画布格式
style.setWrapText(true); // 设置自动换行
style.setAlignment(HorizontalAlignment.CENTER); // 水平居中
style.setVerticalAlignment(VerticalAlignment.CENTER); // 垂直居中
font.setFontHeightInPoints((short) heigth); // 设置行高
style.setBorderBottom(BorderStyle.THIN); // 单元格边框
style.setBorderLeft(BorderStyle.THIN);
style.setBorderRight(BorderStyle.THIN);
style.setBorderTop(BorderStyle.THIN);
cell.setCellStyle(style); // 将单元格格式赋值给单元格
7)Font类 和 HSSFFont类
Font font = wb.createFont(); // 创建字体格式对象
font.setFontName("宋体"); // 设置字体样式
font.setFontHeightInPoints((short) 11); // 字体大小
font.setBold(boolean bold); // 设置是否粗体
font.setItalic(boolean italic); // 设置倾斜
font.setUnderline(byte underline); 设置下划线
style.setFont(font); // 将字体赋值给单元格样式(必须将字体样式赋值给单元格样式,再将单元格样式赋值给单元格对象才能生效)
二. Java 使用POI操作Excel
我写项目时将操作Excel的方法进行简单的封装,一下代码是从多个项目中提取的的通用方法,有些是项目中的需求逻辑,相信大家应该能看的出来,大家有什么错误或者补充的可以留言或私信。废话不多说直接上代码:
/**
* 搜索所有的excel,并且循环调用excel数据处理方法
*
* @throws IOException
*/
public void readFile() {
File file = new File(path);
// 获取包下所有excel文件的名称集合
String[] filelist = file.list();
for (int i = 0; i < filelist.length; i++) {
// 获取excel文件
readExcelToObj(path + "\\" + filelist[i]);
}
}
public List<List<String>> readExcelToObj(String filepath) {
HSSFWorkbook wbook = new HSSFWorkbook(new FileInputStream(path));
Workbook wb = null;
try {
wb = WorkbookFactory.create(new File(filepath));
merge = readExcel(wb, 0, 4, 0);
} catch (InvalidFormatException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
wb.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return merge;
}
/**
* 读取excel文件
*
* @param wb
* @param sheetIndex sheet页下标:从0开始
* @param startReadLine 开始读取的行:从0开始
* @param tailLine 去除最后读取的行
*/
private List<List<String>> readExcel(Workbook wb, int sheetIndex, int startReadLine, int tailLine) {
Sheet sheet = wb.getSheetAt(sheetIndex);
Sheet sheets = wb.createSheet();
Row row = null;
int MaxRowNum = sheet.getLastRowNum();
List<List<String>> result = new ArrayList<>();
for (int i = startReadLine; i < MaxRowNum - tailLine + 1; i++) {
row = sheet.getRow(i);
List<String> rowContent = new ArrayList<>();
for (Cell c : row) {
if (getCellValue(c).contains("备注:1")) {
MaxRowNum = c.getRowIndex();
c.getColumnIndex();
break;
}
rowContent.add(getCellValue(c));
}
if (!rowContent.isEmpty()) {
result.add(rowContent);
}
}
return result;
}
/**
* 读取excel文件存储为Map<String,String>
*
* @param wb
* @param sheetIndex sheet页下标:从0开始
* @param startReadLine 开始读取的行:从0开始
* @param tailLine 去除最后读取的行
*/
private Map<String, String> readExcelForMap(Workbook wb, int sheetIndex, int startReadLine, int tailLine,int flat) {
Sheet sheet = wb.getSheetAt(sheetIndex);
Row row = null;
int MaxRowNum = sheet.getLastRowNum();
Map<String, String> map = new HashMap<>();
if(flat == 0||flat== 1){
for (int i = startReadLine; i < MaxRowNum - tailLine + 1; i++) {
row = sheet.getRow(i);
if (getCellValue(row.getCell(0)).contains("备注:1.")) {
break;
}
String key = getCellValue(row.getCell(1)) + "/" + getCellValue(row.getCell(2)) + "/" + getCellValue(row.getCell(3)) + "/" + getCellValue(row.getCell(4));
String value = getCellValue(row.getCell(10));
map.put(key, value);
}
}else{
for (int i = startReadLine; i < MaxRowNum - tailLine + 1; i++) {
row = sheet.getRow(i);
String key = getCellValue(row.getCell(4))+"/"+getCellValue(row.getCell(8));
String value = getCellValue(row.getCell(17));
map.put(key, value);
}
}
System.out.println(map);
return map;
}
/**
* 读取excel文件存储为List<List<String>>
*
* @param wb
* @param sheetIndex sheet页下标:从0开始
* @param startReadLine 开始读取的行:从0开始s
* @param tailLine 去除最后读取的行
*/
private List<List<String>> readExcel(Workbook wb, int sheetIndex, int startReadLine, int tailLine, int flat) {
Sheet sheet = wb.getSheetAt(sheetIndex);
Row row = null;
int MaxRowNum = sheet.getLastRowNum();
List<List<String>> result = new ArrayList<>();
for (int i = startReadLine; i < MaxRowNum - tailLine + 1; i++) {
row = sheet.getRow(i);
if (getCellValue(row.getCell(1)) == "" && getCellValue(row.getCell(2)) == "" && getCellValue(row.getCell(3)) == "") {
continue;
}
List<String> rowContent = new ArrayList<>();
if (flat == 3 && i == 3) {
rowContent.add("序号");
} else if (flat == 3 && i > 3) {
rowContent.add(i - 3 + "");
} else if (flat == 4 && i == 0) {
rowContent.add("序号");
} else if (flat == 4 && i > 0) {
rowContent.add(i + "");
}
for (Cell hssfCell : row) {
if (flat == 1) {
if (hssfCell.getColumnIndex() < 9) {
rowContent.add(getCellValue(hssfCell));
}
} else if (flat == 2) {
if (hssfCell.getColumnIndex() == 3 || hssfCell.getColumnIndex() == 5 || hssfCell.getColumnIndex() == 9 || hssfCell.getColumnIndex() == 11) {
rowContent.add(getCellValue(hssfCell));
}
} else if (flat == 3) {
rowContent.add(getCellValue(hssfCell));
} else {
rowContent.add(getCellValue(hssfCell));
}
}
result.add(rowContent);
}
return result;
}
/**
* 找到需要插入的行数,并新建一个POI的row对象
*
* @param sheet
* @param rowIndex
* @return
*/
private HSSFRow createRow(HSSFSheet sheet,Integer rowIndex,int n) {
HSSFRow row = null;
if (sheet.getRow(rowIndex) != null) {
int lastRowNo = sheet.getLastRowNum();
sheet.shiftRows(rowIndex, lastRowNo, n);
}
row = sheet.createRow(rowIndex);
return row;
}
/**
* 保存工作薄
*
* @param wb
*/
private void saveExcel(HSSFWorkbook wb,String fileToBeRead) {
FileOutputStream fileOut;
try {
fileOut = new FileOutputStream(fileToBeRead);
wb.write(fileOut);
fileOut.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 获取单元格的值
*
* @param cell
* @return
*/
public String getCellValue(Cell cell) {
if (cell == null) return "";
if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
return cell.getStringCellValue();
} else if (cell.getCellType() == Cell.CELL_TYPE_BOOLEAN) {
return String.valueOf(cell.getBooleanCellValue());
} else if (cell.getCellType() == Cell.CELL_TYPE_FORMULA) {
return cell.getCellFormula();
} else if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
return String.valueOf((int) cell.getNumericCellValue());
}
return "";
}
/**
* 判断指定的单元格是否是合并单元格
*
* @param sheet
* @param row 行下标
* @param column 列下标
* @return
*/
private boolean isMergedRegion(Sheet sheet, int row, int column) {
int sheetMergeCount = sheet.getNumMergedRegions();
for (int i = 0; i < sheetMergeCount; i++) {
CellRangeAddress range = sheet.getMergedRegion(i);
int firstColumn = range.getFirstColumn();
int lastColumn = range.getLastColumn();
int firstRow = range.getFirstRow();
int lastRow = range.getLastRow();
if (row >= firstRow && row <= lastRow) {
if (column >= firstColumn && column <= lastColumn) {
return true;
}
}
}
return false;
}
/**
* 获取合并单元格的值
*
* @param sheet
* @param row
* @param column
* @return
*/
public String getMergedRegionValue(Sheet sheet, int row, int column) {
int sheetMergeCount = sheet.getNumMergedRegions();
for (int i = 0; i < sheetMergeCount; i++) {
CellRangeAddress ca = sheet.getMergedRegion(i);
int firstColumn = ca.getFirstColumn();
int lastColumn = ca.getLastColumn();
int firstRow = ca.getFirstRow();
int lastRow = ca.getLastRow();
if (row >= firstRow && row <= lastRow) {
if (column >= firstColumn && column <= lastColumn) {
Row fRow = sheet.getRow(firstRow);
Cell fCell = fRow.getCell(firstColumn);
return getCellValue(fCell);
}
}
}
return null;
}
/**
* 设置字体样式
*
* @param heigth
* @param font
* @param style
* @param cell
*/
public void setFontStyle(int heigth, HSSFFont font, HSSFCellStyle style, HSSFCell cell) {
font.setFontName("宋体");
font.setFontHeightInPoints((short) heigth);
style.setFont(font);
cell.setCellStyle(style);
}
public static void setHeadStyle(CellStyle style, HSSFCell cell) {
style.setWrapText(true);
style.setVerticalAlignment(VerticalAlignment.CENTER);
style.setAlignment(HorizontalAlignment.CENTER);
style.setBorderBottom(BorderStyle.THIN);
style.setBorderLeft(BorderStyle.THIN);
style.setBorderRight(BorderStyle.THIN);
style.setBorderTop(BorderStyle.THIN);
cell.setCellStyle(style);
}
/**
* 复制一个单元格样式到目的单元格样式
* @param fromStyle
* @param toStyle
*/
public static void copyCellStyle(HSSFCellStyle fromStyle,
HSSFCellStyle toStyle) {
toStyle.setAlignment(fromStyle.getAlignmentEnum());
//边框和边框颜色
toStyle.setBorderBottom(fromStyle.getBorderBottomEnum());
toStyle.setBorderLeft(fromStyle.getBorderLeftEnum());
toStyle.setBorderRight(fromStyle.getBorderRightEnum());
toStyle.setBorderTop(fromStyle.getBorderTopEnum());
toStyle.setTopBorderColor(fromStyle.getTopBorderColor());
toStyle.setBottomBorderColor(fromStyle.getBottomBorderColor());
toStyle.setRightBorderColor(fromStyle.getRightBorderColor());
toStyle.setLeftBorderColor(fromStyle.getLeftBorderColor());
toStyle.setDataFormat(fromStyle.getDataFormat());
toStyle.setFillPattern(fromStyle.getFillPatternEnum());
// toStyle.setFont(fromStyle.getFont(null));
toStyle.setHidden(fromStyle.getHidden());
toStyle.setIndention(fromStyle.getIndention());//首行缩进
toStyle.setLocked(fromStyle.getLocked());
toStyle.setRotation(fromStyle.getRotation());//旋转
toStyle.setVerticalAlignment(fromStyle.getVerticalAlignmentEnum());
toStyle.setWrapText(fromStyle.getWrapText());
}
三. 结语
这是我毕业刚入职第一天的第一个任务,在完全没学过,甚至没听过的情况下,能将功能一个一个实现出来,感觉还是挺有帮助的,希望以后能继续保持学习进步的精神。毕竟有句话说的好,真正的大师永远保持一颗学徒(学秃)的心,我离大师还很远很远,但是我会朝着这个方向一直走下去。