java读写excel(POI,支持xls和xlsx两种格式)
Posted Augus6
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java读写excel(POI,支持xls和xlsx两种格式)相关的知识,希望对你有一定的参考价值。
这应该是一个比较全的示例了,更加复杂的功能可以在此基础上扩展。此示例基于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(); } } }
以上是关于java读写excel(POI,支持xls和xlsx两种格式)的主要内容,如果未能解决你的问题,请参考以下文章