详解java封装实现Excel建表读写操作

对 Excel 进行读写操作是生产环境下常见的业务,网上搜索的实现方式都是基于POI和JXL第三方框架,但都不是很全面。小编由于这两天刚好需要用到,于是就参考手写了一个封装操作工具,基本涵盖了Excel表(分有表头和无表头)的创建,并对它们进行读写操作。为方便大家,有需要者可以点击文后点解下载直接使用哦,当然也可以根据自己需求举一反三自己定制,相信对于聪明的你也不是什么难事。话不多说,直接贴源码

pom.xml 文件:

<properties>
 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 <maven.compiler.source>1.8</maven.compiler.source>
 <maven.compiler.target>1.8</maven.compiler.target>
 </properties>

 <dependencies>
 <dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.11</version>
  <scope>test</scope>
 </dependency>
 <dependency>
  <groupId>org.apache.poi</groupId>
  <artifactId>poi</artifactId>
  <version>3.17</version>
 </dependency>
 <dependency>
  <groupId>org.projectlombok</groupId>
  <artifactId>lombok</artifactId>
  <version>1.18.0</version>
  <scope>provided</scope>
 </dependency>
 <dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-log4j12</artifactId>
  <version>1.8.0-beta2</version>
  <scope>test</scope>
 </dependency>
 <dependency>
  <groupId>log4j</groupId>
  <artifactId>log4j</artifactId>
  <version>1.2.17</version>
 </dependency>
 <dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-api</artifactId>
  <version>1.8.0-beta2</version>
 </dependency>
 </dependencies>

建表工具类:ExcelBuider.java

/**
   * 建表工具类
   * @author Sherman
   * email:1253950375@qq.com
   * created in 2018/8/24
   */
  @Slf4j
  public class ExcelBuilder {

   private static HSSFSheet sheet;
   private static HSSFWorkbook wb;
   private static boolean hasHeader;

   /**
    * 初始化
    * @param excellName 表名
    */
   public ExcelBuilder(String excellName) {
    wb = new HSSFWorkbook();
    sheet = wb.createSheet(excellName);
   }

   /**
    * 设置表头,装配表头数据
    * @param value 字符串数组,用来作为表头的值
    *
    */
   public ExcelBuilder header(String... value) {
    if (value != null && value.length != 0) {
     //设置表头样式
     HSSFCellStyle cellStyle = wb.createCellStyle();
     cellStyle.setFont(font("黑体", true, 12));
     HSSFRow row = sheet.createRow(0);
     for (int i = 0; i < value.length; i++) {
      HSSFCell cell = row.createCell(i);
      cell.setCellValue(value[i]);
      cell.setCellStyle(cellStyle);
     }
     hasHeader = true;
    }
    return this;
 }

 /**
  * excel 表内容装配
  * @param content 待装配表格内容的二维数组
  * @return
  */
 public ExcelBuilder content(List<List<Object>> content) {
  if (content != null && !content.isEmpty()) {
   int index;
   for (int i = 0; i < content.size(); i++) {
    index = hasHeader == false ? i : i + 1;
    HSSFRow row = sheet.createRow(index);
    for (int j = 0; j < content.get(i).size(); j++) {
     String r = "";
     Object value = content.get(i).get(j);
     //根据数据类型装配
     if (value instanceof String) {
      r = (String) value;
     } else if (value instanceof Number) {
      r = String.valueOf(value);
     } else if (value instanceof BigDecimal) {
      r = String.valueOf(value);
     } else {
      if (!(value instanceof Date) && !(value instanceof Timestamp)) {
       if (!(value instanceof ZonedDateTime) && !(value instanceof LocalDateTime)) {
        if (value instanceof Enum) {
         r = ((Enum) value).name();
        } else if (value != null) {

         log.info("Error of create row, Unknow field type: " + value.getClass().getName());
        }
       } else {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        r = formatter.format((TemporalAccessor) value);
       }
      } else {
       DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
       r = sdf.format(value);
      }
     }

     row.createCell(j).setCellValue(r);
    }
   }
  }
  return this;
 }

 /**
  * 自动调整列宽大小
  */
 public ExcelBuilder autoColumnWidth() {
  for (int j = 0; j < sheet.getRow(0).getLastCellNum(); j++) {
   int maxLength = 0;
   for (int i = 0; i <= sheet.getLastRowNum(); i++) {
    String value = sheet.getRow(i).getCell(j).getStringCellValue();
    int length = 0;
    if (value != null) {
     length = value.getBytes().length;
    }
    if (length > maxLength) {
     maxLength = length;
    }
   }
   sheet.setColumnWidth(j, maxLength > 30 ? (30 * 256 + 186) : (maxLength * 256 + 186));
  }
  return this;
 }

 /**
  * 实例化
  * @param hasHeader 是否有表头
  * @return Excel表格
  */
 public AbstractExcel build(Boolean hasHeader) {
  return hasHeader ? new HeaderExcel(sheet) : new NoHeaderExcel(sheet);
 }

 /**
  *
  * @param fontName 字体名字
  * @param isBold 是否粗体
  * @param fontSize 字体大小
  * @return 字体
  */
 private HSSFFont font(String fontName, boolean isBold, int fontSize) {
  HSSFFont font = wb.createFont();
  if (fontName != null) font.setFontName(fontName);
  else font.setFontName("黑体");
  font.setBold(isBold);
  font.setFontHeightInPoints((short) fontSize);
  return font;
 }

}

