在项目的pom文件中引入

<dependency>

<groupId>net.sourceforge.jexcelapi</groupId>

<artifactId>jxl</artifactId>

<version>2.6.10</version> </dependency>

package com.zhy.util.excel;

import java.io.InputStream;

import java.io.OutputStream;

import java.lang.reflect.Field;

import java.text.SimpleDateFormat;

import java.util.ArrayList;

import java.util.Arrays;

import java.util.Date;

import java.util.LinkedHashMap;

import java.util.List;

import java.util.Map.Entry;





import javax.servlet.http.HttpServletResponse;





import jxl.Cell;

import jxl.Sheet;

import jxl.Workbook;

import jxl.write.Label;

import jxl.write.WritableSheet;

import jxl.write.WritableWorkbook;





/**

 * @ClassName: ExcelUtil

 * @Description: TODO(Excel导入导出工具类:导出就是将List转化为Excel(listToExcel)

 *               导入就是将Excel转化为List(excelToList))

 * @author zhanghaiyang

 * @date 2016年2月18日 下午1:29:05

 * @Copyright © 2016上海通善互联网金融信息服务有限公司

 */

public class ExcelUtil {





/**

* @MethodName : listToExcel

* @Description : 导出Excel(可以导出到本地文件系统,也可以导出到浏览器,可自定义工作表大小)

* @param list

*            数据源

* @param fieldMap

*            类的英文属性和Excel中的中文列名的对应关系 如果需要的是引用对象的属性,则英文属性使用类似于EL表达式的格式

*            如:list中存放的都是student,student中又有college属性,而我们需要学院名称,则可以这样写

*            fieldMap.put("college.collegeName","学院名称")

* @param sheetName

*            工作表的名称

* @param sheetSize

*            每个工作表中记录的最大个数

* @param out

*            导出流

* @throws ExcelException

*/

public static <T> void listToExcel(List<T> list, LinkedHashMap<String, String> fieldMap, String sheetName, int sheetSize, OutputStream out)

throws ExcelException {





if (list.size() == 0 || list == null) {

throw new ExcelException("数据源中没有任何数据");

}





if (sheetSize > 65535 || sheetSize < 1) {

sheetSize = 65535;

}





// 创建工作簿并发送到OutputStream指定的地方

WritableWorkbook wwb;

try {

wwb = Workbook.createWorkbook(out);





// 因为2003的Excel一个工作表最多可以有65536条记录,除去列头剩下65535条

// 所以如果记录太多,需要放到多个工作表中,其实就是个分页的过程

// 1.计算一共有多少个工作表

double sheetNum = Math.ceil(list.size() / new Integer(sheetSize).doubleValue());





// 2.创建相应的工作表,并向其中填充数据

for (int i = 0; i < sheetNum; i++) {

// 如果只有一个工作表的情况

if (1 == sheetNum) {

WritableSheet sheet = wwb.createSheet(sheetName, i);

fillSheet(sheet, list, fieldMap, 0, list.size() - 1);





// 有多个工作表的情况

} else {

WritableSheet sheet = wwb.createSheet(sheetName + (i + 1), i);





// 获取开始索引和结束索引

int firstIndex = i * sheetSize;

int lastIndex = (i + 1) * sheetSize - 1 > list.size() - 1 ? list.size() - 1 : (i + 1) * sheetSize - 1;

// 填充工作表

fillSheet(sheet, list, fieldMap, firstIndex, lastIndex);

}

}





wwb.write();

wwb.close();





} catch (Exception e) {

e.printStackTrace();

// 如果是ExcelException,则直接抛出

if (e instanceof ExcelException) {

throw (ExcelException) e;





// 否则将其它异常包装成ExcelException再抛出

} else {

throw new ExcelException("导出Excel失败");

}

}





}





/**

* @MethodName : listToExcel

* @Description : 导出Excel(可以导出到本地文件系统,也可以导出到浏览器,工作表大小为2003支持的最大值)

* @param list

*            数据源

* @param fieldMap

*            类的英文属性和Excel中的中文列名的对应关系

* @param out

*            导出流

* @throws ExcelException

*/

public static <T> void listToExcel(List<T> list, LinkedHashMap<String, String> fieldMap, String sheetName, OutputStream out)

throws ExcelException {





listToExcel(list, fieldMap, sheetName, 65535, out);





}





/**

* @MethodName : listToExcel

* @Description : 导出Excel(导出到浏览器,可以自定义工作表的大小)

* @param list

*            数据源

* @param fieldMap

*            类的英文属性和Excel中的中文列名的对应关系

* @param sheetSize

*            每个工作表中记录的最大个数

* @param response

*            使用response可以导出到浏览器

* @throws ExcelException

*/

public static <T> void listToExcel(List<T> list, LinkedHashMap<String, String> fieldMap, String sheetName, int sheetSize,

HttpServletResponse response) throws ExcelException {





// 设置默认文件名为当前时间:年月日时分秒

String fileName = new SimpleDateFormat("yyyyMMddhhmmss").format(new Date()).toString();





// 设置response头信息

response.reset();

response.setContentType("application/vnd.ms-excel"); // 改成输出excel文件

response.setHeader("Content-disposition", "attachment; filename=" + fileName + ".xls");





// 创建工作簿并发送到浏览器

try {





OutputStream out = response.getOutputStream();

listToExcel(list, fieldMap, sheetName, sheetSize, out);





} catch (Exception e) {

e.printStackTrace();





// 如果是ExcelException,则直接抛出

if (e instanceof ExcelException) {

throw (ExcelException) e;





// 否则将其它异常包装成ExcelException再抛出

} else {

throw new ExcelException("导出Excel失败");

}

}

}





/**

* @MethodName : listToExcel

* @Description : 导出Excel(导出到浏览器,工作表的大小是2003支持的最大值)

* @param list

*            数据源

* @param fieldMap

*            类的英文属性和Excel中的中文列名的对应关系

* @param response

*            使用response可以导出到浏览器

* @throws ExcelException

*/

public static <T> void listToExcel(List<T> list, LinkedHashMap<String, String> fieldMap, String sheetName, HttpServletResponse response)

throws ExcelException {





listToExcel(list, fieldMap, sheetName, 65535, response);

}





/**

* @MethodName : excelToList

* @Description : 将Excel转化为List

* @param in

*            :承载着Excel的输入流

* @param sheetIndex

*            :要导入的工作表序号

* @param entityClass

*            :List中对象的类型(Excel中的每一行都要转化为该类型的对象)

* @param fieldMap

*            :Excel中的中文列头和类的英文属性的对应关系Map

* @param uniqueFields

*            :指定业务主键组合(即复合主键),这些列的组合不能重复

* @return :List

* @throws ExcelException

*/

public static <T> List<T> excelToList(InputStream in, String sheetName, Class<T> entityClass, LinkedHashMap<String, String> fieldMap,

String[] uniqueFields) throws ExcelException {





// 定义要返回的list

List<T> resultList = new ArrayList<T>();





try {





// 根据Excel数据源创建WorkBook

Workbook wb = Workbook.getWorkbook(in);

// 获取工作表

Sheet sheet = wb.getSheet(sheetName);





// 获取工作表的有效行数

int realRows = 0;

for (int i = 0; i < sheet.getRows(); i++) {





int nullCols = 0;

for (int j = 0; j < sheet.getColumns(); j++) {

Cell currentCell = sheet.getCell(j, i);

if (currentCell == null || "".equals(currentCell.getContents().toString())) {

nullCols++;

}

}





if (nullCols == sheet.getColumns()) {

break;

} else {

realRows++;

}

}





// 如果Excel中没有数据则提示错误

if (realRows <= 1) {

throw new ExcelException("Excel文件中没有任何数据");

}





Cell[] firstRow = sheet.getRow(0);





String[] excelFieldNames = new String[firstRow.length];





// 获取Excel中的列名

for (int i = 0; i < firstRow.length; i++) {

excelFieldNames[i] = firstRow[i].getContents().toString().trim();

}





// 判断需要的字段在Excel中是否都存在

boolean isExist = true;

List<String> excelFieldList = Arrays.asList(excelFieldNames);

for (String cnName : fieldMap.keySet()) {

if (!excelFieldList.contains(cnName)) {

isExist = false;

break;

}

}





// 如果有列名不存在,则抛出异常,提示错误

if (!isExist) {

throw new ExcelException("Excel中缺少必要的字段,或字段名称有误");

}





// 将列名和列号放入Map中,这样通过列名就可以拿到列号

LinkedHashMap<String, Integer> colMap = new LinkedHashMap<String, Integer>();

for (int i = 0; i < excelFieldNames.length; i++) {

colMap.put(excelFieldNames[i], firstRow[i].getColumn());

}





// 判断是否有重复行

// 1.获取uniqueFields指定的列

Cell[][] uniqueCells = new Cell[uniqueFields.length][];

for (int i = 0; i < uniqueFields.length; i++) {

int col = colMap.get(uniqueFields[i]);

uniqueCells[i] = sheet.getColumn(col);

}





// 2.从指定列中寻找重复行

for (int i = 1; i < realRows; i++) {

int nullCols = 0;

for (int j = 0; j < uniqueFields.length; j++) {

String currentContent = uniqueCells[j][i].getContents();

Cell sameCell = sheet.findCell(currentContent, uniqueCells[j][i].getColumn(), uniqueCells[j][i].getRow() + 1,

uniqueCells[j][i].getColumn(), uniqueCells[j][realRows - 1].getRow(), true);

if (sameCell != null) {

nullCols++;

}

}





if (nullCols == uniqueFields.length) {

throw new ExcelException("Excel中有重复行,请检查");

}

}





// 将sheet转换为list

for (int i = 1; i < realRows; i++) {

// 新建要转换的对象

T entity = entityClass.newInstance();





// 给对象中的字段赋值

for (Entry<String, String> entry : fieldMap.entrySet()) {

// 获取中文字段名

String cnNormalName = entry.getKey();

// 获取英文字段名

String enNormalName = entry.getValue();

// 根据中文字段名获取列号

int col = colMap.get(cnNormalName);





// 获取当前单元格中的内容

String content = sheet.getCell(col, i).getContents().toString().trim();





// 给对象赋值

setFieldValueByName(enNormalName, content, entity);

}





resultList.add(entity);

}

} catch (Exception e) {

e.printStackTrace();

// 如果是ExcelException,则直接抛出

if (e instanceof ExcelException) {

throw (ExcelException) e;





// 否则将其它异常包装成ExcelException再抛出

} else {

e.printStackTrace();

throw new ExcelException("导入Excel失败");

}

}

return resultList;

}





/*

* <-------------------------辅助的私有方法--------------------->

*/

/**

* @MethodName : getFieldValueByName

* @Description : 根据字段名获取字段值

* @param fieldName

*            字段名

* @param o

*            对象

* @return 字段值

*/

private static Object getFieldValueByName(String fieldName, Object o) throws Exception {





Object value = null;

Field field = getFieldByName(fieldName, o.getClass());





if (field != null) {

field.setAccessible(true);

value = field.get(o);

} else {

throw new ExcelException(o.getClass().getSimpleName() + "类不存在字段名 " + fieldName);

}





return value;

}





/**

* @MethodName : getFieldByName

* @Description : 根据字段名获取字段

* @param fieldName

*            字段名

* @param clazz

*            包含该字段的类

* @return 字段

*/

private static Field getFieldByName(String fieldName, Class<?> clazz) {

// 拿到本类的所有字段

Field[] selfFields = clazz.getDeclaredFields();





// 如果本类中存在该字段,则返回

for (Field field : selfFields) {

if (field.getName().equals(fieldName)) {

return field;

}

}





// 否则,查看父类中是否存在此字段,如果有则返回

Class<?> superClazz = clazz.getSuperclass();

if (superClazz != null && superClazz != Object.class) {

return getFieldByName(fieldName, superClazz);

}





// 如果本类和父类都没有,则返回空

return null;

}





/**

* @MethodName : getFieldValueByNameSequence

* @Description : 根据带路径或不带路径的属性名获取属性值

*              即接受简单属性名,如userName等,又接受带路径的属性名,如student.department.name等



* @param fieldNameSequence

*            带路径的属性名或简单属性名

* @param o

*            对象

* @return 属性值

* @throws Exception

*/

private static Object getFieldValueByNameSequence(String fieldNameSequence, Object o) throws Exception {





Object value = null;





// 将fieldNameSequence进行拆分

String[] attributes = fieldNameSequence.split("\\.");

if (attributes.length == 1) {

value = getFieldValueByName(fieldNameSequence, o);

} else {

// 根据属性名获取属性对象

Object fieldObj = getFieldValueByName(attributes[0], o);

String subFieldNameSequence = fieldNameSequence.substring(fieldNameSequence.indexOf(".") + 1);

value = getFieldValueByNameSequence(subFieldNameSequence, fieldObj);

}

return value;





}





/**

* @MethodName : setFieldValueByName

* @Description : 根据字段名给对象的字段赋值

* @param fieldName

*            字段名

* @param fieldValue

*            字段值

* @param o

*            对象

*/

private static void setFieldValueByName(String fieldName, Object fieldValue, Object o) throws Exception {





Field field = getFieldByName(fieldName, o.getClass());

if (field != null) {

field.setAccessible(true);

// 获取字段类型

Class<?> fieldType = field.getType();





// 根据字段类型给字段赋值

if (String.class == fieldType) {

field.set(o, String.valueOf(fieldValue));

} else if ((Integer.TYPE == fieldType) || (Integer.class == fieldType)) {

field.set(o, Integer.parseInt(fieldValue.toString()));

} else if ((Long.TYPE == fieldType) || (Long.class == fieldType)) {

field.set(o, Long.valueOf(fieldValue.toString()));

} else if ((Float.TYPE == fieldType) || (Float.class == fieldType)) {

field.set(o, Float.valueOf(fieldValue.toString()));

} else if ((Short.TYPE == fieldType) || (Short.class == fieldType)) {

field.set(o, Short.valueOf(fieldValue.toString()));

} else if ((Double.TYPE == fieldType) || (Double.class == fieldType)) {

field.set(o, Double.valueOf(fieldValue.toString()));

} else if (Character.TYPE == fieldType) {

if ((fieldValue != null) && (fieldValue.toString().length() > 0)) {

field.set(o, Character.valueOf(fieldValue.toString().charAt(0)));

}

} else if (Date.class == fieldType) {

field.set(o, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(fieldValue.toString()));

} else {

field.set(o, fieldValue);

}

} else {

throw new ExcelException(o.getClass().getSimpleName() + "类不存在字段名 " + fieldName);

}

}





/**

* @MethodName : setColumnAutoSize

* @Description : 设置工作表自动列宽和首行加粗

* @param ws

*/

private static void setColumnAutoSize(WritableSheet ws, int extraWith) {

// 获取本列的最宽单元格的宽度

for (int i = 0; i < ws.getColumns(); i++) {

int colWith = 0;

for (int j = 0; j < ws.getRows(); j++) {

String content = ws.getCell(i, j).getContents().toString();

int cellWith = content.length();

if (colWith < cellWith) {

colWith = cellWith;

}

}

// 设置单元格的宽度为最宽宽度+额外宽度

ws.setColumnView(i, colWith + extraWith);

}





}





/**

* @MethodName : fillSheet

* @Description : 向工作表中填充数据

* @param sheet

*            工作表

* @param list

*            数据源

* @param fieldMap

*            中英文字段对应关系的Map

* @param firstIndex

*            开始索引

* @param lastIndex

*            结束索引

*/

private static <T> void fillSheet(WritableSheet sheet, List<T> list, LinkedHashMap<String, String> fieldMap, int firstIndex, int lastIndex)

throws Exception {





// 定义存放英文字段名和中文字段名的数组

String[] enFields = new String[fieldMap.size()];

String[] cnFields = new String[fieldMap.size()];





// 填充数组

int count = 0;

for (Entry<String, String> entry : fieldMap.entrySet()) {

enFields[count] = entry.getKey();

cnFields[count] = entry.getValue();

count++;

}

// 填充表头

for (int i = 0; i < cnFields.length; i++) {

Label label = new Label(i, 0, cnFields[i]);

sheet.addCell(label);

}





// 填充内容

int rowNo = 1;

for (int index = firstIndex; index <= lastIndex; index++) {

// 获取单个对象

T item = list.get(index);

for (int i = 0; i < enFields.length; i++) {

Object objValue = getFieldValueByNameSequence(enFields[i], item);

String fieldValue = objValue == null ? "" : objValue.toString();

Label label = new Label(i, rowNo, fieldValue);

sheet.addCell(label);

}





rowNo++;

}





// 设置自动列宽

setColumnAutoSize(sheet, 5);

}

}

