ExcelUtil导入导出

说明:数据库使用mysql,导入的字段类型只能是有varchar,Date 类型

火狐导出文件时做特殊设置,不能用url编码

ExcelUtil.java

package com.lw.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.sql.SQLException;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.InputMismatchException;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.FilenameUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFDataFormat;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
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.xssf.usermodel.XSSFWorkbook;
import org.springframework.util.CollectionUtils;


/**
 * Excel组件
 * 
 * @author david
 * @version 1.0
 * @since 1.0
 */
public class ExcelUtil {

	/**
	 * Excel 2003
	 */
	private final static String XLS = "xls";
	/**
	 * Excel 2007
	 */
	private final static String XLSX = "xlsx";

	/***
	 * 导入Excel数据
	 * 
	 * <li>1、读取excel数据</li>
	 * <li>2、校验数据的合法性(日期,金额,字符长度(和数据库结构比较))</li>
	 * <li>3、合法数据绑定到bean对象中(反射)</li>
	 * <li>4、得到数据层面校验通过的bean对象集合,</li>
	 * 
	 * @param file
	 *            导入数据文件
	 * @param entityClass
	 *            bean对象类型bean.class
	 * @param sheetIndex
	 *            sheet索引
	 * @param columnArray
	 *            字段列数组 (需要导入的字段数组)
	 * @param checkColumn
	 *            需要校验格式的字段列Map
	 * @throws IOException
	 * @throws NoSuchFieldException
	 * @throws SecurityException
	 * @throws InstantiationException
	 * @throws SQLException
	 * @throws IllegalAccessException
	 * @throws ParseException
	 */
	public static <T> List<T> excelToList(File file, Integer sheetIndex, Class<T> entityClass, String[] columnArray,
			Map<String, ColumnCheckTypeEnum> checkColumn) throws IOException, SecurityException, NoSuchFieldException,
					InstantiationException, SQLException, IllegalAccessException, ParseException {
		List<T> list = new ArrayList<T>();
		Workbook workbook = null;
		if (XLS.equalsIgnoreCase(FilenameUtils.getExtension(file.getName()))) {
			workbook = new HSSFWorkbook(new FileInputStream(file));
		} else if (XLSX.equalsIgnoreCase(FilenameUtils.getExtension(file.getName()))) {
			workbook = new XSSFWorkbook(new FileInputStream(file));
		} else {
			throw new IOException("导入excel出错,不支持文件类型!");
		}
		if (sheetIndex == null) {
			sheetIndex = 0;
		}
		if ((sheetIndex + 1) > workbook.getNumberOfSheets()) {
			throw new IndexOutOfBoundsException("导入excel出错,指定sheet索引越界!");
		}
		// sheet中要导出的列
		if (columnArray == null || columnArray.length < 1) {
			throw new NullPointerException("导入excel出错,导入列设置错误!");
		}

		// 拿到sheet
		Sheet sheet = workbook.getSheetAt(sheetIndex);
		String sheetName = sheet.getSheetName(); // sheetName 使用表名称

		// 解析公式结果
		FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
		// 每个sheet中的数据
		List<Map<String, Object>> dataList = readSheet(sheet, evaluator, columnArray);

		// 数据库表对应的字段列信息
		List<ColumnData> columnDatas = null;
		try {
			columnDatas = DBDataUtil.getMySqlColumnDatas(sheetName, "dbName");
		} catch (SQLException e) {
			throw new SQLException("导入excel出错,获取表信息错误!");
		}
		// 不在数据库中的列
		List<String> outColumnDatas = new ArrayList<String>();
		List<String> columnList = new ArrayList<String>();
		for (int i = 0; i < columnDatas.size(); i++) {
			columnList.add(columnDatas.get(i).getColumnLowName());
		}
		for (int i = 0; i < columnArray.length; i++) {
			if (!columnList.contains(columnArray[i])) {
				outColumnDatas.add(columnArray[i]);
			}
		}

		// 遍历数据库表对应的字段列信息
		for (int j = 0; j < dataList.size(); j++) {
			// 拿到每一行的数据
			Map<String, Object> rowData = dataList.get(j);
			T o = null;
			try {
				o = (T) entityClass.newInstance();
			} catch (IllegalAccessException e) {
				throw new IllegalAccessException("导入excel出错,错误信息:" + e.getMessage());
			}
			if (checkColumn == null) {
				checkColumn = new HashMap<String, ColumnCheckTypeEnum>();
			}
			// 1、循环列(数据库中包含)设置,依次设置每一列
			for (int k = 0; k < columnDatas.size(); k++) {
				ColumnData cd = columnDatas.get(k);
				Object value = rowData.get(cd.getColumnLowName());

				String errMsg = "导入excel出错,错误位置>>:第【" + (j + 1 + 1) + "】行,第【"
						+ (getIndexOfArrayItem(cd.getColumnLowName(), columnArray) + 1 + 1) + "】列。错误信息:";
				// 1、先根据设置,校验自定义校验的列
				if (checkColumn.containsKey(cd.getColumnLowName()) == false || ColumnCheckTypeEnum.CHECK_TYPE_NOTNULL
						.equals(checkColumn.get(cd.getColumnLowName())) == false) {
					if (value == null) {
						continue;
					}
				}
				ColumnCheckTypeEnum checkType = checkColumn.get(cd.getColumnLowName());
				customColumnCheck(value, errMsg, checkType);

				// 2、自定义校验完成后,进行常规校验
				// 通过属性名称获取属性,把值设置到属性里面
				Field field = entityClass.getDeclaredField(cd.getColumnLowName());
				field.setAccessible(true); // 设置属性可访问, private
				if ("java.lang.String".equalsIgnoreCase(cd.getJavaType())) {
					if (value.toString().length() > Integer.parseInt(cd.getDataMaxLength())) {
						throw new SQLException(errMsg + "当前数据长度不能超过【" + cd.getDataMaxLength() + "】,当前文本长度【" + value.toString().length() + "】");
					}
					try {
						field.set(o, value.toString());
					} catch (IllegalArgumentException e) {
						throw new IllegalArgumentException(errMsg + e.getMessage());
					} catch (IllegalAccessException e) {
						throw new IllegalAccessException(errMsg + e.getMessage());
					}
				} else if ("java.util.Date".equalsIgnoreCase(cd.getJavaType())) {
					try {
						field.set(o, (Date) value);
					} catch (ClassCastException e) {
						throw new ClassCastException(errMsg + "数据格式错误,无法将【" + value + "】转换为java.util.Date类型日期格式。" + e.getMessage());
					} catch (IllegalArgumentException e) {
						throw new IllegalArgumentException(errMsg + e.getMessage());
					} catch (IllegalAccessException e) {
						throw new IllegalAccessException(errMsg + e.getMessage());
					}
				} else if ("java.lang.Integer".equalsIgnoreCase(cd.getJavaType())) {
					try {
						if(value!=null && !"".equals(value.toString())) {
							field.set(o, Integer.parseInt(value.toString()));
						}
					} catch (NumberFormatException e) {
						throw new NumberFormatException(errMsg + "数据格式错误,无法将【" + value + "】转换为java.lang.Integer类型。" + e.getMessage());
					} catch (IllegalArgumentException e) {
						throw new IllegalArgumentException(errMsg + e.getMessage());
					} catch (IllegalAccessException e) {
						throw new IllegalAccessException(errMsg + e.getMessage());
					}
				} else if ("java.math.BigDecimal".equalsIgnoreCase(cd.getJavaType())) {
					try {
						if(value!=null && !"".equals(value.toString())) {
							field.set(o, new BigDecimal(value.toString()));
						}
					} catch (NumberFormatException e) {
						throw new NumberFormatException(errMsg + "数据格式错误,无法将【" + value + "】转换为java.math.BigDecimal类型。" + e.getMessage());
					} catch (IllegalArgumentException e) {
						throw new IllegalArgumentException(errMsg + e.getMessage());
					} catch (IllegalAccessException e) {
						throw new IllegalAccessException(errMsg + e.getMessage());
					}
				}
			}

			// 2、循环列(数据库中不包含)设置,依次设置每一列
			for (int k = 0; k < outColumnDatas.size(); k++) {
				String columnLowName = outColumnDatas.get(k);
				Object value = rowData.get(outColumnDatas.get(k));

				String errMsg = "导入excel出错,错误位置>>:sheet【" + sheetName + "】中,第【" + (j + 1 + 1) + "】行,第【"
						+ (getIndexOfArrayItem(columnLowName, columnArray) + 1 + 1) + "】列。错误信息:";
				// 1、先根据设置,校验自定义校验的列
				if (checkColumn.containsKey(columnLowName) == false
						|| ColumnCheckTypeEnum.CHECK_TYPE_NOTNULL.equals(checkColumn.get(columnLowName)) == false) {
					if (value == null) {
						continue;
					}
				}
				customColumnCheck(value, errMsg, checkColumn.get(columnLowName));
				// 通过属性名称获取属性,把值设置到属性里面
				Field field = entityClass.getDeclaredField(columnLowName);
				field.setAccessible(true); // 设置属性可访问, private
				String type = field.getType().getName();
				if ("java.lang.String".equalsIgnoreCase(type)) {
					try {
						field.set(o, value.toString());
					} catch (IllegalArgumentException e) {
						throw new IllegalArgumentException(errMsg + e.getMessage());
					} catch (IllegalAccessException e) {
						throw new IllegalAccessException(errMsg + e.getMessage());
					}
				} else if ("java.util.Date".equalsIgnoreCase(type)) {
					try {
						field.set(o, (Date) value);
					} catch (ClassCastException e) {
						throw new ClassCastException(errMsg + "数据格式错误,无法将【" + value + "】转换为java.util.Date类型日期格式。" + e.getMessage());
					} catch (IllegalArgumentException e) {
						throw new IllegalArgumentException(errMsg + e.getMessage());
					} catch (IllegalAccessException e) {
						throw new IllegalAccessException(errMsg + e.getMessage());
					}
				} else if ("java.lang.Integer".equalsIgnoreCase(type)) {
					try {
						if(value!=null && !"".equals(value.toString())) {
							field.set(o, Integer.parseInt(value.toString()));
						}
					} catch (NumberFormatException e) {
						throw new NumberFormatException(errMsg + "数据格式错误,无法将【" + value + "】转换为java.lang.Integer类型。" + e.getMessage());
					} catch (IllegalArgumentException e) {
						throw new IllegalArgumentException(errMsg + e.getMessage());
					} catch (IllegalAccessException e) {
						throw new IllegalAccessException(errMsg + e.getMessage());
					}
				} else if ("java.math.BigDecimal".equalsIgnoreCase(type)) {
					try {
						if(value!=null && !"".equals(value.toString())) {
							field.set(o, new BigDecimal(value.toString()));
						}
					} catch (NumberFormatException e) {
						throw new NumberFormatException(errMsg + "数据格式错误,无法将【" + value + "】转换为java.math.BigDecimal类型。" + e.getMessage());
					} catch (IllegalArgumentException e) {
						throw new IllegalArgumentException(errMsg + e.getMessage());
					} catch (IllegalAccessException e) {
						throw new IllegalAccessException(errMsg + e.getMessage());
					}
				}
			}
			list.add(o);
		}
		return list;
	}