excel的抽象父类:

/**
 * @author Sherman
 * created in 2018/8/24
 */

public abstract class AbstractExcel {
 private final HSSFSheet sheet;

 public AbstractExcel() {
  HSSFWorkbook wb = new HSSFWorkbook();
  sheet = wb.createSheet();
 }

 public AbstractExcel(String sheetName){
  HSSFWorkbook wb = new HSSFWorkbook();
  sheet = wb.createSheet(sheetName);
 }

 public AbstractExcel(HSSFSheet sheet) {
  this.sheet = sheet;
 }

 public abstract List<Map<String, String>> getPayload();

 public void write(OutputStream op) throws IOException {
  sheet.getWorkbook().write(op);
  sheet.getWorkbook().close();
 }

 public String getStringFormatCellValue(HSSFCell cell) {
  String cellVal = "";
  DecimalFormat df = new DecimalFormat("#");
  switch (cell.getCellTypeEnum()) {
   case STRING:
    cellVal = cell.getStringCellValue();
    break;
   case NUMERIC:
    String dataFormat = cell.getCellStyle().getDataFormatString();
    if (DateUtil.isCellDateFormatted(cell)) {
     cellVal = df.format(cell.getDateCellValue());
    } else if ("@".equals(dataFormat)) {
     cellVal = df.format(cell.getNumericCellValue());
    } else {
     cellVal = String.valueOf(cell.getNumericCellValue());
     df = new DecimalFormat("#.#########");
     cellVal = df.format(Double.valueOf(cellVal));
    }
    break;
   case BOOLEAN:
    cellVal = String.valueOf(cell.getBooleanCellValue());
    break;
   case FORMULA:
    cellVal = String.valueOf(cell.getCellFormula());
    break;
   default:
    cellVal = "";
  }
  return cellVal;
 }

}

有表头实现类

/**
 * @author Sherman
 * created in 2018/8/24
 */

public class HeaderExcel extends AbstractExcel {
 private final static boolean hasHeader = true;
 private final HSSFSheet sheet;

 public HeaderExcel(HSSFSheet sheet) {
  super(sheet);
  this.sheet = sheet;
 }

 public HeaderExcel(String sheetName, String excelPath) {
  HSSFWorkbook wb = null;
  try {
   wb = new HSSFWorkbook(new POIFSFileSystem(new FileInputStream(excelPath)));
  } catch (IOException e) {
   e.printStackTrace();
  }
  sheet = sheetName == null || sheetName.isEmpty() ? wb.getSheetAt(0) : wb.getSheet(sheetName);
 }

 @Override
 public List<Map<String, String>> getPayload() {
  List<Map<String, String>> payLoad = new ArrayList<>();
  HSSFRow headRow = sheet.getRow(0);
  for (int i = 1; i <= sheet.getLastRowNum(); i++) {
   HSSFRow currentRow = sheet.getRow(i);
   Map<String, String> map = new HashMap<>();
   for (int j = 0; j < sheet.getRow(i).getLastCellNum(); j++) {
    map.put(getStringFormatCellValue(headRow.getCell(j)), getStringFormatCellValue(currentRow.getCell(j)));
   }
   payLoad.add(map);
  }
  return payLoad;
 }

}

无表头实现类

/**
 * @author Sherman
 * created in 2018/8/24
 */

public class NoHeaderExcel extends AbstractExcel {
 private final static boolean hasHeader = false;
 private HSSFSheet sheet;

