一、重要须知
1、该内容基于有模板的前提下
2、实现的是Excel模板内容导出(可以带标题,可以不带标题)附带校验失败内容下载
3、采用的方式是MVC提供的MultipartFile类
4、有自己的类封装我把用到的相关类放在这里
5、能找到的工具类,例如阿帕奇的等,你们看导入找就行
package com.bookdao.oasis.utils.excel.reader;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.FormulaEvaluator;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import com.bookdao.oasis.sys.util.StringUtil;
import com.bookdao.oasis.utils.excel.AnnotationFieldUtil;
import com.bookdao.oasis.utils.excel.ExcelConstants;
import com.bookdao.oasis.utils.excel.ExcelFieldInfo;
import com.bookdao.oasis.utils.excel.RegexUtil;
import com.bookdao.oasis.utils.excel.WorkBookUtil;
import com.bookdao.oasis.utils.excel.annotation.ExcelObject;
public class ExcelReader<T> {
private Integer startColumn;
private Integer endColumn;
private Integer startRow;
private Integer endRow;
private static boolean readAll = false;
private Class<T> clazz;
private Map<String, ExcelFieldInfo> fieldMaps;
private FormulaEvaluator formulaEvaluator;
public void setReadAll(boolean readAll) {
this.readAll = readAll;
}
public void setStartColumn(Integer startColumn) {
this.startColumn = startColumn;
}
public void setEndColumn(Integer endColumn) {
this.endColumn = endColumn;
}
public void setStartRow(Integer startRow) {
this.startRow = startRow;
}
public void setEndRow(Integer endRow) {
this.endRow = endRow;
}
/**
* Excel数据读取器
*
* @param startColumn
* 起始列(必填,从0开始)
* @param endColumn
* 终止列(必填)
* @param startRow
* 起始行 (可以为NULL,从0开始,默认从第0行开始)
* @param endRow
* 终止行 (可以为NULL)
* @param clazz
*/
public ExcelReader(Integer startColumn, Integer endColumn,
Integer startRow, Integer endRow, Class<T> clazz) {
this.startColumn = startColumn;
this.endColumn = endColumn;
this.startRow = startRow;
this.endRow = endRow;
this.clazz = clazz;
this.fieldMaps = AnnotationFieldUtil.fieldMaps(this.clazz);
}
/**
* Excel数据读取器
*
* @param startColumn
* 起始列(必填,从0开始)
* @param endColumn
* 终止列(必填)
* @param startRow
* 起始行 (可以为NULL,从0开始,默认从第0行开始)
* @param clazz
*/
public ExcelReader(Integer startColumn, Integer endColumn,
Integer startRow, Class<T> clazz) {
this(startColumn, endColumn, startRow, null, clazz);
}
/**
* Excel数据读取器
*
* @param startColumn
* 起始列(必填,从0开始)
* @param endColumn
* 终止列(必填)
* @param clazz
*/
public ExcelReader(Integer startColumn, Integer endColumn, Class<T> clazz) {
this(startColumn, endColumn, null, null, clazz);
}
/**
* 读取Excel数据
*
* @Title read
* @Description TODO
* @param in
* Excel数据流
* @return 读取结果
* @throws Exception
* @update
*
*/
public List<T> read(InputStream in) throws Exception {
Workbook hssfWorkbook = WorkBookUtil.createWorkBook(in);
if(null != hssfWorkbook){
formulaEvaluator = hssfWorkbook.getCreationHelper().createFormulaEvaluator();
}
List<T> list = new ArrayList<T>();
if (null == startColumn) {
throw new NullPointerException("Please set startColumn!");
}
if (null == endColumn) {
throw new NullPointerException("Please set endColumn!");
}
for (int numSheet = 0; numSheet < hssfWorkbook.getNumberOfSheets(); numSheet++) {
Sheet sheet = hssfWorkbook.getSheetAt(numSheet);
if (sheet == null) {
continue;
}
int lastRowNum = null != endRow ? endRow : sheet.getLastRowNum();
int rowNum = null != startRow ? startRow : 0;
if (clazz == List.class) {
readToList(sheet, list, lastRowNum, rowNum);
} else {
readToBean(sheet, list, lastRowNum, rowNum);
}
if(!readAll){
break;
}
}
return list;
}
/**
* 读取数据为List<List<Object>>类型
*
* @Title readToList
* @Description TODO
* @param sheet
* @param list
* @param lastRowNum
* @param rowNum
* @update
*
*/
@SuppressWarnings("unchecked")
private void readToList(Sheet sheet, List<T> list, int lastRowNum,
int rowNum) throws Exception {
for (; rowNum <= lastRowNum; rowNum++) {
Row hssfRow = sheet.getRow(rowNum);
if (null == hssfRow) {
break;
}
List<Object> inList = new ArrayList<Object>();
for (int column = startColumn; column <= endColumn; column++) {
Cell cell = hssfRow.getCell(column);
String str = WorkBookUtil.getValue(cell,formulaEvaluator);
inList.add(str);
}
list.add((T) inList);
}
}
/**
* 读取数据为List<Object>类型,其中Object为通过泛型设置的类型
*
* @Title readToBean
* @Description TODO
* @param sheet
* @param list
* @param lastRowNum
* @param rowNum
* @throws Exception
* @update
*
*/
private void readToBean(Sheet sheet, List<T> list, int lastRowNum,
int rowNum) throws Exception {
ExcelObject excelObject = clazz.getAnnotation(ExcelObject.class);
if (null == excelObject || !excelObject.value()) {
return;
}
for (; rowNum <= lastRowNum; rowNum++) {
Row hssfRow = sheet.getRow(rowNum);
if (null == hssfRow) {
break;
}
if (WorkBookUtil.rowIsNull(hssfRow,formulaEvaluator, startColumn, endColumn)) {
return;
}
T obj = (T) Class.forName(clazz.getName()).newInstance();
int excelColumn = 1;
for (int column = startColumn; column <= endColumn; column++) {
Cell cell = hssfRow.getCell(column);
ExcelFieldInfo excelField = fieldMaps.get(excelColumn++ + "");
String strValue = WorkBookUtil.getValue(cell,formulaEvaluator);
int[] validateArray = excelField.getExcelField().validate();
for (int i = 0; i < validateArray.length; i++) {
if(validateArray[i] == ExcelConstants.VALIDATION_NOT_NULL){
if(null == strValue || strValue.length() == 0){
throw new Exception("MSG_第"+(rowNum+1)+"行,第"+(column+1)+"列不能为空");
}
}
}
if (null == strValue) {
continue;
}
Field field = excelField.getField();
Class<?> fieldClazz = field.getType();
if (fieldClazz == String.class) {
field.set(obj, strValue);
} else if (fieldClazz == Integer.class
|| fieldClazz == int.class) {
if(!RegexUtil.isNumber(strValue)){
throw new Exception("MSG_第"+(rowNum+1)+"行,第"+(column+1)+"列格式必须为数字");
}
field.set(obj, CellDataReader.readInt(strValue));
} else if (fieldClazz == short.class
|| fieldClazz == Short.class) {
if(!RegexUtil.isNumber(strValue)){
throw new Exception("MSG_第"+(rowNum+1)+"行,第"+(column+1)+"列格式必须为数字");
}
field.set(obj, CellDataReader.readShort(strValue));
} else if (fieldClazz == long.class || fieldClazz == Long.class) {
if(!RegexUtil.isNumber(strValue)){
throw new Exception("MSG_第"+(rowNum+1)+"行,第"+(column+1)+"列格式必须为数字");
}
field.set(obj, CellDataReader.readLong(strValue));
} else if (fieldClazz == float.class
|| fieldClazz == Float.class) {
if(!RegexUtil.isNumber(strValue)){
throw new Exception("MSG_第"+(rowNum+1)+"行,第"+(column+1)+"列格式必须为数字");
}
int decimal = Integer.parseInt(excelField.getExcelField().decimal());
field.set(obj, CellDataReader.readFloat(strValue, decimal));
} else if (fieldClazz == double.class
|| fieldClazz == Double.class) {
if(!RegexUtil.isNumber(strValue)){
throw new Exception("MSG_第"+(rowNum+1)+"行,第"+(column+1)+"列格式必须为数字");
}
int decimal = Integer.parseInt(excelField.getExcelField().decimal());
field.set(obj, CellDataReader.readDouble(strValue, decimal));
} else if (fieldClazz == BigInteger.class) {
if(!RegexUtil.isNumber(strValue)){
throw new Exception("MSG_第"+(rowNum+1)+"行,第"+(column+1)+"列格式必须为数字");
}
field.set(obj, CellDataReader.readBigInteger(strValue));
} else if (fieldClazz == BigDecimal.class) {
if(!RegexUtil.isNumber(strValue)){
throw new Exception("MSG_第"+(rowNum+1)+"行,第"+(column+1)+"列格式必须为数字");
}
if(StringUtil.isNotNull(strValue)){
int decimal = Integer.parseInt(excelField.getExcelField().decimal());
field.set(obj,CellDataReader.readBigDecimal(strValue, decimal));
}else{
int decimal = Integer.parseInt(excelField.getExcelField().decimal());
field.set(obj,CellDataReader.readBigDecimal("0", decimal));
}
} else if (fieldClazz == Date.class) {
String dateFormat = excelField.getExcelField().dateFormat();
try {
field.set(obj,CellDataReader.readDate(strValue, dateFormat));
} catch (Exception e) {
throw new Exception("MSG_第"+(rowNum+1)+"行,第"+(column+1)+"列格式必须为"+dateFormat);
}
}
}
list.add(obj);
}
}
//************************************仅仅满足订单明细导入需求***************************************
public ExcelReader(){
}
/**
*
* @Title read
* @Description 根据配置的注解,解析excel的数据导po
* @param in
* @param clazz
* @return
* @throws Exception
* List<ProductItemVO>
* @throws
*/
public static <T> List<T> read(InputStream in,Class<T> clazz) throws Exception {
Workbook hssfWorkbook = WorkBookUtil.createWorkBook(in);
FormulaEvaluator formulaEvaluator = hssfWorkbook.getCreationHelper().createFormulaEvaluator();
List<T> list = new ArrayList<T>();
//处理excel首行和对象的属性以及注解的对应关系
Map<String, ExcelFieldInfo> fieldMaps=null;
Sheet firstSheet=hssfWorkbook.getSheetAt(0);
int columnLength=0;
if(null != firstSheet){
Row firstRow=firstSheet.getRow(0);
if(firstRow!=null){
columnLength=firstRow.getPhysicalNumberOfCells();
fieldMaps=AnnotationFieldUtil.initRelation(clazz, firstRow,formulaEvaluator);
}else{
return list;
}
}
if(null == fieldMaps){
return list;
}
for (int numSheet = 0; numSheet < hssfWorkbook.getNumberOfSheets(); numSheet++) {
Sheet sheet = hssfWorkbook.getSheetAt(numSheet);
if (sheet == null) {
continue;
}
int rowNum=sheet.getLastRowNum();
for (int i = 1; i <= rowNum; i++) {
Row row=sheet.getRow(i);
if(WorkBookUtil.rowIsNull(row,formulaEvaluator, 0, columnLength)){
continue;
}
Object object=clazz.newInstance();
T obj =(T)object;
ExcelFieldInfo rowIndexExcelField =fieldMaps.get("rowIndexExcel");
if(rowIndexExcelField!=null){
Field field = rowIndexExcelField.getField();
field.setAccessible(true);
field.set(obj, i);
}
for(int j=0;j<columnLength;j++){
ExcelFieldInfo excelField=fieldMaps.get(String.valueOf(j));
if(null ==excelField){
continue;
}
Cell cell=row.getCell(j);
String strValue = WorkBookUtil.getValue(cell,formulaEvaluator);
int[] validateArray = excelField.getExcelField().validate();
for (int k = 0; k < validateArray.length; k++) {
if(validateArray[k] == ExcelConstants.VALIDATION_NOT_NULL){
if(null == strValue || strValue.length() == 0){
throw new Exception("MSG_第"+(i+1)+"行,第"+(j+1)+"列不能为空");
}
}
}
if (StringUtils.isBlank(strValue)) {
continue;
}
Field field = excelField.getField();
Class<?> fieldClazz = field.getType();
field.setAccessible(true);//基类中也可以定义非private
//下面代码可共用
if (fieldClazz == String.class) {
field.set(obj, strValue);
} else if (fieldClazz == Integer.class
|| fieldClazz == int.class) {
if(!RegexUtil.isNumber(strValue)){
throw new Exception("MSG_第"+(i+1)+"行,第"+(j+1)+"列格式必须为数字");
}
field.set(obj, CellDataReader.readInt(strValue));
} else if (fieldClazz == short.class
|| fieldClazz == Short.class) {
if(!RegexUtil.isNumber(strValue)){
throw new Exception("MSG_第"+(i+1)+"行,第"+(j+1)+"列格式必须为数字");
}
field.set(obj, CellDataReader.readShort(strValue));
} else if (fieldClazz == long.class || fieldClazz == Long.class) {
if(!RegexUtil.isNumber(strValue)){
throw new Exception("MSG_第"+(i+1)+"行,第"+(j+1)+"列格式必须为数字");
}
field.set(obj, CellDataReader.readLong(strValue));
} else if (fieldClazz == float.class
|| fieldClazz == Float.class) {
if(!RegexUtil.isNumber(strValue)){
throw new Exception("MSG_第"+(i+1)+"行,第"+(j+1)+"列格式必须为数字");
}
int decimal = Integer.parseInt(excelField.getExcelField().decimal());
field.set(obj, CellDataReader.readFloat(strValue, decimal));
} else if (fieldClazz == double.class
|| fieldClazz == Double.class) {
if(!RegexUtil.isNumber(strValue)){
throw new Exception("MSG_第"+(i+1)+"行,第"+(j+1)+"列格式必须为数字");
}
int decimal = Integer.parseInt(excelField.getExcelField().decimal());
field.set(obj, CellDataReader.readDouble(strValue, decimal));
} else if (fieldClazz == BigInteger.class) {
if(!RegexUtil.isNumber(strValue)){
throw new Exception("MSG_第"+(i+1)+"行,第"+(j+1)+"列格式必须为数字");
}
field.set(obj, CellDataReader.readBigInteger(strValue));
} else if (fieldClazz == BigDecimal.class) {
if(!RegexUtil.isNumber(strValue)){
throw new Exception("MSG_第"+(i+1)+"行,第"+(j+1)+"列格式必须为数字");
}
int decimal = Integer.parseInt(excelField.getExcelField().decimal());
field.set(obj,CellDataReader.readBigDecimal(strValue, decimal));
} else if (fieldClazz == Date.class) {
String dateFormat = excelField.getExcelField().dateFormat();
try {
field.set(obj,CellDataReader.readDate(strValue, dateFormat));
} catch (Exception e) {
throw new Exception("MSG_第"+(i+1)+"行,第"+(j+1)+"列格式必须为"+dateFormat);
}
}
}
list.add(obj);
}
if(!readAll){
break;
}
}
return list;
}
}
package com.bookdao.oasis.utils.excel;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.FormulaEvaluator;
import org.apache.poi.ss.usermodel.Row;
import com.bookdao.oasis.utils.excel.annotation.ExcelField;
import com.bookdao.oasis.utils.excel.annotation.ExcelObject;
import com.google.common.collect.Maps;
public class AnnotationFieldUtil {
/**
* 获取列与VO属性对应关系
*
*
*/
public static Map<String, ExcelFieldInfo> fieldMaps(Class<?> clazz) {
Map<String, ExcelFieldInfo> fieldMaps = new HashMap<String, ExcelFieldInfo>();
ExcelObject excelObject = clazz.getAnnotation(ExcelObject.class);
if (null == excelObject || !excelObject.value()) {
return fieldMaps;
}
Field[] fields = clazz.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
fields[i].setAccessible(true);
ExcelField excelField = fields[i].getAnnotation(ExcelField.class);
if (null != excelField) {
ExcelFieldInfo excelFieldVO = new ExcelFieldInfo();
excelFieldVO.setField(fields[i]);
excelFieldVO.setExcelField(excelField);
fieldMaps.put(excelField.index(), excelFieldVO);
}
}
Class<?> superClazz = clazz.getSuperclass();
ExcelObject excelObj = superClazz.getAnnotation(ExcelObject.class);
if (null != excelObj && excelObj.value()) {
fieldMaps.putAll(fieldMaps(superClazz));
}
return fieldMaps;
}
/**
* @Description excel和实体对象的对应关系
*/
public static Map<String, ExcelFieldInfo> initRelation(Class<?> clazz,Row firstRow,FormulaEvaluator formulaEvaluator) throws Exception{
Map<String, ExcelFieldInfo> fieldMaps = new HashMap<String, ExcelFieldInfo>();
Map<String,ExcelFieldInfo> fieldAnnotionMap=getFieldExcelCellAnnotion(clazz);
//处理单元格列数据:
int columnLength=firstRow.getPhysicalNumberOfCells();
for(int i=0;i<columnLength;i++){
Cell cell= firstRow.getCell(i);
String cellValue = WorkBookUtil.getValue(cell,formulaEvaluator);
if(StringUtils.isNotBlank(cellValue)){
if(null != fieldAnnotionMap.get(cellValue)){
fieldMaps.put(String.valueOf(i),fieldAnnotionMap.get(cellValue));
}
}
}
fieldMaps.put("rowIndexExcel", fieldAnnotionMap.get("rowIndexExcel"));
return fieldMaps;
}
/**
*
* @Title getFieldAnnotion
* @Description 获取类注解和属性对象的对应关系
*/
public static Map<String,ExcelFieldInfo> getFieldExcelCellAnnotion(Class<?> clazz){
Map<String,ExcelFieldInfo> excelFieldMap=Maps.newHashMap();
ExcelObject excelObject = clazz.getAnnotation(ExcelObject.class);
if (null == excelObject || !excelObject.value()) {
return excelFieldMap;
}
Field[] fields = clazz.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
ExcelField excelField=fields[i].getAnnotation(ExcelField.class);
if(null != excelField && StringUtils.isNotBlank(excelField.cellColumnName())){
ExcelFieldInfo excelFieldInfo=new ExcelFieldInfo();
excelFieldInfo.setField(fields[i]);
excelFieldInfo.setExcelField(excelField);
excelFieldMap.put(excelField.cellColumnName().trim(), excelFieldInfo);
}
}
Class superClazz=clazz.getSuperclass();
if(null != superClazz){
excelFieldMap.putAll(getFieldExcelCellAnnotion(superClazz));
}
return excelFieldMap;
}
public static void main(String[] args) {
}
}
package com.bookdao.oasis.utils.excel;
import java.io.InputStream;
import java.io.PushbackInputStream;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.poi.POIXMLDocument;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.CellValue;
import org.apache.poi.ss.usermodel.FormulaEvaluator;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressBase;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class WorkBookUtil {
/**
* 根据输入流创建一个Excel对象
*
**/
public static Workbook createWorkBook(InputStream in) throws Exception {
if (!in.markSupported()) {
in = new PushbackInputStream(in, 8);
}
if (POIFSFileSystem.hasPOIFSHeader(in)) {
return new HSSFWorkbook(in);
}
if (POIXMLDocument.hasOOXMLHeader(in)) {
return new XSSFWorkbook(OPCPackage.open(in));
}
throw new Exception("MSG_此Excel版本目前无法解析");
}
/**
* 判断指定行是否为空
*
* @Title rowIsNull
* @Description TODO
* @param row
* 指定行
* @param startColumn
* 起始列
* @param endColumn
* 终止列
*/
public static boolean rowIsNull(Row row,FormulaEvaluator formulaEvaluator, int startColumn, int endColumn) throws Exception {
if(row == null){
return true;
}
int nullCount = 0;
int totalColumn = endColumn - startColumn + 1;
for (; startColumn <= endColumn; startColumn++) {
Cell cell = row.getCell(startColumn);
if (null == cell) {
nullCount++;
continue;
}
String value = getValue(cell,formulaEvaluator);
if (null == value || value.trim().length() == 0) {
nullCount++;
}
}
return totalColumn == nullCount;
}
/**
* 读取Excel中单个Cell的值
*
*/
public static String getValue(Cell cell,FormulaEvaluator formulaEvaluator) throws Exception {
if (null == cell) {
return null;
}
int rowNumber = cell.getRow().getRowNum();
try {
CellValue cellValue = formulaEvaluator.evaluate(cell);
if(null == cellValue){
return null;
}
int cellType = cellValue.getCellType();
if (cellType == Cell.CELL_TYPE_BOOLEAN) {
return String.valueOf(cellValue.getBooleanValue());
} else if (cellType == Cell.CELL_TYPE_NUMERIC) {
double doubleValue = cellValue.getNumberValue();
BigDecimal tempNumber = new BigDecimal(doubleValue);
String strValue = tempNumber.toString();
String[] strArray = strValue.split("\\.");
DecimalFormat df = null;
if (strArray.length == 2) {
StringBuilder strb = new StringBuilder();
strb.append("0");
for (int i = 0; i < strArray[1].length(); i++) {
if (i == 0) {
strb.append(".");
}
strb.append("0");
}
df = new DecimalFormat(strb.toString());
} else {
df = new DecimalFormat("0");
}
return df.format(doubleValue);
} else if(cellType == Cell.CELL_TYPE_STRING){
return String.valueOf(cellValue.getStringValue());
}
return "";
} catch (Exception e) {
e.printStackTrace();
throw new Exception("MSG_第"+(rowNumber+1)+"行,第"+(cell.getColumnIndex()+1)+"列数据错误");
}
}
/**
* get Row, if not exists, create
*
* @param rowCounter int
* @param sheet Sheet
* @return Row
*/
public static Row getRow(int rowCounter, Sheet sheet) {
Row row = sheet.getRow((short) rowCounter);
if (row == null) {
row = sheet.createRow((short) rowCounter);
}
return row;
}
/**
* get Cell, if not exists, create
*
* @param row Row
* @param column int
* @return Cell
*/
public static Cell getCell(Row row, int column) {
Cell cell = row.getCell((short) column);
if (cell == null) {
cell = row.createCell((short) column);
}
return cell;
}
/**
* get cell, if not exists, create
*
* @param sheet Sheet
* @param rowNum int
* @param colNum int
* @return Cell
*/
public static Cell getCell(Sheet sheet, int rowNum, int colNum) {
Row row = getRow(rowNum, sheet);
Cell cell = getCell(row, colNum);
return cell;
}
/**
* copy row
*
* @param sheet
* @param from begin of the row
* @param to destination fo the row
* @param count count of copy
*/
public static void copyRow(Sheet sheet, int from, int to, int count) {
for (int rownum = from; rownum < from + count; rownum++) {
Row fromRow = sheet.getRow(rownum);
Row toRow = getRow(to + rownum - from, sheet);
if (null == fromRow)
return;
toRow.setHeight(fromRow.getHeight());
toRow.setHeightInPoints(fromRow.getHeightInPoints());
short lastCellNum = fromRow.getLastCellNum();
short firstCelNum = fromRow.getFirstCellNum();
for (int i = firstCelNum; i < lastCellNum && i >= 0; i++) {
Cell fromCell = getCell(fromRow, i);
Cell toCell = getCell(toRow, i);
// toCell.setEncoding(fromCell.getEncoding());
toCell.setCellStyle(fromCell.getCellStyle());
toCell.setCellType(fromCell.getCellType());
switch (fromCell.getCellType()) {
case Cell.CELL_TYPE_BOOLEAN:
toCell.setCellValue(fromCell.getBooleanCellValue());
break;
case Cell.CELL_TYPE_FORMULA:
toCell.setCellFormula(fromCell.getCellFormula());
break;
case Cell.CELL_TYPE_NUMERIC:
toCell.setCellValue(fromCell.getNumericCellValue());
break;
case Cell.CELL_TYPE_STRING:
toCell.setCellValue(fromCell.getStringCellValue());
break;
default:
}
}
}
// copy merged region
List<CellRangeAddress> shiftedRegions = new ArrayList<CellRangeAddress>();
for (int i = 0; i < sheet.getNumMergedRegions(); i++) {
CellRangeAddressBase r = sheet.getMergedRegion(i);
if (r.getFirstRow() >= from && r.getLastRow() < from + count) {
CellRangeAddress n_r = new CellRangeAddress(r.getFirstRow() + to - from,r.getLastRow() + to - from,r.getFirstColumn(),r.getLastColumn());
shiftedRegions.add(n_r);
}
}
// readd so it doesn't get shifted again
Iterator<CellRangeAddress> iterator = shiftedRegions.iterator();
while (iterator.hasNext()) {
CellRangeAddress region = iterator.next();
sheet.addMergedRegion(region);
}
}
public static void shiftCell(Sheet sheet, Row row, Cell beginCell, int shift, int rowCount) {
if (shift == 0)
return;
// get the from & to row
int fromRow = row.getRowNum();
int toRow = row.getRowNum()+rowCount-1;
for (int i = 0; i < sheet.getNumMergedRegions(); i++) {
CellRangeAddressBase r = sheet.getMergedRegion(i);
if (r.getFirstRow() == row.getRowNum()) {
if (r.getLastRow() > toRow) {
toRow = r.getLastRow();
}
if (r.getFirstRow() < fromRow) {
fromRow = r.getFirstRow();
}
}
}
for (int rownum = fromRow; rownum <= toRow; rownum++) {
Row curRow = WorkBookUtil.getRow(rownum, sheet);
int lastCellNum = curRow.getLastCellNum();
for (int cellpos = lastCellNum; cellpos >= beginCell.getColumnIndex(); cellpos--) {
Cell fromCell = WorkBookUtil.getCell(curRow, cellpos);
Cell toCell = WorkBookUtil.getCell(curRow, cellpos + shift);
toCell.setCellType(fromCell.getCellType());
toCell.setCellStyle(fromCell.getCellStyle());
switch (fromCell.getCellType()) {
case Cell.CELL_TYPE_BOOLEAN:
toCell.setCellValue(fromCell.getBooleanCellValue());
break;
case Cell.CELL_TYPE_FORMULA:
toCell.setCellFormula(fromCell.getCellFormula());
break;
case Cell.CELL_TYPE_NUMERIC:
toCell.setCellValue(fromCell.getNumericCellValue());
break;
case Cell.CELL_TYPE_STRING:
toCell.setCellValue(fromCell.getStringCellValue());
break;
case Cell.CELL_TYPE_ERROR:
toCell.setCellErrorValue(fromCell.getErrorCellValue());
break;
}
fromCell.setCellValue("");
fromCell.setCellType(Cell.CELL_TYPE_BLANK);
HSSFWorkbook wb = new HSSFWorkbook();
CellStyle style = wb.createCellStyle();
fromCell.setCellStyle(style);
}
// process merged region
for (int cellpos = lastCellNum; cellpos >= beginCell.getColumnIndex(); cellpos--) {
Cell fromCell = WorkBookUtil.getCell(curRow, cellpos);
List<CellRangeAddress> shiftedRegions = new ArrayList<CellRangeAddress>();
for (int i=0; i<sheet.getNumMergedRegions(); i++) {
CellRangeAddress r = sheet.getMergedRegion(i);
if (r.getFirstRow()==curRow.getRowNum() && r.getFirstColumn() == fromCell.getColumnIndex()) {
r.setFirstColumn((short) (r.getFirstColumn() + shift));
r.setLastColumn((short) (r.getLastColumn() + shift));
// have to remove/add it back
shiftedRegions.add(r);
sheet.removeMergedRegion(i);
// we have to back up now since we removed one
i = i - 1;
}
}
// readd so it doesn't get shifted again
Iterator<CellRangeAddress> iterator = shiftedRegions.iterator();
while (iterator.hasNext()) {
CellRangeAddress region = iterator.next();
sheet.addMergedRegion(region);
}
}
}
}
/**
* 根据Excel的数字行号转换成字符行号
* @param colNumber 数字行号
* @return 字符行号,例如:A、B、C......AB、AC
*/
public static String getExcelColCharacter(int colNumber) {
//计算的过程:可以把Excel中的行号看成是27进制,A代表1 ,满27进1,从左到右进行计算,最后倒置结果
int num = colNumber / 26;//26 代表字母个数
StringBuilder colChar = new StringBuilder();
//计算余数,以余数作为开始计算值
if (colNumber % 26 > 0) {
//'A' - 1 + 余数 主要作用把余数转换成字母
colChar.append((char)('A' -1 + (colNumber % 26)));
}
for (int i = 0; i < num; i++) {
add(colChar, 0, 'Z');
}
//结果倒置
colChar.reverse();
return colChar.toString();
}
private static void add(StringBuilder colChar, int index, int addNum) {
if(index > colChar.length() - 1){
colChar.append((char)addNum);
return;
}
char ch = colChar.charAt(index);
//addNum - 'A' + 1 : 把相加的字母转换成相加的数
char addResult = (char) (ch + addNum - 'A' + 1);
if (addResult > 'Z') {
//满27进1,'A'代表1
//先addResult - 'Z'结果是相差多少,'A' - 1主要作用是转换成字母
colChar.replace(index, index + 1, (char)(addResult - 'Z' + 'A' - 1) + "");
add(colChar, index + 1, 'A');
} else {
colChar.replace(index, index + 1, (char)addResult + "");
}
}
}
下面是导出错误信息用到的工具类
package com.bookdao.oasis.utils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.json.JSONObject;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import com.bookdao.oasis.common.tools.json.jackson.JacksonUtil;
import com.google.common.collect.Maps;
public class HttpUtil {
/**
* ZIP文件
*/
public static final String HTTP_MIME_ZIP = "application/zip";
/**
* Excel文件
*/
public static final String HTTP_MIME_XLS = "application/vnd.ms-excel";
/**
* 二进制输出,支持所有文件
*/
public static final String HTTP_MIME_ALL = "application/octet-stream";
/**
* word add by zhanghuajie 20160209
*/
public static final String HTTP_MIME_WORD = "application/msword";
/**
* pdf add by zhanghuajie 20160209
*/
public static final String HTTP_MIME_PDF = "application/pdf";
public static Map<String, Object> httpRequestParamaterWrap(
HttpServletRequest request) {
HashMap<String, Object> result = new HashMap<String, Object>();
Enumeration<String> enumeration = request.getParameterNames();
while (enumeration.hasMoreElements()) {
String key = enumeration.nextElement();
String value = request.getParameter(key);
if (null != value && (value = value.trim()).length() > 0) {
try {
value = URLDecoder.decode(value, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
result.put(key, value);
}
}
return result;
}
/**
* @Title sendPost
* @Description 调用erp借口 推送信息
* @param url
* erp借口地址
* @param param
* 传递参数 void
* @author zhuchunyang
* @date 2015年10月21日-下午3:32:28
* @update
* @throws
*/
public static void sendPost(String url, Map<String, String> param) {
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
try {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
for (String key : param.keySet()) {
nameValuePairs.add(new BasicNameValuePair(key, URLEncoder
.encode(param.get(key), "UTF-8")));
}
httpPost.setHeader("Content-Type",
"application/x-www-form-urlencoded;charset=UTF-8");
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse httpResponse = httpClient.execute(httpPost);
if (httpResponse.getStatusLine().getStatusCode() == 200) {
System.out.println("调用成功!");
}
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 建立远程连接
* @throws
*/
@SuppressWarnings({ "deprecation", "resource" })
public static String sendPostReturn(String url, Map<String, String> param) throws Exception {
String msg = "";
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
// nameValuePairs.add(new BasicNameValuePair("json", URLEncoder.encode(json, "UTF-8")));
for (String key : param.keySet()) {
if(param.get(key) != null){
nameValuePairs.add(new BasicNameValuePair(key, URLEncoder
.encode(param.get(key), "UTF-8")));
}
}
httpPost.setHeader("Content-Type",
"application/x-www-form-urlencoded;charset=UTF-8");
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse httpResponse = httpClient.execute(httpPost);
if (httpResponse.getStatusLine().getStatusCode() == 200) {
HttpEntity entity = httpResponse.getEntity();
msg = EntityUtils.toString(entity);
}else{
msg = "对接信息失败!";
}
return msg;
}
/**
* @Title sendPost
* @Description 调用erp借口 推送信息
* @param url
* erp借口地址
* @param param
* 传递参数 void
*/
public static String sendPostStock(String url, Map<String, String> param) {
String jsonStr = "";
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
try {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
for (String key : param.keySet()) {
nameValuePairs.add(new BasicNameValuePair(key, URLEncoder
.encode(param.get(key), "UTF-8")));
}
httpPost.setHeader("Content-Type",
"application/x-www-form-urlencoded;charset=UTF-8");
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse httpResponse = httpClient.execute(httpPost);
if(httpResponse.getStatusLine().getStatusCode() == 200){
jsonStr = EntityUtils.toString(httpResponse.getEntity(), "utf-8");
}else if(httpResponse.getStatusLine().getStatusCode() != 200){
if(httpResponse.getStatusLine().getStatusCode() == 302){
Map info = Maps.newHashMap();
info.put("FLAG", false);
info.put("MSG", httpResponse.getStatusLine().toString());
jsonStr = JacksonUtil.fromObjectToJson(info).toString();
}else{
jsonStr = EntityUtils.toString(httpResponse.getEntity(), "utf-8");
}
}
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return jsonStr;
}
/**
* 根据请求浏览器类型(Chrome、Firefox、IE)获取下载文件名
*
* @return
*/
public static String getNewName(HttpServletRequest request, String oldName) {
String agent = request.getHeader("USER-AGENT");
String result = "";
try {
if (null != agent && -1 != agent.indexOf("Chrome")) { // Chrome
result = new String(oldName.getBytes("UTF-8"), "iso-8859-1");
} else if (null != agent && -1 != agent.indexOf("Firefox")) { // Firefox
result = "=?UTF-8?B?"
+ (new String(
org.apache.commons.codec.binary.Base64
.encodeBase64(oldName.getBytes("UTF-8"))))
+ "?=";
} else {// IE7++
result = java.net.URLEncoder.encode(oldName, "UTF-8");
result = StringUtils.replace(result, "+", "%20");
}
} catch (UnsupportedEncodingException e) {
result = oldName;
}
return result;
}
/**
* 下载文件到客户端
*
* @Title sendFile
* @Description TODO
* @param request
* @param response
* @param fileName
* 文件路径
* @param downLoadName
* 下载文件名
* @param contentType
* 文件类型
* @update
*
*/
public static void sendFile(HttpServletRequest request,
HttpServletResponse response, String fileName, String downLoadName,
String contentType) {
File file = new File(fileName);
if (!file.exists()) {
return;
}
InputStream in = null;
try {
in = new FileInputStream(file);
sendFile(request, response, in, downLoadName, contentType);
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (null != in) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 下载文件到客户端
*
* @Title sendFile
* @Description TODO
* @param request
* @param response
* @param in
* 文件输入流
* @param downLoadName
* 下载文件名
* @param contentType
* 类型
*
*/
public static void sendFile(HttpServletRequest request,
HttpServletResponse response, InputStream in, String downLoadName,
String contentType) {
response.setContentType(contentType);
downLoadName = HttpUtil.getNewName(request, downLoadName);
OutputStream out = null;
try {
int fileSize = 0;
fileSize = in.available();
response.setHeader("content-disposition", "attachment;filename=\""
+ downLoadName + "\";size=" + fileSize);
out = response.getOutputStream();
byte[] b = new byte[1024];
int len = 0;
while ((len = in.read(b)) != -1) {
out.write(b, 0, len);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (null != out) {
out.flush();
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 对前台提交的进行编码过的数据进行解码
*
* @Title oasisDecode
* @Description TODO
* @param sourceCode
* @return
* @throws UnsupportedEncodingException
* @update
*
*/
public static String oasisDecode(String sourceCode) throws UnsupportedEncodingException{
return URLDecoder.decode(new String(Base64.decodeBase64(sourceCode),"UTF-8"),"UTF-8");
}
/**
* 对字符串进行编码
*
* @Title oasisEncode
* @Description TODO
* @param sourceCode
* @return
* @throws UnsupportedEncodingException
* @update
*
*/
public static String oasisEncode(String sourceCode) throws UnsupportedEncodingException{
return new String(Base64.encodeBase64String(URLEncoder.encode(sourceCode,"UTF-8").getBytes("UTF-8")));
}
/**
* @throws Exception
* @Title sendPost
* @Description 调用erp借口 推送信息
* @param url
* erp借口地址
* @param param
* 传递参数 void
* @update
* @throws
*/
public static Map<String, Object> sendPostMap(String url, Map<String, String> param) throws Exception {
Map<String, Object> result = Maps.newHashMap();
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
HttpEntity entity = null;
try {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
for (String key : param.keySet()) {
nameValuePairs.add(new BasicNameValuePair(key, URLEncoder
.encode(param.get(key), "UTF-8")));
}
httpPost.setHeader("Content-Type",
"application/x-www-form-urlencoded;charset=UTF-8");
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse httpResponse = httpClient.execute(httpPost);
int statusCode = httpResponse.getStatusLine().getStatusCode();
entity = httpResponse.getEntity();
String data = EntityUtils.toString(entity, "utf-8");
result.put("statusCode", statusCode);
result.put("result", data);
} catch (Exception e) {
e.printStackTrace();
throw e;
} finally {
httpPost.abort();
}
return result;
}
}
二、接收文件
前台
<a href="javascript:void(0)" id="importBtn" class="btn shiny btn-sm">
<i class="fa fa-sign-in">导入</i>
</a>
<form method="post" id="importForm" enctype="multipart/form-data">
<input type="file" name="file" id="fileInput" style="display:none;"/>
</form>
JS
$("#importBtn").click(function(){
$("#fileInput").trigger("click");
});
大坑之:$("#fileInput").val("");成功之后一定把里面的东西置空,不然没办法二次点击
URL:记得替换
//导入文件
$("#fileInput").change(function(){
var form = $("#importForm");
form.attr("action",URL);
form.ajaxSubmit({
beforeSubmit:function(){
$.plugin.plugLoading("正在导入商品,请稍候...");
},
success:function(data) {
$.plugin.close();
$("#fileInput").val("");
if (!data) {
$.messager.alert("系统提示", "后台错误", "warning");
return false;
}
if (data.success) {
$.messager.alert("系统提示", "导入成功", "warning");
$("#datagrid_table").datagrid('reload');
return false;
}else {
if (data.msg) {
$.messager.alert("系统提示", data.msg, "warning");
return false;
}
if (data.fileName) {
$("#datagrid_table").datagrid('reload');
$.messager.confirm('系统提示', "有导入失败数据,是否下载错误数据?", function (ok) {
if (ok) {
downExcel(URL,
data.fileName);
} else {
return false;
}
});
}
}
}
});
});
/**
* 下载明细错误信息
* @param url
* @param fileName
*/
function downExcel(url,fileName) {
var tmpForm = $("#downloadForm");
tmpForm.html("");
var input = $("<input>");
input.attr("name", "fileName");
input.attr("value", fileName);
tmpForm.append(input);
tmpForm.attr("method", "post");
tmpForm.attr("action", url);
tmpForm.submit();
}
ExcelModel类,和导入的Excel模板对应上
Remark是备注的意思,导入的文件是没有的,我写上是为了导出错误信息
@ExcelObject(true)
public class ExcelStandardBookVO {
@ExcelField(index = "1", cellColumnName = "书号")
private String barcode;
@ExcelField(index = "2", cellColumnName = "定价")
private String productPrice;
@ExcelField(index = "3", cellColumnName = "商品品名")
private String name;
@ExcelField(index = "4", cellColumnName = "样品类型")
private String typeName;
@ExcelField(index = "5", cellColumnName = "印次")
private String banyinReal;
@ExcelField(index = "6", cellColumnName = "备注")
private String Remark;
读取内容不包含标题;名称对上Excel里只要有对应字段标题就可以导入
list = ExcelReader.read(in, ExcelStandardBookVO.class);
我下面用的是需要导入标题的
我利用File标签传的
String fileName = file.getOriginalFilename();
InputStream in = null;
List<ExcelStandardBookVO> list = new ArrayList<>();
try {
in = file.getInputStream();
// list = ExcelReader.read(in, ExcelStandardBookVO.class);
ExcelReader<ExcelStandardBookVO> excelReader = new ExcelReader<ExcelStandardBookVO>(
0, 4, 0, null, ExcelStandardBookVO.class);
list = excelReader.read(in);
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
if (null != in) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return list;
4、错误内容下载,下载要求是把错误数据放上并且加错误原因(导入失败的原因)
错误信息的内容在有相关检验的时候就存进Excel类List集合里面。我用的和导入是一个ExcelVO类
只能作为例子看,担心大家不知道怎么存所以放在这里而已
List<ExcelStandardBookVO> failMSG = new ArrayList<>();
excelStandardBook.setRemark("书号不能为空");
failMSG.add(excelStandardBook);
@RequestMapping("/downLoadError")
@ResponseBody
public void downLoadError(HttpServletRequest request,HttpServletResponse response) {
mmStandardSampleLog.info(">>>>>mmStandardSampleLog.downLoadError");
String fileName = request.getParameter("fileName");
String tempPath = System.getProperty("java.io.tmpdir");
File file = new File(tempPath + File.separator + fileName);
if (!file.exists() || !file.isFile()) {// 文件不存在,自动跳转404
return;
}
String httpMime = "";
if (fileName.endsWith(".zip")) {
httpMime = HttpUtil.HTTP_MIME_ZIP;
} else {
httpMime = HttpUtil.HTTP_MIME_XLS;
}
mmStandardSampleLog.info("<<<<<<<<<<MmStandardSampleController.importBook");
HttpUtil.sendFile(request, response, file.getPath(), file.getName(),
httpMime);
}
我是在有错误信息的时候就创建Excel模板,下面是创建模板。
public String createErrorFile(List<ExcelStandardBookVO> matchingBookResult) {
String tempPath = System.getProperty("java.io.tmpdir");
InputStream in = null;
try {
String tempFile = this//ERROR_CUSTOMER_SALES_PRODUCT_LIST
.completeExcelTemplate("MM_STANDARD_BOOK_ERROR.xlsx");
in = new FileInputStream(tempFile);
ExcelWriter<ExcelStandardBookVO> excelWriter = new ExcelWriter<ExcelStandardBookVO>(
in, "错误数据", tempPath, ExcelConstants.OFFICE_2007,
"sheetName", ExcelStandardBookVO.class);
excelWriter.setStartColumn(0);
excelWriter.setStartRow(1);
excelWriter.push(matchingBookResult);
excelWriter.flush();
String finalFile = excelWriter.getFinalFile();
if (null != finalFile) {
finalFile = finalFile.substring(tempPath.length());
return finalFile;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != in) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
//制作Excel模板
private String completeExcelTemplate(String templateName) {
String path = this.getClass().getClassLoader().getResource("")
.getPath();
StringBuilder tempString = new StringBuilder();
tempString.append(path).append(File.separator).append("template")
.append(File.separator).append("excel").append(File.separator)
.append("mm").append(File.separator).append(templateName);
return tempString.toString();
}