	/**
	 * @param value
	 * @param errMsg
	 * @param checkType
	 */
	private static void customColumnCheck(Object value, String errMsg, ColumnCheckTypeEnum checkType) {
		// 非空校验
		if (ColumnCheckTypeEnum.CHECK_TYPE_NOTNULL.equals(checkType)) {
			if (value == null) {
				throw new InputMismatchException(errMsg + "此列为非空列,请检查excel数据是否为空!");
			}
		}
		// 整数类型校验
		else if (ColumnCheckTypeEnum.CHECK_TYPE_LONG.equals(checkType)) {
			try {
				Long.parseLong(value.toString());
			} catch (NumberFormatException e) {
				throw new NumberFormatException(
						errMsg + "此列为整数列,单元格应设置为文本类型,请检查excel数据是否整数数字或单元格是否为文本类型!" + e.getMessage());
			}
		}
		// 价格类型校验,取2位小数
		else if (ColumnCheckTypeEnum.CHECK_TYPE_PRICE.equals(checkType)) {
			try {
				String price = value.toString();
				new BigDecimal(price);
				if (price.indexOf(".") > -1 && price.split("\\.")[1].length() > 2) {
					throw new InputMismatchException(errMsg + "此列为金额数值列,小数点后不超过2位小数,请检查excel数据是否合格!");
				}
			} catch (NumberFormatException e) {
				throw new NumberFormatException(errMsg + "此列为金额数值列,请检查excel数据是否合格!");
			}
		}
		// 价格类型校验,取4位小数
		else if (ColumnCheckTypeEnum.CHECK_TYPE_PRICE_1.equals(checkType)) {
			try {
				String price = value.toString();
				new BigDecimal(price);
				if (price.indexOf(".") > -1 && price.split("\\.")[1].length() > 4) {
					throw new InputMismatchException(errMsg + "此列为金额数值列,小数点后不超过4位小数,请检查excel数据是否合格!");
				}
			} catch (NumberFormatException e) {
				throw new NumberFormatException(errMsg + "此列为金额数值列,请检查excel数据是否合格!");
			}
		}
	}