 public NoHeaderExcel(HSSFSheet sheet) {
  super(sheet);
  this.sheet = sheet;
 }

 public NoHeaderExcel(String sheetName, String excelPath) {
  HSSFWorkbook wb = null;
  try {
   wb = new HSSFWorkbook(new POIFSFileSystem(new FileInputStream(excelPath)));
  } catch (IOException e) {
   e.printStackTrace();
  }
  sheet = sheetName == null || sheetName.isEmpty() ? wb.getSheetAt(0) : wb.getSheet(sheetName);
 }

 @Override
 public List<Map<String, String>> getPayload() {
  List<Map<String, String>> payLoad = new ArrayList<>();
  for (int i = 0; i < sheet.getLastRowNum(); i++) {
   HSSFRow currentRow = sheet.getRow(i);
   Map<String, String> map = new HashMap<>();
   for (int j = 0; j <= sheet.getRow(i).getLastCellNum(); j++) {
    map.put(String.valueOf(j), getStringFormatCellValue(currentRow.getCell(j)));
   }
   payLoad.add(map);
  }
  return payLoad;
 }

}

测试工具类:

/**
 * Unit test for simple App.
 */
public class AppTest
{
 /**
  * 测试建表,写表操作
  */
 @Test
 public void testExportExcel()
 {
  //测试数据
  String[] headers = new String[]{"A","B","C","D","E"};
   List<List<Object>> valueList = new LinkedList<>();
  for (char i = 'A'; i <= 'E' ; i++) {
   List<Object> rowList = new LinkedList<>();
   for (int j = 0; j <= 4; j++) {
    rowList.add(i+String.valueOf(j));
   }
   valueList.add(rowList);
  }

 AbstractExcel excel = new ExcelBuilder("报名表")
   .header(headers)
   .content(valueList)
   .autoColumnWidth()
   .build(true);

  try {
   File file = new File("E:\\excel\\test.xls");
   FileOutputStream op = new FileOutputStream(file);
   excel.write(op);
  } catch (IOException e) {
   e.printStackTrace();
  }
 }

 /**
  * 测试读取表数据操作
  */
 @Test
 public void testImportExcel(){
  AbstractExcel excel = new HeaderExcel(null,"E:/excel/test.xls");
  List<Map<String,String>> values = excel.getPayload();
  values.forEach(stringStringMap -> {
   stringStringMap.entrySet().forEach(stringStringEntry -> {
    System.out.println(stringStringEntry.getKey()+"---->"+stringStringEntry.getValue());
   });

  });
 }

}

附图:

测试1

测试二:

看起来效果还不错,当然还有很多不完善的地方,有需要的朋友可以在此基础上扩展定制,例如读取表数据结构方式,实现行数增删改查据或者创建表标题等等。

或者有朋友有更好的实现方案,欢迎前来交流!

最后的最后,当然忘不了附上笨工具的源码啦!

https://github.com/yumiaoxia/excel-commom-demo.git

(0)

