前言

最近项目中遇到要将MySQL数据库中的某些数据导出为Excel格式保存,在以前也写过这样的功能,这次就准备用以前的代码,但是看了一下,这次却不一样,因为在以前用到的都是导出一种或几种数据,种类不多,但是这次导出的种类比较多,相当于就是每一种类型的数据得单独写一些代码,而且重复的比较多;就想写一个通用的,不管什么种类,直接传入数据就行了;

正文

想法

因为数据的种类是不同的,里面的属性也各不相同,如何用同一段代码去处理这些不同种类的属性,让我第一时间想到了Java的泛型和反射;因为之前的笔记中就写到了反射,这时候刚好派上用场,就来实际操作一下;

代码部分

首先导入poi相应的jar包:


<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>3.17</version>
</dependency>
  1. 实体类

    有两个实体类:pojoA 和pojoBB,主要是为了测试不同实体类的不同属性是否有效;

    pojoA:

/**
* @author gyc
* @date 2018/10/26 21:50
*/ public class PojoA {
private String name;
private int num;
private double price;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}

pojoB:


/**
* @author gyc
* @date 2018/10/26 21:51
*/
public class PojoB {
private String userName;
private int age;
private Date birthday;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
  1. 核心代码部分

    使用该类时,需要传入每列得列名,为String数组,以及数据的List集合对象;还有一个Excel的title名;其中每列自动适应宽度,这个属性得将数据存入Excel之后才能调用,如果在数据存入之前调用,则不会取作用;

/**
* @author gyc
* @date 2018/10/26 21:45
*/
public class ExcelUtil<T> { public HSSFWorkbook setExcel(String title,String[] columnNames, List<T> tList) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, IOException {
// 1.创建Excel工作薄对象
HSSFWorkbook workbook=new HSSFWorkbook();
// 2.创建Excel工作表对象
HSSFSheet sheet=workbook.createSheet(title);
HSSFRow row=null;
// 3.创建Excel工作表的第一行,并填充列名
row=sheet.createRow(0);
for(int i=0;i<columnNames.length;i++){
row.createCell(i).setCellValue(columnNames[i]);
}
Field[] declaredFields = tList.get(0).getClass().getDeclaredFields();
// 4.将数据填充至表格中
for(int j=1;j<=tList.size();j++){
T t= tList.get(j-1);
row=sheet.createRow(j);
for(int i=0;i<declaredFields.length;i++){
// 通过反射获取属性值
String fieldName = declaredFields[i].getName();
String getMethodName="get"+fieldName.substring(0,1).toUpperCase()+fieldName.substring(1);
Method declaredMethod = t.getClass().getDeclaredMethod(getMethodName);
//执行方法
Object fieldValue = declaredMethod.invoke(t);
//判断是否为空
if(fieldValue!=null && !"".equals(fieldValue)){
//判断属性值类型
if(fieldValue instanceof Integer){
row.createCell(i).setCellValue(Integer.valueOf(fieldValue.toString()));
}else if(fieldValue instanceof Double){
row.createCell(i).setCellValue(Double.valueOf(fieldValue.toString()));
}else if(fieldValue instanceof Date){
row.createCell(i).setCellValue(new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(fieldValue));
}else {
row.createCell(i).setCellValue(fieldValue.toString());
}
}else {
row.createCell(i).setCellValue("");
}
}
}
// 自动设置列宽,要在在数据读入之后设置;
for (int i = 0; i < columnNames.length; i++) {
sheet.autoSizeColumn(i);
//在自动适应的基础上增加宽度
// sheet.setColumnWidth(i,sheet.getColumnWidth(i)*17/10);
}
return workbook;
}
}

测试

测试代码


/**
* @author gyc
* @date 2018/10/26 21:52
*/
public class Test {
public static void main(String[] args) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException, IOException {
PojoA pojoA=new PojoA();
pojoA.setName("a");
pojoA.setNum(1);
pojoA.setPrice(1.1234);
List<PojoA> lista=new ArrayList<>();
lista.add(pojoA); PojoB pojoB=new PojoB();
pojoB.setUserName("b");
pojoB.setAge(2);
pojoB.setBirthday(new Date());
List<PojoB> listb=new ArrayList<>();
listb.add(pojoB); HSSFWorkbook workbooka = new ExcelUtil().setExcel("pojoA", new String[]{"名称", "数量", "价格"}, lista);
HSSFWorkbook workbookb = new ExcelUtil().setExcel("pojoB", new String[]{"名称", "年龄", "时间"}, listb); workbooka.write(new FileOutputStream(new File("/Users/rose/IdeaProjects/java-study/smalltools/pojoA.xls")));
workbookb.write(new FileOutputStream(new File("/Users/rose/IdeaProjects/java-study/smalltools/pojoB.xls")));
}
}

GitHub地址:

总结

本篇笔记中使用了Java泛型和反射,但都是用得比较浅,只是最基础的使用;主要解决了处理数据种类繁多的的问题,不用单独处理;

其中也有很多不足之处,如下:

  • 数据集合只支持List集合
  • 用到了反射,速率可能比单独处理的低
  • 需要手动传入列名,比较硬编码

Excel通用类工具(一)的更多相关文章