	/***
	 * 读取单个sheet
	 * <p>
	 * 导入Excel数据使用私有方法
	 * </p>
	 * 
	 * @param sheet
	 *            单个sheet
	 * @param evaluator
	 *            解析公式结果
	 * @param columnArray
	 *            字段列数组
	 */
	private static List<Map<String, Object>> readSheet(Sheet sheet, FormulaEvaluator evaluator, String... columnArray) {
		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		int firstRowNum = sheet.getFirstRowNum();
		int lastRowNum = sheet.getLastRowNum();
		// 从第二行开始读取数据
		for (int rowIndex = firstRowNum + 1; rowIndex <= lastRowNum; rowIndex++) {
			Row row = sheet.getRow(rowIndex);
			short firstCellNum = row.getFirstCellNum();
			// short maxColIx = row.getLastCellNum();
			Map<String, Object> rowMap = new HashMap<String, Object>();
			// 读取列的时候,按照设置好的字段列的数量长度循环读取
			for (short colIndex = firstCellNum; colIndex < columnArray.length; colIndex++) {
				Cell cell = row.getCell(new Integer(colIndex) + 1); // 从第二列开始导入,
																	// 第一列序号列不做导入
				CellValue cellValue = evaluator.evaluate(cell);
				if (cellValue == null) {
					continue;
				}
				// 经过公式解析,最后只存在Boolean、Numeric和String三种数据类型,此外就是Error了
				// 其余数据类型,根据官方文档,完全可以忽略http://poi.apache.org/spreadsheet/eval.html
				switch (cellValue.getCellType()) {
				case Cell.CELL_TYPE_BOOLEAN:
					rowMap.put(columnArray[colIndex], cellValue.getBooleanValue());
					break;
				case Cell.CELL_TYPE_NUMERIC:
					// 这里的日期类型会被转换为数字类型,需要判别后区分处理
					if (HSSFDateUtil.isCellDateFormatted(cell)) {
						rowMap.put(columnArray[colIndex], cell.getDateCellValue());
					} else {
						rowMap.put(columnArray[colIndex], cellValue.getNumberValue());
					}
					break;
				case Cell.CELL_TYPE_STRING:
					rowMap.put(columnArray[colIndex], cellValue.getStringValue());
					break;
				case Cell.CELL_TYPE_FORMULA:
					break;
				case Cell.CELL_TYPE_BLANK:
					break;
				case Cell.CELL_TYPE_ERROR:
					break;
				default:
					break;
				}
			}
			list.add(rowMap);
		}

		return list;
	}

