您的位置:首页 > 其它

Excel导入导出

2016-03-08 08:12 260 查看
由于项目中经常需要进行数据的导入和导出。所以研究下Excel的导入导出技术并作出整理。采用的是Apache POI 对Excel的支持。

Apache POI 是创建和维护操作各种符合Office Open XML(OOXML)标准和微软的OLE 2复合文档格式(OLE2)的Java API。用它可以使用Java读取和创建,修改MS Excel文件.而且,还可以使用Java读取和创建MS Word和MSPowerPoint文件。Apache POI 提供Java操作Excel解决方案(适用于Excel97-2008)。

其中 HSSF - 提供读写Microsoft Excel XLS格式档案的功能XSSF - 提供读写Microsoft Excel OOXML XLSX格式档案的功能

网上搜索资料并进行了修改封装:

1、ExcelBeanUtils.java 工具类


/**
* <p>Excel导入数据时进行bean的复制</p>
* -为Date类型注册类型转换器
* @version V1.0
*/
public class ExcelBeanUtils extends  org.apache.commons.beanutils.BeanUtils{

private static final String CONTEXT_KEY_FORMAT_DATE_VALUE = "yyyy-MM-dd";
private static final String CONTEXT_KEY_FORMAT_DATETIME_VALUE = "yyyy-MM-dd HH:mm:ss";
private static final String CONTEXT_KEY_FORMAT_TIME_VALUE = "HH:mm:ss";

static {
DateConverter dateConverter = new DateConverter(null);
dateConverter.setUseLocaleFormat(true);
dateConverter.setPatterns(new String[]{CONTEXT_KEY_FORMAT_DATE_VALUE, CONTEXT_KEY_FORMAT_DATETIME_VALUE, CONTEXT_KEY_FORMAT_TIME_VALUE});
ConvertUtils.register(dateConverter, Date.class);
}

public static class DateConverter extends DateTimeConverter {

public DateConverter() {

}

public DateConverter(Object defaultValue) {
super(defaultValue);
}

@SuppressWarnings("rawtypes")
protected Class getDefaultType() {
return Date.class;
}

@SuppressWarnings("rawtypes")
@Override
protected Object convertToType(Class type, Object obj) throws Exception {
if (obj == null) {
return null;
}
String value = obj.toString().trim();
if (value.length() == 0) {
return null;
}
return super.convertToType(type, obj);
}
}

public static void populateBean(Object bean, Map<?, ?> properties) throws IllegalAccessException, InvocationTargetException{
populate(bean, properties);
}
}


  2、ExcelColumn.java 表头信息和ExcelHead.java列信息


/**
* <p>Excel列信息</p>
* @author maxianming 2016-1-21 上午10:40:42
* @version V1.0
*/
public class ExcelColumn {
/**
* 列索引
*/
private Integer index;
/**
* 实际字段名称
*/
private String fieldName;
/**
* 表格中的显示名称
*/
private String fieldDispName;
/**
* 字段类型。数字类型还是日期等
*/
private Integer type;

public ExcelColumn() {

}

public ExcelColumn(int index, String fieldName, String fieldDispName) {
this.index = index;
this.fieldName = fieldName;
this.fieldDispName = fieldDispName;
}

public ExcelColumn(int index, String fieldName, String fieldDispName, int type) {
this.index = index;
this.fieldName = fieldName;
this.fieldDispName = fieldDispName;
this.type = type;
}

public Integer getIndex() {
return index;
}

public void setIndex(Integer index) {
this.index = index;
}

public String getFieldName() {
return fieldName;
}

public void setFieldName(String fieldName) {
this.fieldName = fieldName;
}

public String getFieldDispName() {
return fieldDispName;
}

public void setFieldDispName(String fieldDispName) {
this.fieldDispName = fieldDispName;
}

public Integer getType() {
return type;
}

public void setType(Integer type) {
this.type = type;
}

}


ExcelHead.java 表头信息

public class ExcelHead {

/**
* 列信息
*/
private List<ExcelColumn> columns;

/**
* 需要转换的列
*/
private Map<String, Map<?, ?>> columnsConvertMap;

/**
* 头部所占用的行数
*/
private int rowCount;

/**
* 头部所占用的列数
*/
private int columnCount;

public List<ExcelColumn> getColumns() {
return columns;
}

public int getRowCount() {
return rowCount;
}

public int getColumnCount() {
return columnCount;
}

public void setColumns(List<ExcelColumn> columns) {
this.columns = columns;
}

public void setRowCount(int rowCount) {
this.rowCount = rowCount;
}

public void setColumnCount(int columnCount) {
this.columnCount = columnCount;
}

public Map<String, Map<?, ?>> getColumnsConvertMap() {
return columnsConvertMap;
}

public void setColumnsConvertMap(Map<String, Map<?, ?>> columnsConvertMap) {
this.columnsConvertMap = columnsConvertMap;
}

@Override
public String toString() {
return "ExcelHead [columnCount=" + columnCount + ", columns=" + columns
+ ", columnsConvertMap=" + columnsConvertMap + ", rowCount="
+ rowCount + "]";
}

}