Java基础学习总结(49)——Excel导入导出工具类的更多相关文章

  1. 一个基于POI的通用excel导入导出工具类的简单实现及使用方法

    前言: 最近PM来了一个需求,简单来说就是在录入数据时一条一条插入到系统显得非常麻烦,让我实现一个直接通过excel导入的方法一次性录入所有数据.网上关于excel导入导出的例子很多,但大多相互借鉴. ...

  2. java中excel导入\导出工具类

    1.导入工具 package com.linrain.jcs.test; import jxl.Cell; import jxl.Sheet; import jxl.Workbook; import ...

  3. java Excel导入导出工具类

    本文章,导入导出依赖提前定义好的模板 package com.shareworx.yjwy.utils; import java.io.File; import java.io.FileInputSt ...

  4. 【原创】POI操作Excel导入导出工具类ExcelUtil

    关于本类线程安全性的解释: 多数工具方法不涉及共享变量问题,至于添加合并单元格方法addMergeArea,使用ThreadLocal变量存储合并数据,ThreadLocal内部借用Thread.Th ...

  5. java简易excel导入导出工具(封装POI)

    Octopus 如何导入excel 如何导出excel github项目地址 Octopus Octopus 是一个简单的java excel导入导出工具. 如何导入excel 下面是一个excel文 ...

  6. Octopus——excel导入导出工具

    Octopus Octopus是一个简易的Excel导入导出工具.目前主要就两个功能: 导入:将excel中一行数据转换为指定的java对象,并通过指定的正则表达式检查合法性. 导出:按照给定的xml ...

  7. Excel导入导出工具(简单、好用且轻量级的海量Excel文件导入导出解决方案.)

    Excel导入导出工具(简单.好用且轻量级的海量Excel文件导入导出解决方案.) 置顶 2019-09-07 16:47:10 $9420 阅读数 261更多 分类专栏: java   版权声明:本 ...

  8. Excel导入导出帮助类

    /// <summary>    /// Excel导入导出帮助类    /// 记得引入 NPOI    /// 下载地址   http://npoi.codeplex.com/rele ...

  9. 巨杉学习笔记 | SequoiaDB MySQL导入导出工具使用实战

    本文来自社区用户投稿,感谢这位小伙伴的技术分享 巨杉数据库架构简介 巨杉数据库作为分布式数据库是计算和存储分离架构,由数据库实例层和存储引擎层组成的.存储引擎层负责数据库核心功能比如数据读写存储以及分 ...