	private static int getIndexOfArrayItem(String arrItem, String[] array) {
		int index = -1;
		for (int i = 0; i < array.length; i++) {
			if (array[i].equals(arrItem)) {
				index = i;
				break;
			}
		}
		return index;
	}

	/***
	 * 导出Excel数据
	 * 
	 * @param fileName
	 *            导出文件名
	 * @param sheetName
	 *            sheet名称
	 * @param list
	 *            要导出的数据
	 * @param dataFormatMap
	 *            可以设置某个列的数据格式 ,key:列名;value:格式值
	 * @param request
	 * @param response
	 * @throws IOException
	 */
	public static void exportDatas(String fileName, String sheetName, List<Map<String, Object>> list,
			Map<String, CellDataFormatEnum> dataFormatMap, HttpServletRequest request, HttpServletResponse response)
					throws IOException {
		HSSFWorkbook wb = new HSSFWorkbook();
		HSSFSheet sheet = wb.createSheet(sheetName);
		if (CollectionUtils.isEmpty(list)) {
			// 输出空文件
			outputFile(fileName, request, response, wb);
			return;
		}
		int rowNum = 0;

		// 设置单元格样式(标题样式)
		HSSFCellStyle styleTitle = wb.createCellStyle();
		styleTitle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
		styleTitle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
		styleTitle.setBorderRight(HSSFCellStyle.BORDER_THIN);
		styleTitle.setBorderTop(HSSFCellStyle.BORDER_THIN);
		// 对齐方式
		styleTitle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
		styleTitle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
		// 字体
		HSSFFont font = wb.createFont();
		font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
		styleTitle.setFont(font);

		// 设置单元格样式(数据值样式)
		HSSFCellStyle styleContent = wb.createCellStyle();
		styleContent.setBorderBottom(HSSFCellStyle.BORDER_THIN);
		styleContent.setBorderLeft(HSSFCellStyle.BORDER_THIN);
		styleContent.setBorderRight(HSSFCellStyle.BORDER_THIN);
		styleContent.setBorderTop(HSSFCellStyle.BORDER_THIN);
		styleContent.setAlignment(HSSFCellStyle.ALIGN_CENTER);

		HSSFCellStyle styleContent1 = wb.createCellStyle();
		styleContent1.setBorderBottom(HSSFCellStyle.BORDER_THIN);
		styleContent1.setBorderLeft(HSSFCellStyle.BORDER_THIN);
		styleContent1.setBorderRight(HSSFCellStyle.BORDER_THIN);
		styleContent1.setBorderTop(HSSFCellStyle.BORDER_THIN);
		styleContent1.setAlignment(HSSFCellStyle.ALIGN_CENTER);
		
		// 标题行
		HSSFRow rowTitle = sheet.createRow(rowNum++);

		int i = 0;
		HSSFCell cellH0 = rowTitle.createCell(i++);
		cellH0.setCellValue("序号");
		cellH0.setCellStyle(styleTitle);
		for (Map.Entry<String, Object> tmp : list.get(0).entrySet()) {
			HSSFCell cellH = rowTitle.createCell(i++);
			cellH.setCellValue(tmp.getKey());
			cellH.setCellStyle(styleTitle);
		}

		int cellOrder = 1;
		for (Map<String, Object> map : list) {
			HSSFRow row = sheet.createRow(rowNum++);
			int j = 0;
			// 序号
			HSSFCell cellC0 = row.createCell(j++);
			cellC0.setCellValue(cellOrder++);
			cellC0.setCellStyle(styleContent);

			for (Map.Entry<String, Object> entry : map.entrySet()) {
				HSSFCell cellC = row.createCell(j++);
				sheet.setColumnWidth(cellC.getColumnIndex(), 256 * (11 + 10));
				cellC.setCellValue(entry.getValue() + "");
				// 动态设置单元格的格式 枚举值对应到HSSFDataFormat的值
				CellDataFormatEnum df = null;
				if (dataFormatMap != null) {
					df = dataFormatMap.get(entry.getKey());
				}
				if (df != null) {
					if(CellDataFormatEnum.DATA_FORMAT_DOUBLE.getShortEnumCode().equals(df.getShortEnumCode())) {
						if(entry.getValue()==null || "".equals(entry.getValue())) {
							cellC.setCellValue("");
						} else {
							if(isDouble(entry.getValue()+"")) {
								styleContent1.setDataFormat(df.getShortEnumCode());
								cellC.setCellValue(Double.valueOf(entry.getValue()+""));
							} else {
								cellC.setCellValue(entry.getValue()+"");
							}
						}
					} else {
						cellC.setCellValue(entry.getValue() + "");
					}
					cellC.setCellStyle(styleContent1);
				} else {
					cellC.setCellStyle(styleContent);
				}
			}
		}

		// 输出文件
		outputFile(fileName, request, response, wb);
	}