相关推荐

  • Java读写Excel实例分享

    话不多说,请看代码: ExcelUtil.java package pers.kangxu.datautils.utils; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.

  • java读写excel文件实现POI解析Excel的方法

    在日常工作中,我们常常会进行文件读写操作,除去我们最常用的纯文本文件读写,更多时候我们需要对Excel中的数据进行读取操作,本文将介绍Excel读写的常用方法,希望对大家学习Java读写Excel会有帮助. package com.zhx.base.utils; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.us

  • 详解java封装实现Excel建表读写操作

    对 Excel 进行读写操作是生产环境下常见的业务,网上搜索的实现方式都是基于POI和JXL第三方框架,但都不是很全面.小编由于这两天刚好需要用到,于是就参考手写了一个封装操作工具,基本涵盖了Excel表(分有表头和无表头)的创建,并对它们进行读写操作.为方便大家,有需要者可以点击文后点解下载直接使用哦,当然也可以根据自己需求举一反三自己定制,相信对于聪明的你也不是什么难事.话不多说,直接贴源码 pom.xml 文件: <properties> <project.build.source

  • 详解Python利用configparser对配置文件进行读写操作

    简介 想写一个登录注册的demo,但是以前的demo数据都写在程序里面,每一关掉程序数据就没保存住.. 于是想着写到配置文件里好了 Python自身提供了一个Module - configparser,来进行对配置文件的读写 Configuration file parser. A configuration file consists of sections, lead by a "[section]" header, and followed by "name: valu

  • 详解java封装继承多态

    面向对象编程(Object Oriented Programming)有三大特性:封装.继承.多态.在这里,和大家一起加深对三者的理解. 封装 封装可以拆开理解,装,是把数据和方法放进了类里:封,把装进去的数据和成员方法加上访问权限.对于外界,内部细节是透明的,暴露给外面的是它的访问方法. 继承 继承,是为了重用父类代码.两个类若具有is a的关系就可以用extends.另外,继承也为实现多态做了铺垫. 多态 程序中定义的引用变量(java有两大数据类型,内部数据类型和引用数据类型)所指向的具体

  • python基础入门详解(文件输入/输出 内建类型 字典操作使用方法)

    一.变量和表达式 复制代码 代码如下: >>> 1 + 1               2>>> print 'hello world' hello world>>> x = 1               >>> y = 2>>> x + y3 Python是强类型语言,无法根据上下文自动解析转换成合适的类型. Python是一种动态语言,在程序运行过程中,同一个变量名在运行的不同阶段可以代表不同形式的值(整型,浮

  • 详解Java使用Pipeline对Redis批量读写(hmset&hgetall)

    一般情况下,Redis Client端发出一个请求后,通常会阻塞并等待Redis服务端处理,Redis服务端处理完后请求命令后会将结果通过响应报文返回给Client. 感觉这有点类似于HBase的Scan,通常是Client端获取每一条记录都是一次RPC调用服务端. 在Redis中,有没有类似HBase Scanner Caching的东西呢,一次请求,返回多条记录呢? 有,这就是Pipline.官方介绍 http://redis.io/topics/pipelining 通过pipeline方

  • 详解C++编程中对二进制文件的读写操作

    二进制文件不是以ASCII代码存放数据的,它将内存中数据存储形式不加转换地传送到磁盘文件,因此它又称为内存数据的映像文件.因为文件中的信息不是字符数据,而是字节中的二进制形式的信息,因此它又称为字节文件. 对二进制文件的操作也需要先打开文件,用完后要关闭文件.在打开时要用ios::binary指定为以二进制形式传送和存储.二进制文件除了可以作为输入文件或输出文件外,还可以是既能输入又能输出的文件.这是和ASCII文件不同的地方. 用成员函数read和write读写二进制文件 对二进制文件的读写主

  • 详解Java如何实现百万数据excel导出功能

    目录 前言 1.异步处理 1.1 使用job 1.2 使用mq 2.使用easyexcel 3.分页查询 4.多个sheet 5.计算limit的起始位置 6.文件上传到OSS 7.通过WebSocket推送通知 8.总条数可配置 9.order by商品编号 总结 前言 最近我做过一个MySQL百万级别数据的excel导出功能,已经正常上线使用了. 这个功能挺有意思的,里面需要注意的细节还真不少,现在拿出来跟大家分享一下,希望对你会有所帮助. 原始需求:用户在UI界面上点击全部导出按钮,就能导

  • 详解java调用存储过程并封装成map

    详解java调用存储过程并封装成map 本文代码中注释写的比较清楚不在单独说明,希望能帮助到大家, 实例代码: public List<Map<String , Object>> doCallProcedure(String procedureString,String[] parameters) throws PersistentDataOperationException { if (!isReady ()) { throw new PersistentDataOperatio

  • 详解Java Socket通信封装MIna框架

    核心类 IoService :Mina中将服务端和客户端都看成是服务,这里提供统一接口IoService,这个接口的作用就是用来处理套接字机制.也正是IoService来监听消息返回消息这些步骤,可以说IoService就是我们Mina中核心 IoProcessor:这个接口在另一个线程上,负责检查是否有数据在通道上读写,也就是说它也拥有自己的Selector,这是与我们使用JAVA NIO 编码时的一个不同之处,通常在JAVA NIO 编码中,我们都是使用一个Selector,也就是不区分Io

  • java EasyExcel面向Excel文档读写逻辑示例详解

    目录 正文 1 快速上手 1.1 引入依赖 1.2 导入与导出 2 实现原理 2.1 @RequestExcel 与 @ResponseExcel 解析器 2.2 RequestMappingHandlerAdapter 后置处理器 3 总结 正文 EasyExcel是一款由阿里开源的 Excel 处理工具.相较于原生的Apache POI,它可以更优雅.快速地完成 Excel 的读写功能,同时更加地节约内存. 即使 EasyExcel 已经很优雅了,但面向 Excel 文档的读写逻辑几乎千篇一

随机推荐