java讀寫excel(POI,支援xls和xlsx兩種格式)
阿新 • • 發佈:2019-01-04
這應該是一個比較全的示例了,更加複雜的功能可以在此基礎上擴充套件。此示例基於apache的POI類庫,相關jar包就不列舉了。這個類庫很通用,網上很好找。
1、不包含單元格合併的寫excel
/** * excel匯出到輸出流 * 誰呼叫誰負責關閉輸出流 * @param os 輸出流 * @param excelExtName excel檔案的副檔名,支援xls和xlsx,不帶點號 * @param data * @throws IOException */ public static void writeExcel(OutputStream os, String excelExtName, Map<String, List<List<String>>> data) throws IOException{ Workbook wb = null; try { if ("xls".equals(excelExtName)) { wb = new HSSFWorkbook(); } else if ("xlsx".equals(excelExtName)) { wb = new XSSFWorkbook(); } else { throw new Exception("當前檔案不是excel檔案"); } for (String sheetName : data.keySet()) { Sheet sheet = wb.createSheet(sheetName); List<List<String>> rowList = data.get(sheetName); for (int i = 0; i < rowList.size(); i++) { List<String> cellList = rowList.get(i); Row row = sheet.createRow(i); for (int j = 0; j < cellList.size(); j++) { Cell cell = row.createCell(j); cell.setCellValue(cellList.get(j)); } } } wb.write(os); } catch (Exception e) { e.printStackTrace(); } finally { if (wb != null) { wb.close(); } } }
2、包含單元格合併的寫excel
輔助vo
class ExcelData{ private String value;//單元格的值 private int colSpan = 1;//單元格跨幾列 private int rowSpan = 1;//單元格跨幾行 private boolean alignCenter;//單元格是否居中,預設不居中,如果選擇是,則水平和上下都居中 public boolean isAlignCenter() { return alignCenter; } public void setAlignCenter(boolean alignCenter) { this.alignCenter = alignCenter; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } public int getColSpan() { return colSpan; } public void setColSpan(int colSpan) { this.colSpan = colSpan; } public int getRowSpan() { return rowSpan; } public void setRowSpan(int rowSpan) { this.rowSpan = rowSpan; } }
寫excel檔案的邏輯
/** * excel匯出到輸出流 * 誰呼叫誰負責關閉輸出流 * @param os 輸出流 * @param excelExtName excel檔案的副檔名,支援xls和xlsx,不帶點號 * @param data excel資料,map中的key是標籤頁的名稱,value對應的list是標籤頁中的資料。list中的子list是標籤頁中的一行,子list中的物件是一個單元格的資料,包括是否居中、跨幾行幾列以及存的值是多少 * @throws IOException */ public static void testWrite(OutputStream os, String excelExtName, Map<String, List<List<ExcelData>>> data) throws IOException{ Workbook wb = null; CellStyle cellStyle = null; boolean isXls; try { if ("xls".equals(excelExtName)) { wb = new HSSFWorkbook(); isXls = true; } else if ("xlsx".equals(excelExtName)) { wb = new XSSFWorkbook(); isXls = false; } else { throw new Exception("當前檔案不是excel檔案"); } cellStyle = wb.createCellStyle(); if (isXls) { cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); } else { cellStyle.setAlignment(XSSFCellStyle.ALIGN_CENTER); cellStyle.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER); } for (String sheetName : data.keySet()) { Sheet sheet = wb.createSheet(sheetName); List<List<ExcelData>> rowList = data.get(sheetName); //i 代表第幾行 從0開始 for (int i = 0; i < rowList.size(); i++) { List<ExcelData> cellList = rowList.get(i); Row row = sheet.createRow(i); int j = 0;//j 代表第幾列 從0開始 for (ExcelData excelData : cellList) { if (excelData != null) { if (excelData.getColSpan() > 1 || excelData.getRowSpan() > 1) { CellRangeAddress cra = new CellRangeAddress(i, i + excelData.getRowSpan() - 1, j, j + excelData.getColSpan() - 1); sheet.addMergedRegion(cra); } Cell cell = row.createCell(j); cell.setCellValue(excelData.getValue()); if (excelData.isAlignCenter()) { cell.setCellStyle(cellStyle); } j = j + excelData.getColSpan(); } else { j++; } } } } wb.write(os); } catch (Exception e) { e.printStackTrace(); } finally { if (wb != null) { wb.close(); } } }
測試程式碼
public static void main(String[] args) throws IOException {
Map<String, List<List<ExcelData>>> data = new LinkedHashMap<>();
List<List<ExcelData>> sheet1 = new ArrayList<>();//第一頁
List<ExcelData> list1 = new ArrayList<>();//第一行
ExcelData excelData = new ExcelData();//第一個單元格
excelData.setColSpan(6);
excelData.setRowSpan(1);
excelData.setValue("xxx");
excelData.setAlignCenter(true);
list1.add(excelData);
List<ExcelData> list2 = new ArrayList<>();//第二行
excelData = new ExcelData();//第一個單元格
excelData.setColSpan(1);
excelData.setRowSpan(1);
excelData.setValue("a");
list2.add(excelData);
excelData = new ExcelData();//第二個單元格
excelData.setColSpan(1);
excelData.setRowSpan(1);
excelData.setValue("b");
list2.add(excelData);
excelData = new ExcelData();//第三個單元格
excelData.setColSpan(2);
excelData.setRowSpan(4);
excelData.setValue("c");
excelData.setAlignCenter(true);
list2.add(excelData);
excelData = new ExcelData();//第四個單元格
excelData.setColSpan(2);
excelData.setRowSpan(2);
excelData.setValue("d");
excelData.setAlignCenter(true);
list2.add(excelData);
List<ExcelData> list3 = new ArrayList<>();//第三行
excelData = new ExcelData();//第一個單元格
excelData.setColSpan(1);
excelData.setRowSpan(1);
excelData.setValue("e");
list3.add(excelData);
excelData = new ExcelData();//第二個單元格
excelData.setColSpan(1);
excelData.setRowSpan(1);
excelData.setValue("f");
list3.add(excelData);
list3.add(null);//第三個單元格
list3.add(null);//第四個單元格
list3.add(null);//第五個單元格
list3.add(null);//第六個單元格
List<ExcelData> list4 = new ArrayList<>();//第四行
excelData = new ExcelData();//第一個單元格
excelData.setColSpan(1);
excelData.setRowSpan(1);
excelData.setValue("i");
list4.add(excelData);
excelData = new ExcelData();//第二個單元格
excelData.setColSpan(1);
excelData.setRowSpan(1);
excelData.setValue("j");
list4.add(excelData);
list4.add(null);//第三個單元格
list4.add(null);//第四個單元格
excelData = new ExcelData();//第五個單元格
excelData.setRowSpan(1);
excelData.setColSpan(1);
excelData.setValue("g");
list4.add(excelData);
excelData = new ExcelData();//第六個單元格
excelData.setRowSpan(1);
excelData.setColSpan(1);
excelData.setValue("h");
list4.add(excelData);
List<ExcelData> list5 = new ArrayList<>();//第五行
excelData = new ExcelData();//第一個單元格
excelData.setColSpan(1);
excelData.setRowSpan(1);
excelData.setValue("k");
list5.add(excelData);
excelData = new ExcelData();//第二個單元格
excelData.setColSpan(1);
excelData.setRowSpan(1);
excelData.setValue("l");
list5.add(excelData);
list5.add(null);//第三個單元格
list5.add(null);//第四個單元格
excelData = new ExcelData();//第五個單元格
excelData.setRowSpan(1);
excelData.setColSpan(1);
excelData.setValue("m");
list5.add(excelData);
excelData = new ExcelData();//第六個單元格
excelData.setRowSpan(1);
excelData.setColSpan(1);
excelData.setValue("n");
list5.add(excelData);
sheet1.add(list1);
sheet1.add(list2);
sheet1.add(list3);
sheet1.add(list4);
sheet1.add(list5);
data.put("表1", sheet1);
testWrite(new FileOutputStream(new File("D:/temp/my.xlsx")), "xlsx", data);
}
}
3、讀取excel,這個方法的返回值帶有一點業務邏輯,適用於沒有單元格合併的excel,並且第一行是title的情況。返回的結果中,把第一行之外的每一個單元格包裝成一個map,key是這個單元格的第一行的數值,也就是標題,value是這個單元格的值。邏輯有些繞,直接看程式碼。
/**
* 適用於第一行是標題行的excel,例如
* 姓名 年齡 性別 身高
* 張三 25 男 175
* 李四 22 女 160
* 每一行構成一個map,key值是列標題,value是列值。沒有值的單元格其value值為null
* 返回結果最外層的list對應一個excel檔案,第二層的list對應一個sheet頁,第三層的map對應sheet頁中的一行
* @throws Exception
*/
public static List<List<Map<String, String>>> readExcelWithTitle(String filepath) throws Exception{
String fileType = filepath.substring(filepath.lastIndexOf(".") + 1, filepath.length());
InputStream is = null;
Workbook wb = null;
try {
is = new FileInputStream(filepath);
if (fileType.equals("xls")) {
wb = new HSSFWorkbook(is);
} else if (fileType.equals("xlsx")) {
wb = new XSSFWorkbook(is);
} else {
throw new Exception("讀取的不是excel檔案");
}
List<List<Map<String, String>>> result = new ArrayList<List<Map<String,String>>>();//對應excel檔案
int sheetSize = wb.getNumberOfSheets();
for (int i = 0; i < sheetSize; i++) {//遍歷sheet頁
Sheet sheet = wb.getSheetAt(i);
List<Map<String, String>> sheetList = new ArrayList<Map<String, String>>();//對應sheet頁
List<String> titles = new ArrayList<String>();//放置所有的標題
int rowSize = sheet.getLastRowNum() + 1;
for (int j = 0; j < rowSize; j++) {//遍歷行
Row row = sheet.getRow(j);
if (row == null) {//略過空行
continue;
}
int cellSize = row.getLastCellNum();//行中有多少個單元格,也就是有多少列
if (j == 0) {//第一行是標題行
for (int k = 0; k < cellSize; k++) {
Cell cell = row.getCell(k);
titles.add(cell.toString());
}
} else {//其他行是資料行
Map<String, String> rowMap = new HashMap<String, String>();//對應一個數據行
for (int k = 0; k < titles.size(); k++) {
Cell cell = row.getCell(k);
String key = titles.get(k);
String value = null;
if (cell != null) {
value = cell.toString();
}
rowMap.put(key, value);
}
sheetList.add(rowMap);
}
}
result.add(sheetList);
}
return result;
} catch (FileNotFoundException e) {
throw e;
} finally {
if (wb != null) {
wb.close();
}
if (is != null) {
is.close();
}
}
}
4、讀取excel,適合於沒有合併單元格且沒有標題行的情況
/**
* 適用於沒有標題行的excel,例如
* 張三 25歲 男 175cm
* 李四 22歲 女 160cm
* 每一行構成一個map,key值是列標題,value是列值。沒有值的單元格其value值為null
* 返回結果最外層的list對應一個excel檔案,第二層的list對應一個sheet頁,第三層的map對應sheet頁中的一行
* @throws Exception
*/
public static List<List<List<String>>> readExcelWithoutTitle(String filepath) throws Exception{
String fileType = filepath.substring(filepath.lastIndexOf(".") + 1, filepath.length());
InputStream is = null;
Workbook wb = null;
try {
is = new FileInputStream(filepath);
if (fileType.equals("xls")) {
wb = new HSSFWorkbook(is);
} else if (fileType.equals("xlsx")) {
wb = new XSSFWorkbook(is);
} else {
throw new Exception("讀取的不是excel檔案");
}
List<List<List<String>>> result = new ArrayList<List<List<String>>>();//對應excel檔案
int sheetSize = wb.getNumberOfSheets();
for (int i = 0; i < sheetSize; i++) {//遍歷sheet頁
Sheet sheet = wb.getSheetAt(i);
List<List<String>> sheetList = new ArrayList<List<String>>();//對應sheet頁
int rowSize = sheet.getLastRowNum() + 1;
for (int j = 0; j < rowSize; j++) {//遍歷行
Row row = sheet.getRow(j);
if (row == null) {//略過空行
continue;
}
int cellSize = row.getLastCellNum();//行中有多少個單元格,也就是有多少列
List<String> rowList = new ArrayList<String>();//對應一個數據行
for (int k = 0; k < cellSize; k++) {
Cell cell = row.getCell(k);
String value = null;
if (cell != null) {
value = cell.toString();
}
rowList.add(value);
}
sheetList.add(rowList);
}
result.add(sheetList);
}
return result;
} catch (FileNotFoundException e) {
throw e;
} finally {
if (wb != null) {
wb.close();
}
if (is != null) {
is.close();
}
}
}