	/***
	 * 导出Excel数据(多个sheet)
	 * 
	 * @param fileName
	 *            导出文件名
	 * @param sheetNameMap
	 *            key:sheetCode, value:sheet名称
	 * @param map
	 *            要导出的数据 Map<String, List<Map<String,
	 *            Object>>>,key:结果集的编码(表名称),value:结果集(key:字段,value:字段的值)
	 * @param dataFormatMap
	 *            设置多个sheet中某个列的数据格式,Map<String, Map<String,
	 *            CellDataFormatEnum>>,key:结果集的编码(表名称),value:(sheet中列的格式map,key:
	 *            列名;value:格式值)
	 * @param request
	 * @param response
	 * @throws IOException
	 */
	public static void exportDatas(String fileName, Map<String, String> sheetNameMap,
			Map<String, List<Map<String, Object>>> map, Map<String, Map<String, CellDataFormatEnum>> dataFormatMap,
			HttpServletRequest request, HttpServletResponse response) throws IOException {
		HSSFWorkbook wb = new HSSFWorkbook();
		if (CollectionUtils.isEmpty(map)) {
			// 输出空文件
			outputFile(fileName, request, response, wb);
			return;
		}
		for (Map.Entry<String, List<Map<String, Object>>> dataMap : map.entrySet()) {
			String resultCode = dataMap.getKey(); // 结果集的编码(表名称)
			HSSFSheet sheet = wb.createSheet(sheetNameMap.get(resultCode));
			List<Map<String, Object>> list = dataMap.getValue(); // 数据list,字段已map的形式存储
			if(CollectionUtils.isEmpty(list)) {
				continue;
			}
			int rowNum = 0;

			// 设置单元格样式(标题样式)
			HSSFCellStyle styleTitle = wb.createCellStyle();
			styleTitle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
			styleTitle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
			styleTitle.setBorderRight(HSSFCellStyle.BORDER_THIN);
			styleTitle.setBorderTop(HSSFCellStyle.BORDER_THIN);
			styleTitle.setWrapText(true);// 数据自动换行
			// 对齐方式
			styleTitle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
			styleTitle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
			// 字体
			HSSFFont font = wb.createFont();
			font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
			styleTitle.setFont(font);

			// 设置单元格样式(数据值样式)
			HSSFCellStyle styleContent = wb.createCellStyle();
			styleContent.setBorderBottom(HSSFCellStyle.BORDER_THIN);
			styleContent.setBorderLeft(HSSFCellStyle.BORDER_THIN);
			styleContent.setBorderRight(HSSFCellStyle.BORDER_THIN);
			styleContent.setBorderTop(HSSFCellStyle.BORDER_THIN);
			styleContent.setAlignment(HSSFCellStyle.ALIGN_CENTER);
			styleContent.setWrapText(true);// 数据自动换行

			HSSFCellStyle styleContent1 = wb.createCellStyle();
			styleContent1.setBorderBottom(HSSFCellStyle.BORDER_THIN);
			styleContent1.setBorderLeft(HSSFCellStyle.BORDER_THIN);
			styleContent1.setBorderRight(HSSFCellStyle.BORDER_THIN);
			styleContent1.setBorderTop(HSSFCellStyle.BORDER_THIN);
			styleContent1.setAlignment(HSSFCellStyle.ALIGN_CENTER);

			// 标题行
			HSSFRow rowTitle = sheet.createRow(rowNum++);
			
			int i = 0;
			HSSFCell cellH0 = rowTitle.createCell(i++);
			cellH0.setCellValue("序号");
			cellH0.setCellStyle(styleTitle);
			
			boolean isOnlyTitle = false;
			for (Map.Entry<String, Object> tmp : list.get(0).entrySet()) {
				HSSFCell cellH = rowTitle.createCell(i++);
				// 不是空数据的情况
				if (!"isOnlyTitle".equals(tmp.getKey())) {
					cellH.setCellValue(tmp.getKey());
					cellH.setCellStyle(styleTitle);
				} else {
					isOnlyTitle = true;
				}
			}

			// 空数据时,只输出标题信息
			if (isOnlyTitle) {
				continue;
			}

			int cellOrder = 1;
			for (Map<String, Object> entityMap : list) {
				HSSFRow row = sheet.createRow(rowNum++);
				int j = 0;
				// 序号
				HSSFCell cellC0 = row.createCell(j++);
				cellC0.setCellValue(cellOrder++);
				cellC0.setCellStyle(styleContent);

				for (Map.Entry<String, Object> entry : entityMap.entrySet()) {
					HSSFCell cellC = row.createCell(j++);
					sheet.setColumnWidth(cellC.getColumnIndex(), 256 * (11 + 10));
					// 动态设置单元格的格式 枚举值对应到HSSFDataFormat的值
					CellDataFormatEnum df = null;
					if (dataFormatMap != null) {
						Map<String, CellDataFormatEnum> map2 = dataFormatMap.get(resultCode);
						if(map2!=null) {
							df = map2.get(entry.getKey());
						}
					}
					if (df != null) {
						if(CellDataFormatEnum.DATA_FORMAT_DOUBLE.getShortEnumCode().equals(df.getShortEnumCode())) {
							if(entry.getValue()==null || "".equals(entry.getValue())) {
								cellC.setCellValue("");
							} else {
								if(isDouble(entry.getValue()+"")) {
									styleContent1.setDataFormat(df.getShortEnumCode());
									cellC.setCellValue(Double.valueOf(entry.getValue()+""));
								} else {
									cellC.setCellValue(entry.getValue()+"");
								}
							}
						} else {
							cellC.setCellValue(entry.getValue() + "");
						}
						cellC.setCellStyle(styleContent1);
					} else {
						cellC.setCellStyle(styleContent);
						cellC.setCellValue(entry.getValue() + "");
					}
				}
			}
		}
		// 输出文件
		outputFile(fileName, request, response, wb);
	}