随机推荐

  1. [Python] Wikipedia Crawler

    import time import urllib import bs4 import requests start_url = "https://en.wikipedia.org/wiki ...

  2. JavaScript定时调用函数(SetInterval与setTimeout)

    setTimeout和setInterval的语法同样.它们都有两个參数.一个是将要运行的代码字符串.另一个是以毫秒为单位的时间间隔,当过了那个时间段之后就将运行那段代码. 只是这两个函数还是有差别的 ...

  3. Redis命令学习-Transaction(事务)

    DISCARD ​DISCARD :取消事务,放弃运行事务块内的全部代码.假设在使用WATCH命令监视某个key.则取消监视,等同于UNWATCH. ​返回值:总是返回ok.    ​     ​ ...

  4. android 获取蓝牙已连接设备

    蓝牙如果手动配对并已连接,获取连接的设备: 1.检测连接状态: int a2dp = bluetoothAdapter.getProfileConnectionState(BluetoothProfi ...

  5. c/c++中static与extern关键字介绍

    一.C语言中的static关键字 在C语言中,static可以用来修饰局部变量,全局变量以及函数.在不同的情况下static的作用不尽相同. (1)修饰局部变量 一般情况下,对于局部变量是存放在栈区的 ...

  6. 10.cocos2d坐标系

    一.笛卡儿坐标系 OpenGl坐标系为笛卡儿右手系.x向右,y向上,z向外.在cocos2d-lua中坐标系原点在屏幕的左下角,x向右,y向上,z则是指的zorder(层级). 二.世界坐标系,本地坐 ...

  7. Highcharts图表的注解功能

    Highcharts图表的注解功能 在图表中,往往须要对图表总体或者部分元素进行对应注解.帮助浏览者阅读图表.尽管标签组labels能够实现类似的功能.可是其功能相对简单.要实现复杂的注解功能,用户能 ...

  8. [Python] List & Object spread in Python

    def myfunc(x, y, z): print(x, y, z) tuple_vec = (, , ) dict_vec = {, , } >>> myfunc(*tuple_ ...

  9. mysql 不能启动的两种错误提示及解决方法

    在linux系统中安装mysql服务器详细步骤并解决ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using passw ...

  10. Android学习笔记进阶19之给图片加边框

    //设置颜色 public void setColour(int color){ co = color; } //设置边框宽度 public void setBorderWidth(int width ...