3、ExcelHelper.java 导入导出的工具类(借鉴网上他人代码) 采用泛型方式可直接导入相应对象类型的数据

package com.hikvision.finance.isms.common.excel;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;

import com.google.common.collect.Lists;
import com.hikvision.finance.core.util.BeanUtils;
import com.hikvision.finance.core.util.DateUtils;
import com.hikvision.finance.fwork.exception.ExpectedException;
import com.hikvision.finance.isms.common.excel.model.ExcelColumn;
import com.hikvision.finance.isms.common.excel.model.ExcelHead;
import com.hikvision.finance.isms.common.excel.utils.ExcelBeanUtils;
import com.hikvision.finance.isms.common.excel.utils.ExcelUtils;

/**
* <p>导入、导出的Excel帮助类</p>
* -导入数据到相关泛型对象T中
* @author maxianming 2016-1-21 下午12:14:35
* @version V1.0
*/
public class ExcelHelper<T> {

private IPoiExcelOperation excelOperation;

public IPoiExcelOperation getExcelOperation() {
return excelOperation;
}

public void setExcelOperation(IPoiExcelOperation excelOperation) {
this.excelOperation = excelOperation;
}

public ExcelHelper(IPoiExcelOperation excelOperation){
this.excelOperation = excelOperation;
}
/**
* <p>将excel中数据导入到list中</p>
* 文件读取失败会抛出ExpectedException
* @author maxianming 2016-1-21 下午12:21:24
* @param head 文件头信息
* @param file 导入的数据源
* @param cls 保存当前数据的对象
* @return
*/
public List<T> importToObjectList(ExcelHead head, File file, Class<T> cls) {
List<T> contents = null;
FileInputStream fis;
List<List<?>> rows = null;   // 根据excel 每行  生成list类型的数据
try {
fis = new FileInputStream(file);
rows = excelFileConvertToList(fis);
} catch (Exception ex) {
ex.printStackTrace();
throw new ExpectedException("","读取文件失败");
}
// 1.删除头信息
if(rows != null){
for (int i = 0; i < head.getRowCount(); i++) {
rows.remove(0);
}
}
// 2.将表结构转换成Map
Map<Integer, String> excelHeadMap = convertExcelHeadToMap(head.getColumns());
// 3.构建为对象
contents = buildDataObject(excelHeadMap, head.getColumnsConvertMap(), rows, cls);
return contents;
}

/**
* 将Excel文件内容转换为List对象
* @author maxianming 2016-1-20 下午6:15:05
* @param fis excel文件
* @return List<List> list存放形式的内容
* @throws Exception
*/
public List<List<?>> excelFileConvertToList(FileInputStream fis) throws Exception{
Workbook wb = this.excelOperation.readExcel(fis);
Sheet sheet = wb.getSheetAt(0);
List<List<?>> rows = new ArrayList<List<?>>();
if(sheet != null){
for (Row row : sheet) {
if(!ExcelUtils.isBlankRow(row)){
List<Object> cells = new ArrayList<Object>();
for (Cell cell : row) {
Object obj = null;
obj = this.getValue(cell);
cells.add(obj);
}
rows.add(cells);
}
}
}
return rows;
}
/**
* <p>将Excel中的数据类型进行转换</P>
* @author maxianming 2016-1-21 下午6:27:54
* @param cell
* @return
*/
private Object getValue(Cell cell) {
Object value = null;
if(cell != null){
switch (cell.getCellType()) {
case Cell.CELL_TYPE_STRING:
value = cell.getRichStringCellValue().getString();
break;
case Cell.CELL_TYPE_NUMERIC:
if (DateUtil.isCellDateFormatted(cell)) {
value = cell.getDateCellValue();
} else {
BigDecimal big = new BigDecimal(cell.getNumericCellValue());
String strValue = big.toString();
// 解决1234.0  去掉后面的.0
if(null != strValue && !"".equals(strValue.trim())){
String[] item = strValue.split("[.]");
if(1 < item.length && "0".equals(item[1])){
strValue = item[0];
}
};
value = strValue;
}
break;
case Cell.CELL_TYPE_BOOLEAN:
value = cell.getBooleanCellValue();
break;
case Cell.CELL_TYPE_FORMULA:
value = String.valueOf(cell.getNumericCellValue());  //读公式计算值
if (value.equals("NaN")) {                          // 如果获取的数据值为非法值,则转换为获取字符串
value = cell.getStringCellValue().toString();
}
break;
default:
value = null;
}
}
return value;
}

/**
* <p>将报表结构转换成Map</p>
* @author maxianming 2016-1-22 下午2:43:01
* @param excelColumns
* @return
*/
private Map<Integer, String> convertExcelHeadToMap(List<ExcelColumn> excelColumns) {
Map<Integer, String> excelHeadMap = new HashMap<Integer, String>();
for (ExcelColumn excelColumn : excelColumns) {
if(StringUtils.isNotEmpty(excelColumn.getFieldName())) {
excelHeadMap.put(excelColumn.getIndex(), excelColumn.getFieldName());
}
}
return excelHeadMap;
}

/**
* <p>根据Excel生成数据对象</P>
* @author maxianming 2016-1-21 下午1:42:22
* @param excelHeadMap 表头信息
* @param excelHeadConvertMap 需要特殊转换的单元
* @param rows   Excel文件中数据的List对象
* @param cls    转换为的对象
* @return
*/
private List<T> buildDataObject(Map<Integer, String> excelHeadMap, Map<String, Map<?, ?>> excelHeadConvertMap, List<List<?>> rows, Class<T> cls) {
List<T> contents = Lists.newArrayList();
for (List<?> list : rows) {
// 1.如果当前第一列中无数据,则忽略当前行的数据
if(list == null || list.get(0) == null) {
break;
}
// 2.当前行的数据放入map中,生成<fieldName, value>的形式
Map<String, Object> rowMap = rowListToMap(excelHeadMap, excelHeadConvertMap, list);
// 3.将当前行转换成对应的对象
T obj = null;
try {

obj = cls.newInstance();
} catch (InstantiationException ex) {
ex.printStackTrace();
} catch (IllegalAccessException ex) {
ex.printStackTrace();
}

try {
ExcelBeanUtils.populateBean(obj, rowMap);
} catch (IllegalAccessException e) {
e.printStackTrace();
throw new ExpectedException("","导入文件内容有误!");
} catch (InvocationTargetException e) {
e.printStackTrace();
throw new ExpectedException("","导入文件内容有误!");
}

contents.add(obj);
}
return contents;
}
/**
* <p>将行转行成map,生成<fieldName, value>的形式</p>
* @author maxianming 2016-1-21 下午1:46:57
* @param excelHeadMap          表头信息
* @param excelHeadConvertMap  需要转换的信息
* @param list     excel中的数据
* @throws ExpectedException 当导入文件不是按模板定义好的格式时,抛出异常。
* @return
*/
private Map<String, Object> rowListToMap(Map<Integer, String> excelHeadMap, Map<String, Map<?, ?>> excelHeadConvertMap, List<?> list) {
Map<String, Object> rowMap = new HashMap<String, Object>();
if(excelHeadMap.size() > list.size()){
throw new ExpectedException("", "导入文件的内容格式有误!");
}
for(int i = 0; i < list.size(); i++) {
String fieldName =  excelHeadMap.get(i);
if(fieldName != null) {
// 得到一行数据中每个单元格的value
Object value = list.get(i);
if(excelHeadConvertMap != null && excelHeadConvertMap.get(fieldName) != null) {
value = excelHeadConvertMap.get(fieldName).get(value);
}
rowMap.put(fieldName, value);
}
}
return rowMap;
}

/*--------------------------------导出功能还未完善-----------------------------------*/

/**
* 导出数据至Excel文件
* @author maxianming 2016-1-20 下午6:41:30
* @param head         报表头信息
* @param modelFile    导出文件
* @param outputFile   导出文件
* @param dataList     导入excel报表的数据来源
*/
public void exportExcelFile(ExcelHead head, File modelFile, File outputFile, List<?> dataList) {
InputStream inp = null;
Workbook wb = null;
try {
// 1.读取导出excel模板
inp = new FileInputStream(modelFile);
wb = this.excelOperation.readExcel(inp);
Sheet sheet = wb.getSheetAt(0);
//  2.生成导出数据
buildExcelData(sheet, head, dataList);

//  3.导出到文件中
FileOutputStream fileOut = new FileOutputStream(outputFile);
wb.write(fileOut);
fileOut.close();
} catch (FileNotFoundException ex) {
ex.printStackTrace();
} catch (InvalidFormatException ex) {
ex.printStackTrace();
} catch (Exception ex) {
ex.printStackTrace();
}
}
/**
* <p>生成导出至Excel文件的数据</p>
* @author maxianming 2016-1-22 下午2:45:45
* @param sheet  工作区间
* @param head   excel表头
* @param dataList  导入excel报表的数据来源
*/
private void buildExcelData(Sheet sheet, ExcelHead head, List<?> dataList) {
List<ExcelColumn> excelColumns = head.getColumns();
Map<String, Map<?, ?>> excelHeadConvertMap = head.getColumnsConvertMap();
// 1.将表结构转换成Map
Map<Integer, String> excelHeadMap = convertExcelHeadToMap(excelColumns);
// 2.从第几行开始插入数据
int startRow = head.getRowCount();
int order = 1;
for (Object obj : dataList) {
Row row = sheet.createRow(startRow++);
for (int j = 0; j < excelColumns.size(); j++) {
Cell cell = row.createCell(j);
cell.setCellType(excelColumns.get(j).getType());
String fieldName = excelHeadMap.get(j);
if(fieldName != null) {
Object valueObject = null;
try {
valueObject = BeanUtils.getProperty(obj, fieldName);
} catch (Exception e){
e.printStackTrace();
}
/*
*  如果存在需要转换的字段信息,则进行转换
*/
if(excelHeadConvertMap != null && excelHeadConvertMap.get(fieldName) != null) {
valueObject = excelHeadConvertMap.get(fieldName).get(valueObject);
}

if(valueObject == null) {
cell.setCellValue("");
} else if (valueObject instanceof Integer) {
cell.setCellValue((Integer)valueObject);
} else if (valueObject instanceof String) {
cell.setCellValue((String)valueObject);
} else if (valueObject instanceof Date) {
cell.setCellValue(DateUtils.getStringDateTime((Date)valueObject));
} else {
cell.setCellValue(valueObject.toString());
}
} else {
cell.setCellValue(order++);
}
}
}
}

}


  4、ExcelHelper.java 工厂化方法按Excel格式产生特定的Excel导入导出工具