	/**
	 * 输出文件
	 * 
	 * @param fileName
	 * @param request
	 * @param response
	 * @param wb
	 * @throws UnsupportedEncodingException
	 * @throws IOException
	 */
	private static void outputFile(String fileName, HttpServletRequest request, HttpServletResponse response,
			HSSFWorkbook wb) throws UnsupportedEncodingException, IOException {
		String agent = request.getHeader("User-Agent");
		// 火狐浏览器导出文件不会url解码
		if (agent != null && !"".equals(agent) && agent.toLowerCase().indexOf("firefox") > -1) {
			response.setHeader("Content-disposition",
					"attachment;filename=\"" + new String(fileName.getBytes("UTF-8"), "ISO-8859-1") + ".xls\"");
		} else {
			response.setHeader("Content-disposition",
					"attachment;filename=" + URLEncoder.encode(fileName + ".xls", "UTF-8"));
		}
		response.setContentType("application/vnd.ms-excel;charset=UTF-8");
		OutputStream out = response.getOutputStream();
		wb.write(out);
		out.flush();
		out.close();
	}

	/**
	 * 
	 * 解析excel Map<sheet名称,List<Map<单元格对应的标题,单元格类容>>>
	 * 
	 * @param filePath
	 * @param listSheetNames
	 * @return
	 * @throws IOException
	 */
	public static Map<String, List<Map<String, String>>> getExcelData(String filePath, List<String> listSheetNames)
			throws IOException {
		Workbook wookbook = null;
		Map<String, String> mapExcel;
		Map<Integer, String> mapColumnName = new HashMap<Integer, String>();
		Map<String, List<Map<String, String>>> mapListDatabaseNameAndData = new HashMap<String, List<Map<String, String>>>();

		try {
			try {
				wookbook = new HSSFWorkbook(new FileInputStream(filePath));
			} catch (Exception e) {
				wookbook = new XSSFWorkbook(new FileInputStream(filePath));
			}
			// 目前就一个sheet 循环读取是为了以后扩展用
			for (int i = 0; i < wookbook.getNumberOfSheets(); i++) {
				listSheetNames.add(wookbook.getSheetName(i));
			}
			Sheet sheet;
			for (int k = 0; k < listSheetNames.size(); k++) {
				sheet = wookbook.getSheet(listSheetNames.get(k));
				List<Map<String, String>> listExcelData = new ArrayList<Map<String, String>>();
				// 获取到Excel文件中的所有行数
				int rows = sheet.getPhysicalNumberOfRows();
				// 遍历行­
				for (int i = 0; i < rows; i++) {
					// 读取左上端单元格
					Row row = sheet.getRow(i);
					// 行不为空
					if (row != null) {
						boolean boolNullLine = true; // 验证是否整行是空行,有时候,会出现空行,单是无数据,可以拷贝出来得到全是竖线!
						// 获取到Excel文件中的所有的列
						int cells = row.getLastCellNum();
						mapExcel = new HashMap<String, String>();
						// 遍历列
						for (int j = 0; j < cells; j++) {
							// 获取到列的值­
							Cell cell = row.getCell(j);
							if (cell != null) {
								if (i == 0) {
									mapColumnName.put(j, cell.getStringCellValue().toUpperCase());
								}
								switch (cell.getCellType()) {
								case HSSFCell.CELL_TYPE_NUMERIC:
									boolNullLine = false;
									DecimalFormat df = new DecimalFormat("#.########");
									String strCell = df.format(cell.getNumericCellValue());
									mapExcel.put(mapColumnName.get(j), strCell);
									break;
								case HSSFCell.CELL_TYPE_STRING:
									boolNullLine = false;
									mapExcel.put(mapColumnName.get(j), cell.getStringCellValue());
									break;
								case HSSFCell.CELL_TYPE_FORMULA:
								case HSSFCell.CELL_TYPE_BLANK:
								case HSSFCell.CELL_TYPE_BOOLEAN:
								case HSSFCell.CELL_TYPE_ERROR:
								default:
									// 有些行是空行,
									mapExcel.put(mapColumnName.get(j), null);
									break;
								}
							} else {
								mapExcel.put(mapColumnName.get(j), null);
							}
						}
						// 如果这行不为空的,add
						if (!boolNullLine) {
							listExcelData.add(mapExcel);
						}
					}
				}
				mapListDatabaseNameAndData.put(listSheetNames.get(k), listExcelData);
			}
		} catch (FileNotFoundException e) {

		} finally {
			if (wookbook != null) {
				// wookbook.close();
			}
		}
		return mapListDatabaseNameAndData;
	}
	