  1. Excel通用类工具(二)

    前言 上一篇中写到了用反射来处理类中的不用的属性,但是Excel的列名还得手动输入,这样还是比较麻烦的,今天这篇就利用自定义注解来解决手动传入列名的问题:其实很简单的,只需要在上一篇的基础上加一个类就 ...

  2. MVC NPOI Linq导出Excel通用类

    之前写了一个模型导出Excel通用类,但是在实际应用中,可能不是直接导出模型,而是通过Linq查询后获取到最终结果再导出 通用类: public enum DataTypeEnum { Int = , ...

  3. NPOI导入导出EXCEL通用类,供参考,可直接使用在WinForm项目中

    以下是NPOI导入导出EXCEL通用类,是在别人的代码上进行优化的,兼容xls与xlsx文件格式,供参考,可直接使用在WinForm项目中,由于XSSFWorkbook类型的Write方法限制,Wri ...

  4. NPOI MVC 模型导出Excel通用类

    通用类: public enum DataTypeEnum { Int = , Float = , Double = , String = , DateTime = , Date = } public ...

  5. C#:导入Excel通用类(CSV格式)

    一.引用插件LumenWorks.Framework.IO.dll(CsvReader) 插件下载地址:https://pan.baidu.com/s/1c3kTKli  提取密码 dz7j 二.定义 ...

  6. C#:导入Excel通用类(Xls格式)

    PS:在CSV格式和XLSX格式中有写到通用调用的接口和引用的插件,所以在这个xls格式里面并没有那么详细,只是配上xls通用类. 一.引用插件NPOI.dll.NPOI.OOXML.dll.NPOI ...

  7. C#:导入Excel通用类(Xlsx格式)

    一.引用插件EPPlus.dll   插件下载地址:https://pan.baidu.com/s/1jEl7iu1H_C7-j9Wq37xIRQ  提取密码:pdy6 二.定义通用类XlsxExce ...

  8. poi导出excel通用类

    一.关键的通用类public class PoiExportUtils {    private static HSSFWorkbook workBook; public PoiExportUtils ...

  9. NPOI导入导出EXCEL通用类,可直接使用在WinForm项目中

    由于XSSFWorkbook类型的Write方法限制,Write完成后就自动关闭流数据,所以无法很好的支持的Web模式,网上目前也未找到好的解决方案. 注意:若直接使用在WinForm项目中,必需先下 ...

随机推荐

  1. C语言窗口例子

    #include <windows.h> LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM ) ; //声明用来处理消息的函数 in ...

  2. pwn入门之栈溢出练习

    本文原创作者:W1ngs,本文属i春秋原创奖励计划,未经许可禁止转载!前言:最近在入门pwn的栈溢出,做了一下jarvisoj里的一些ctf pwn题,感觉质量都很不错,难度循序渐进,把自己做题的思路 ...

  3. Alibaba FastJson 常用方法使用指南

    介绍 FastJson是阿里巴巴的开源JSON解析库,它可以解析JSON格式的字符串,支持将Java Bean序列化为JSON字符串,也可以从JSON字符串反序列化到JavaBean. FastJso ...

  4. 第53节:Java当中的IO流(上)

    Java当中的IO流 在Java中,字符串string可以用来操作文本数据内容,字符串缓冲区是什么呢?其实就是个容器,也是用来存储很多的数据类型的字符串,基本数据类型包装类的出现可以用来解决字符串和基 ...

  5. Redis学习笔记之Redis基本数据结构

    Redis基础数据结构 Redis有5种基本数据结构:String(字符串).list(列表).set(集合).hash(哈希).zset(有序集合) 字符串string 字符串类型是Redis的va ...

  6. 什么 是JavaScript中的变量? 部分2

    变量:是计算机存储数据的标识符 js中存储数据的方式 都是使用变量 js 中声明变量的方式都是var 存储数据,应该有对应的数据类型js中的字符串类型都用成对的单引号或者双引号包裹起来 变量 1. 变 ...

  7. Jade是变体的HTML

    在这段HTML代码中,div 包含了一个 a 元素与一段没有标记包围的文本.若要用Jade表述这段HTML,div 元素和 a 元素都可以用前面所述的方法实现,但剩下的那个没有标记包围的文本就不能用前 ...

  8. mysql 开发进阶篇系列 21 磁盘I/O问题(RAID)

    一.概述 作为应用系统的持久化层,不管数据库采取了什么样的Cache机制,数据库最终总是要将数据储存到可以长久保存的I/O设备磁盘上.但磁盘的存取速度显然要比cpu,ram的速度慢很多.因此,对于比较 ...

  9. Android数据保存之文件保存

    前言: 上一篇文章写了在Android中利用SharedPreferences保存数据,SharedPreferences在保存数据的时候主要是保存一些应用程序的设置信息或者少量的用户信息,并且是以k ...

  10. Elasticsearch实践(三):Mapping

    版本:Elasticsearch 6.2.4. Mapping类似于数据库中的表结构定义,主要作用如下: 定义Index下字段名(Field Name) 定义字段的类型,比如数值型,字符串型.布尔型等 ...