特点:
支持xls、xlsx格式;
导出时支持自定义表格标题和表格数据,支持一个文档里多个Sheet;
依赖:
<!--excel util--> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>4.1.2</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.1.2</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml-schemas</artifactId> <version>4.1.2</version> </dependency>
maven
代码:
/** 工具类,用于将数据导出到excel文件(可以导出到一个文件的多个Sheet) 或 从excel文件读取数据 */ @Slf4j public class ExcelUtil { public static void main(String[] args) throws IOException { String fileName = "test.xls"; exportExcel( Arrays.asList( new SheetInfo<StuExpDownloadVO>( "class1", ("用户名, 姓名, 完成情况, 得分, 评语").split(","), Arrays.asList(new StuExpDownloadVO("zhangsna", "张三", "未开始", 22.0, "good"), new StuExpDownloadVO("lisi", "李四", "进行中", 21.0, "bad")) ), new SheetInfo<StuExpDownloadVO>( "class2", ("用户名, 姓名, 完成情况").split(","), Arrays.asList(new StuExpDownloadVO("wangwu", "王五", "已完成", 20.0, "good"), new StuExpDownloadVO("zhaoliu", "赵六", "未开始", 19.0, "bad")) ) ), Files.newOutputStream(Paths.get("a.xls"))); exportExcel( ("用户名, 姓名, 完成情况, 得分, 评语").split(","), Arrays.asList(new StuExpDownloadVO("zhangsna", "张三", "未开始", 22.0, "good"), new StuExpDownloadVO("lisi", "李四", "进行中", 21.0, "bad")), Files.newOutputStream(Paths.get("b.xls"))); } private ExcelUtil() { } private static final String datetimeFormat = "yyyy-MM-dd HH:mm:ss"; /** * @see {@link #exportExcel(String[] headers, Collection dataset, OutputStream out, String datetimeFormat) } */ public static <T> void exportExcel(String[] headers, Collection<T> dataSet, OutputStream out) { exportExcel(headers, dataSet, out, datetimeFormat); } /** * 利用JAVA的反射机制,将放置在JAVA集合中并且符合一定条件的数据以EXCEL的形式输出到指定输出流。<br> * <br> * <b>输出后会关闭输出流</b> * * @param headers 表格属性列名数组。注意:数组中列名的顺序须与待导出的javabean属性的定义顺序一致 * @param dataset 需要显示的数据集合,集合中java bean对象的所有非继承属性的值均会被输出。此方法支持的 * javabean属性的数据类型有基本数据类型及String,Date,byte[](图片数据) * @param out 与输出设备关联的流对象,可以将 EXCEL 文档导出到本地文件或者网络中 * @param datetimeFormat 如果有时间数据,设定输出格式。 */ public static <T> void exportExcel(String[] headers, Collection<T> dataset, OutputStream out, String datetimeFormat) { exportExcel(Arrays.asList(new SheetInfo("sheet 0", headers, dataset)), out, datetimeFormat); } public static <T> void exportExcel(List<SheetInfo<T>> sheetInfos, OutputStream out) { exportExcel(sheetInfos, out, datetimeFormat); } /** * 利用JAVA的反射机制,将放置在JAVA集合中并且符合一定条件的数据以EXCEL的形式输出到指定输出流。<br> * <br> * <b>输出后会关闭输出流</b> * * @param sheetInfos EXCEL 文档中的Sheet信息定义 * @param out 与输出设备关联的流对象,可以将 EXCEL 文档导出到本地文件或者网络中 * @param datetimeFormat 如果有时间数据,设定输出格式。 */ public static <T> void exportExcel(List<SheetInfo<T>> sheetInfos, OutputStream out, String datetimeFormat) { sheetInfos = Optional.ofNullable(sheetInfos).orElse(Collections.emptyList()); // 生成Excel文档 Workbook workbook = generateWorkbook(); // 生成表头样式 CellStyle tableHeaderStyle = generateTableHeaderStyle(workbook); // 生成表体样式 CellStyle tableBodyStyle = generateTableBodyStyle(workbook); // 时间值格式化工具 DateTimeFormatter sdf = DateTimeFormatter.ofPattern(datetimeFormat); // 生成Excel文档中的sheet for (int siIndex = 0; siIndex < sheetInfos.size(); siIndex++) { SheetInfo sheetInfo = sheetInfos.get(siIndex); String[] headers = sheetInfo.getHeaders(); //创建sheet Sheet sheet = workbook.createSheet(); workbook.setSheetName(siIndex, sheetInfo.getName()); sheet.setDefaultColumnWidth(18); // 声明一个绘制图片的顶级管理器 Drawing patriarch = sheet.createDrawingPatriarch(); // 定义注释的大小和位置 // HSSFComment comment = patriarch.createComment(new HSSFClientAnchor(0, // 0, 0, 0, (short) 4, 2, (short) 6, 5)); // 设置注释内容 // comment.setString(new HSSFRichTextString("可以在POI中添加注释!")); // 设置注释作者,当鼠标移动到单元格上是可以在状态栏中看到该内容. // comment.setAuthor("sensetime"); // 填充表格标题行 int rowIndex = 0; Row row = sheet.createRow(rowIndex); for (int i = 0; i < headers.length; i++) { Cell cell = row.createCell(i); cell.setCellStyle(tableHeaderStyle); cell.setCellValue(generateRichTextString(headers[i])); } rowIndex++; // 填充表格数据行 Iterator<T> rowDataIt = sheetInfo.getDataset().iterator(); Field[] fields = null; while (rowDataIt.hasNext()) { row = sheet.createRow(rowIndex); T t = (T) rowDataIt.next(); // 利用反射,根据javabean属性的先后顺序,动态调用getXxx()方法得到属性值 if (null == fields) { fields = t.getClass().getDeclaredFields(); } for (int i = 0; i < fields.length && i < headers.length; i++) { //HSSFCell cell = row.createCell(i); Cell cell = row.createCell(i); cell.setCellStyle(tableBodyStyle); Field field = fields[i]; field.setAccessible(true); try { Object value = field.get(t); // 判断值的类型后进行强制类型转换 String textValue = null; // if (value instanceof Integer) { // int intValue = (Integer) value; // cell.setCellValue(intValue); // } else if (value instanceof Float) { // float fValue = (Float) value; // textValue = new HSSFRichTextString( // String.valueOf(fValue)); // cell.setCellValue(textValue); // } else if (value instanceof Double) { // double dValue = (Double) value; // textValue = new HSSFRichTextString( // String.valueOf(dValue)); // cell.setCellValue(textValue); // } else if (value instanceof Long) { // long longValue = (Long) value; // cell.setCellValue(longValue); // } if (value == null) { textValue = ""; } else if (value instanceof Date) { Date date = (Date) value; textValue = sdf.format(date.toInstant()); } else if (value instanceof byte[]) { // 有图片时,设置行高为60px; row.setHeightInPoints(60); // 设置图片所在列宽度为80px,注意这里单位的一个换算 sheet.setColumnWidth(i, (short) (35.7 * 80)); sheet.autoSizeColumn(i); byte[] bsValue = (byte[]) value; HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0, 1023, 255, (short) 6, rowIndex, (short) 6, rowIndex); anchor.setAnchorType(ClientAnchor.AnchorType.byId(2)); patriarch.createPicture(anchor, workbook.addPicture(bsValue, HSSFWorkbook.PICTURE_TYPE_JPEG)); } else { // 其它数据类型都当作字符串简单处理 textValue = value.toString(); } // 如果不是图片数据,就利用正则表达式判断textValue是否全部由数字组成 if (textValue != null) { Pattern p = Pattern.compile("^//d+(//.//d+)?$"); Matcher matcher = p.matcher(textValue); if (matcher.matches()) { // 是数字则当作double处理 cell.setCellValue(Double.parseDouble(textValue)); } else { cell.setCellValue(generateRichTextString(textValue)); } } } catch (Exception e) { log.error(e.getMessage(), e); } } rowIndex++; } } try { workbook.write(out); } catch (IOException e) { log.error(e.getMessage(), e); } finally {// 清理资源 if (null != workbook) { try { workbook.close(); } catch (IOException e) { log.error(e.getMessage(), e); } } if (null != out) { try { out.close(); } catch (IOException e) { log.error(e.getMessage(), e); } } } } /** * 读取excel文件内容,存入到字节流。每行结尾加了换行符,一行中各字段后跟一逗号来分隔 */ public static ByteArrayInputStream importExcel(InputStream in, int sheetIndex) throws InvalidFormatException, IOException, InstantiationException, IllegalAccessException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); try (Workbook workbook = generateWorkbookFromInputStream(in)) { Sheet sheet = workbook.getSheetAt(sheetIndex); for (int ri = sheet.getFirstRowNum(); ri <= sheet.getLastRowNum(); ri++) { Row row = sheet.getRow(ri); for (int ci = row.getFirstCellNum(); ci < row.getLastCellNum(); ci++) { Cell cell = row.getCell(ci); String value = getValue(cell) + ", "; baos.write(value.getBytes()); // System.out.printf("%s ", value); } baos.write("/n".getBytes()); // System.out.println(""); } } catch (Exception e) { log.error(e.getMessage(), e); } ; return new ByteArrayInputStream(baos.toByteArray()); } private static String getValue(Cell cell) { if (cell.getCellType() == CellType.BOOLEAN) { // 返回布尔类型的值 return String.valueOf(cell.getBooleanCellValue()); } else if (cell.getCellType() == CellType.NUMERIC) { // 返回数值类型的值 return String.valueOf(cell.getNumericCellValue()); } else { // 返回字符串类型的值 return String.valueOf(cell.getStringCellValue()); } } /** * excepl 文档中的一个Sheet的信息定义 */ @Data @AllArgsConstructor public static class SheetInfo<T> { private String name;//表格名称 private String[] headers;//表格列名 private Collection<T> dataset;//表格数据,每个元素代表一行 } //以下为为了同时兼容 xls、xlsx 格式的excel文档而定义的方法 /** * 是否生成xlsx文档,为true则生成xlsx格式的文档(Excel2007及以后的版本,扩展名是.xlsx)、否则生成xls格式的文档(Excel2003及以前的版本,扩展名是.xls)。 */ private static final boolean USE_XLSX = true; private static RichTextString generateRichTextString(String val) { RichTextString res = USE_XLSX ? new XSSFRichTextString(val) : new HSSFRichTextString(val); //res.applyFont(new xx); return res; } /** * 创建一个excel文档 */ private static Workbook generateWorkbook() { //HSSFWorkbook:是操作Excel2003以前(包括2003)的版本,扩展名是.xls //XSSFWorkbook:是操作Excel2007的版本,扩展名是.xlsx Workbook res = USE_XLSX ? new XSSFWorkbook() : new HSSFWorkbook(); return res; } /** * 创建一个excel文档 */ private static Workbook generateWorkbookFromInputStream(InputStream in) throws IOException { //HSSFWorkbook:是操作Excel2003以前(包括2003)的版本,扩展名是.xls //XSSFWorkbook:是操作Excel2007的版本,扩展名是.xlsx Workbook res = USE_XLSX ? new XSSFWorkbook(in) : new HSSFWorkbook(in); return res; } private static CellStyle generateTableHeaderStyle(Workbook workbook) { CellStyle style = workbook.createCellStyle(); style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); style.setFillPattern(FillPatternType.SOLID_FOREGROUND); style.setBorderBottom(BorderStyle.THIN); style.setBorderLeft(BorderStyle.THIN); style.setBorderRight(BorderStyle.THIN); style.setBorderTop(BorderStyle.THIN); style.setAlignment(HorizontalAlignment.CENTER); Font font = workbook.createFont(); font.setColor(IndexedColors.WHITE.getIndex()); font.setFontHeightInPoints((short) 12); //font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); style.setFont(font); return style; } private static CellStyle generateTableBodyStyle(Workbook workbook) { CellStyle style = workbook.createCellStyle(); style.setFillForegroundColor(IndexedColors.WHITE.getIndex()); style.setFillPattern(FillPatternType.SOLID_FOREGROUND); style.setBorderBottom(BorderStyle.THIN); style.setBorderLeft(BorderStyle.THIN); style.setBorderRight(BorderStyle.THIN); style.setBorderTop(BorderStyle.THIN); style.setAlignment(HorizontalAlignment.CENTER); style.setVerticalAlignment(VerticalAlignment.CENTER); Font font = workbook.createFont(); font.setColor(IndexedColors.GREY_80_PERCENT.index); //font2.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL); style.setFont(font); return style; } }
ExcelUtil
原创文章,作者:bd101bd101,如若转载,请注明出处:https://blog.ytso.com/274577.html