	/**
	 * <pre>
	 * 导入excel数据列校验类型
	 * </pre>
	 */
	public enum ColumnCheckTypeEnum {
		
		CHECK_TYPE_NOTNULL("1", "非空数据校验"),
		CHECK_TYPE_PRICE("2", "价格类型校验,取2位小数"),
		CHECK_TYPE_PRICE_1("3", "价格类型校验,取4位小数"),
		CHECK_TYPE_LONG("4", "整数类型校验");
		
		private String code; // 枚举代码
		private String description; // 枚举标签
		
		private ColumnCheckTypeEnum(String code, String description) {
			this.code = code;
			this.description = description;
		}
		
		public String getEnumCode() {
			return code;
		}
		
		public String getEnumLabel() {
			return description;
		}
		
		public static ColumnCheckTypeEnum getEnumType(String enumCode) {
			ColumnCheckTypeEnum enumType = null;
			EnumSet<ColumnCheckTypeEnum> enumSet = EnumSet.allOf(ColumnCheckTypeEnum.class);
			for (ColumnCheckTypeEnum enumItem : enumSet) {
				if(enumItem.getEnumCode().equals(enumCode)) {
					enumType = enumItem;
					break;
				}
			}
			return enumType;
		}
		
	}
	
	/**
	 * <pre>
	 * 导入excel数据列校验类型
	 * </pre>
	 */
	public enum CellDataFormatEnum {
		
		DATA_FORMAT_GENERAL("" + HSSFDataFormat.getBuiltinFormat("General"), "常规"),
		DATA_FORMAT_DOUBLE("" + HSSFDataFormat.getBuiltinFormat("0.00"), "2位小数浮点型数值"),
		DATA_FORMAT_PRICE("" + HSSFDataFormat.getBuiltinFormat("0.0000"), "4位小数浮点型数值"),
		DATA_FORMAT_INT("" + HSSFDataFormat.getBuiltinFormat("0"), "整数型数值"),
		DATA_FORMAT_DATE("" + HSSFDataFormat.getBuiltinFormat("yyyy/MM/dd"), "date日期类型"),
		DATA_FORMAT_TIMESTAMP("" + HSSFDataFormat.getBuiltinFormat("yyyy/MM/dd HH:mm:ss"), "timestamp日期类型")
		;
		
		private String code; // 枚举代码
		private String description; // 枚举标签
		
		private CellDataFormatEnum(String code, String description) {
			this.code = code;
			this.description = description;
		}
		
		public String getEnumCode() {
			return code;
		}
		
		public String getEnumLabel() {
			return description;
		}

		public Short getShortEnumCode() {
			return Short.parseShort(code);
		}
		
		public static CellDataFormatEnum getEnumType(String enumCode) {
			CellDataFormatEnum enumType = null;
			EnumSet<CellDataFormatEnum> enumSet = EnumSet.allOf(CellDataFormatEnum.class);
			for (CellDataFormatEnum enumItem : enumSet) {
				if(enumItem.getEnumCode().equals(enumCode)) {
					enumType = enumItem;
					break;
				}
			}
			return enumType;
		}
	}
	
	private static boolean isDouble(String str) {
		try {
			new Double(str);
		} catch (Exception e) {
			return false;
		}
		return true;
	}
	
}

DBDataUtil.java

package com.lw.util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class DBDataUtil {

	private static String url = "jdbc:mysql://172.0.0.1:3306/dbName?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull";
	private static String username = "root";
	private static String password = "root";
	private static String driverClassName = "com.mysql.jdbc.Driver";

	/**
	 * 查询表的字段,封装成List
	 * 
	 * @param tableName
	 *            表名
	 * @param schemaName
	 *            数据库名
	 * @return
	 * @throws SQLException
	 */
	public static List<ColumnData> getMySqlColumnDatas(String tableName, String schemaName) throws SQLException {
		String SQLColumns = " select COLUMN_NAME,DATA_TYPE,column_comment,numeric_scale,numeric_precision,character_maximum_length,ordinal_position from information_schema.COLUMNS where table_name =  '"
				+ tableName + "'" + " and TABLE_SCHEMA='" + schemaName + "' " + " ORDER by  ordinal_position";
		Connection con = getConnection();
		PreparedStatement ps = con.prepareStatement(SQLColumns);
		List<ColumnData> columnList = new ArrayList<ColumnData>();
		ResultSet rs = ps.executeQuery();
		while (rs.next()) {
			String name = rs.getString(1);
			String lowName = getColumnBeanName(name); // 将XXX_XXX转换成xxxXxx的格式
			String type = rs.getString(2).toUpperCase(); // mysql 区分大小写
			String javaType = getType(rs.getString(2), rs.getString(4), rs.getString(5)); // mysql
																							// 区分大小写
			String comment = rs.getString(3);
			String dataScale = rs.getString(4);
			String dataPrecision = rs.getString(5);
			String dataMaxLength = rs.getString(6);

			ColumnData cd = new ColumnData(name, lowName, type, javaType, comment, dataScale, dataPrecision,
					dataMaxLength);
			columnList.add(cd);
		}
		rs.close();
		ps.close();
		con.close();
		return columnList;
	}

	public static Connection getConnection() throws SQLException {
		try {
			Class.forName(driverClassName);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return DriverManager.getConnection(url, username, password);
	}

	private static String getColumnBeanName(String column) {
		String[] split = column.split("_");
		StringBuffer columnVal = new StringBuffer();
		if (split.length > 1) {
			for (int i = 0; i < split.length; i++) {
				String colVal = "";
				if (i == 0) {
					colVal = split[i].toLowerCase();
					columnVal.append(colVal);
				} else {
					colVal = split[i].substring(0, 1).toUpperCase()
							+ split[i].substring(1, split[i].length()).toLowerCase();
					columnVal.append(colVal);
				}
			}
			columnVal.toString();
		} else {
			String colVal = column.toLowerCase();
			columnVal.append(colVal);
		}
		return columnVal.toString();
	}

	/***
	 * 获取java类型
	 * 
	 * @param type
	 *            数据库数据类型
	 * @param dataScale
	 *            小数位数
	 * @param dataPrecision
	 *            数据精度
	 * @return
	 */
	private static String getType(String type, String dataScale, String dataPrecision) {
		type = type.toLowerCase();
		if ("char".equalsIgnoreCase(type) || "varchar".equalsIgnoreCase(type) || "varchar2".equalsIgnoreCase(type)) {
			return "java.lang.String";
		} else if ("NUMBER".equalsIgnoreCase(type) || "numeric".equalsIgnoreCase(type)) {//
			if ((dataScale != null && !dataScale.equals("") && !dataScale.equals("0"))) {
				if (dataPrecision != null && dataPrecision.equals("38")) {
					return "java.math.BigDecimal";
				} else {
					return "java.lang.Double";
				}
			} else {
				if (dataPrecision != null && dataPrecision.equals("38")) {
					return "java.math.BigDecimal";
				} else {
					return "java.lang.Long";
				}
			}
		} else if ("decimal".equalsIgnoreCase(type)) {
			return "java.math.BigDecimal";
		} else if ("DATE".equalsIgnoreCase(type)) {
			return "java.util.Date";
		} else if ("DATETIME".equalsIgnoreCase(type)) {
			return "java.util.Date";
		} else if ("BLOB".equalsIgnoreCase(type)) {
			return "java.sql.Blob";
		} else if ("CLOB".equalsIgnoreCase(type)) {
			return "java.sql.Clob";
		} else if ("int".equalsIgnoreCase(type)) {
			return "java.lang.Integer";
		} else if ("TINYINT".equalsIgnoreCase(type)) {
			return "java.lang.Boolean";
		} else if ("double".equalsIgnoreCase(type)) {
			return "java.math.BigDecimal";
		} else if ("datetime".equalsIgnoreCase(type)) {
			return "java.util.Date";
		}
		return null;
	}
}

ColumnData.java

package com.lw.util;

/**
 * 表字段类
 * @author david
 */
public class ColumnData {

	private String columnName;
	private String dataType;
	private String comments;
	private String columnLowName;
	private String dataScale;
	private String dataPrecision;
	private String javaType; // java数据类型
	private String dataMaxLength; // 最大长度
	
	public ColumnData() {}
	
	public ColumnData(String columnName, 
			String columnLowName, 
			String dataType, 
			String javaType, 
			String comments, 
			String dataScale, 
			String dataPrecision, 
			String dataMaxLength) {
		this.columnName = columnName;
		this.columnLowName = columnLowName;
		this.dataType = dataType;
		this.javaType = javaType;
		this.comments = comments;
		this.dataScale = dataScale;
		this.dataPrecision = dataPrecision;
		this.dataMaxLength = dataMaxLength;
	}
	
	public String getColumnName() {
		return columnName;
	}
	public void setColumnName(String columnName) {
		this.columnName = columnName;
	}
	public String getDataType() {
		return dataType;
	}
	public void setDataType(String dataType) {
		this.dataType = dataType;
	}
	public String getComments() {
		return comments;
	}
	public void setComments(String comments) {
		this.comments = comments;
	}
	public String getColumnLowName() {
		return columnLowName;
	}
	public void setColumnLowName(String columnLowName) {
		this.columnLowName = columnLowName;
	}
	public String getDataScale() {
		return dataScale;
	}
	public void setDataScale(String dataScale) {
		this.dataScale = dataScale;
	}
	public String getDataPrecision() {
		return dataPrecision;
	}
	public void setDataPrecision(String dataPrecision) {
		this.dataPrecision = dataPrecision;
	}
	public String getJavaType() {
		return javaType;
	}
	public void setJavaType(String javaType) {
		this.javaType = javaType;
	}
	public String getDataMaxLength() {
		return dataMaxLength;
	}
	public void setDataMaxLength(String dataMaxLength) {
		this.dataMaxLength = dataMaxLength;
	}
}


猜你喜欢

转载自blog.csdn.net/davidhhs/article/details/80973067