**
* <p>产生一个ExcelHelper工具类</p>
* @author maxianming 2016-1-22 下午4:28:35
* @version V1.0
*/
public class ExcelHelperFactory {
/**
* <p>根据后缀名类型产生一个ExcelHelper类</p>
* @author maxianming 2016-1-22 下午4:30:41
* @param cls
*/
public static <T> ExcelHelper<T> createExcelHelper(String fileName){
ExcelHelper<T> excelHelper = null;
if(StringUtils.isNotBlank(fileName)){
String type = fileName.substring(fileName.lastIndexOf(".") + 1);
if("xls".equals(type)){
excelHelper = new ExcelHelper<T>(new HSSFExcel());
} else if("xlsx".equals(type)){
excelHelper = new ExcelHelper<T>(new XSSFExcel());
} else{
throw new ExpectedException("","不支持Excel文件的扩展名【" + type +"】");
}
}
return excelHelper;
}
}


最后实际应用例子:

// 1、Excel中每一行的信息

List<ExcelColumn> excelColumns = Lists.newArrayList();
excelColumns.add(new ExcelColumn(0, "strName", "机构名称"));
excelColumns.add(new ExcelColumn(1, "nlevel","机构级别"));
excelColumns.add(new ExcelColumn(2, "strCode", "机构号"));
excelColumns.add(new ExcelColumn(3, "strAddress","机构地址"));
excelColumns.add(new ExcelColumn(4, "parentOrg", "上级机构"));

// 2、机构级别中显示的名称-数据库中整数
Map<String, Integer> levelMap = new HashMap<String, Integer>(){
{
put("总行", 0); put("一级分行", 1); put("二级分行", 2);
put("直属支行", 3); put("支行", 4); put("办事处", 5);
put("经营支行", 6); put("分理处", 7); put("储蓄所",8);
}
};

// 3、excel中显示的信息转换为数据库中的值
Map<String, Map<?, ?>> excelColumnsConvertMap = Maps.newHashMap();
excelColumnsConvertMap.put("nlevel", levelMap);

// 4、组装excel信息
ExcelHead excelHead = new ExcelHead();
excelHead.setColumnCount(2);
excelHead.setColumns(excelColumns);
excelHead.setColumnsConvertMap(excelColumnsConvertMap);


// 5、Excel导入类使用

List<OrganizationDto> orgs = Lists.newArrayList();
ExcelHelper<OrganizationDto> excelHelper = ExcelHelperFactory.createExcelHelper(fileName);
orgs = excelHelper.importToObjectList(excelHead, orgFile, OrganizationDto.class);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: