Excel导入导出工具类

目录

1.mavn jar

2 工具类代码

2.1 ExcelUtil

2.2 引用自写类

2.2.1 ExcelMsg

2.2.2 CellDataType

2.2.3 SaxReadExcelUtil


1.mavn jar

<!-- excel poi jar -->
    <dependency>
      <groupId>org.apache.poi</groupId>
      <artifactId>poi</artifactId>
      <version>3.9</version>
    </dependency>
    
    <!-- excel poi(编目-excel导入解析使用-fengwei添加) -->
    <dependency>
      <groupId>org.apache.poi</groupId>
      <artifactId>poi-ooxml</artifactId>
      <version>3.9</version>
    </dependency>
    <!-- excel 解析大数据 -->
    <dependency>
      <groupId>xerces</groupId>
      <artifactId>xercesImpl</artifactId>
      <version>2.11.0</version>
    </dependency>

2 工具类代码

2.1 ExcelUtil

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;
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.hssf.util.CellRangeAddress;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.Cell;
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.usermodel.WorkbookFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.tengfan.system.utils.ConfigUtil;

/**
 * @Title ExcelUtil.java
 * @Description excel 导入导出
 */
public class ExcelUtil {
	public static String FILE_SAVE_ROOT_PATH = "D:";// 默认根目录导出到E盘
	public static int createRowIndex = 0;// excel创建行下标,用于控制从哪行开始填写数据
	public static int SheetMaxRows = 50000;// excel每一个sheet最大存储行数(excel sheet有最大行数问题)
	private static Logger logger = LoggerFactory.getLogger(ExcelUtil.class);

	static {
		// 初始化根目录:改为读取配置
		try {
			//config.properties文件中配置的文件物理存储目录(local_path=E:/res)
			FILE_SAVE_ROOT_PATH = ConfigUtil.get("local_path"); 
			if (StringUtils.isNotBlank(FILE_SAVE_ROOT_PATH) && FILE_SAVE_ROOT_PATH.contains("/res")) {
				FILE_SAVE_ROOT_PATH = FILE_SAVE_ROOT_PATH.replaceAll("/res", "");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 
	 * @Title exportExcel
	 * @Description
	 * @param datalist 写入的数据列表 [{"title":"test","img":"img"}...]
	 * @param headList excel表头列表[{"name":"title(对应数据列表中key)","label":"标题","datatype": "数据类型(number,date,money,string)"]...}
	 * @param excelName
	 * @param savePath 存入的相对目录 例如:/res/excel
	 * @return
	 * @version
	 */
	public static ExcelMsg exportExcel(List<Map<String, Object>> datalist, List<Map<String, Object>> headList, String excelName, String savePath) {
		ExcelMsg msg = new ExcelMsg();
		FileOutputStream fout = null;
		try {
			// 校验excel数据
			msg = validateExcel(datalist, headList);
			if (!msg.isSuccess()) {
				return msg;
			}
			// 第一步,创建一个webbook,对应一个Excel文件
			HSSFWorkbook wb = new HSSFWorkbook();
			// 第二步,在webbook中添加sheet,datalist.size()>SheetMaxRows,需要进行分割在不同的sheet中
			int sheetNum = (int) Math.ceil(datalist.size() / Double.valueOf(SheetMaxRows));// sheet个数
			for (int i = 1; i <= sheetNum; i++) {
				HSSFSheet sheet=null;
				if(sheetNum>1){
					 sheet = wb.createSheet(getExcelName("sheet", excelName, i + ""));
				}else{
					sheet = wb.createSheet(getExcelName("sheet", excelName, null));
				}
				// 第三步,创建标题
				createExcelTitle(headList, sheet, wb, excelName);
				// 第四步,创建表头
				createExcelHead(headList, sheet, wb);
				// 第五步,创建表数据
				int formIndex = (i - 1) * SheetMaxRows;
				int toIndex = i * SheetMaxRows >= datalist.size() ? datalist.size() : i * SheetMaxRows;
				List<Map<String, Object>> sheetDataList = datalist.subList(formIndex, toIndex);
				createExcelData(sheetDataList, headList, sheet, wb);
				// excel创建行下标清零
				createRowIndex = 0;
			}
			// 第六步,判断存放excel文件的文件夹是否存在,不存在则创建
			File directory = new File(FILE_SAVE_ROOT_PATH + savePath);
			if (!directory.exists()) {
				directory.mkdirs();
			}
			// 第七步,写入本地
			String excelPath = savePath + "/" + getExcelName("file", excelName, null);
			String filePath = FILE_SAVE_ROOT_PATH + excelPath;
			fout = new FileOutputStream(filePath);
			wb.write(fout);
			fout.close();
			msg.setSuccess(true);
			msg.setObj(excelPath);
			msg.setMsg("Excel数据导出成功");
			return msg;
		} catch (Exception e) {
			e.printStackTrace();
			msg.setMsg("Excel数据导出失败");
			return msg;
		} finally {
			// 关闭流
			if (fout != null) {
				try {
					fout.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * 
	 * @Title getDefaultName
	 * @Description 获取excel默认名称
	 * @param type 类型 sheet-返回excel Sheet名称 file-返回excel文件名称 title-返回标题
	 * @param excelName excel名称
	 * @param suffixName 后缀名称
	 * @version
	 */
	private static String getExcelName(String type, String excelName, String suffixName) {
		String result = excelName;
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
		if (excelName != null && excelName != "") {
			if (type.trim().equalsIgnoreCase("sheet")) {
				result = excelName;
			} else if (type.trim().equalsIgnoreCase("file")) {
				result = excelName + ".xls";
			} else if (type.trim().equalsIgnoreCase("title")) {
				result = excelName;
			}
		} else {
			if (type.trim().equalsIgnoreCase("sheet")) {
				result = sdf.format(new Date());
			} else if (type.trim().equalsIgnoreCase("file")) {
				result = sdf.format(new Date()) + ".xls";
			} else if (type.trim().equalsIgnoreCase("title")) {
				sdf = new SimpleDateFormat("yyyy年MM月dd日");
				result = sdf.format(new Date()) + "Excel导出数据";
			}
		}
		if (suffixName != null && !suffixName.trim().equals("")) {
			result += suffixName;
		}
		return result;
	}

	/**
	 * 
	 * @Title validateExcel
	 * @Description 校验excel
	 * @param datalist 数据list
	 * @param headList 表头list
	 * @return
	 * @version
	 */
	private static ExcelMsg validateExcel(List<Map<String, Object>> datalist, List<Map<String, Object>> headList) {
		ExcelMsg msg = new ExcelMsg();
		if (datalist == null || datalist.size() == 0) {
			msg.setMsg("写入excel数据为空");
			return msg;
		}
		if (headList == null || headList.size() == 0) {
			msg.setMsg("写入excel表头数据为空");
			return msg;
		}
		msg.setSuccess(true);
		return msg;
	}

	/**
	 * 
	 * @Title createExcelTitle
	 * @Description 创建excel内容标题
	 * @param headList
	 * @param sheet
	 * @param wb
	 * @param excelName
	 * @version
	 */
	private static void createExcelTitle(List<Map<String, Object>> headList, HSSFSheet sheet, HSSFWorkbook wb, String excelName) {
		// 在索引0的位置创建行(最顶端的行)
		HSSFRow row = sheet.createRow(createRowIndex);
		row.setHeightInPoints(48);// 设置行高单位像素,excel 默认行高为13.5 像素值为: (13.5/72)*96=18
		// 设置单元格格式
		HSSFCellStyle cellStyle = setCellStyleByType("title", wb);
		HSSFCell cell = null;
		for (int i = 0; i < headList.size(); i++) {
			cell = row.createCell(i);
			cell.setCellStyle(cellStyle);
			if (i <= 0) {
				cell.setCellValue(getExcelName("title", excelName, null));
			} else {
				cell.setCellValue("");
			}

		}
		// 合并第一行,设定合并单元格区域范围 firstRow 0-based lastRow 0-based firstCol 0-based
		// lastCol
		CellRangeAddress region = new CellRangeAddress(0, 0, 0, headList.size() - 1);
		sheet.addMergedRegion(region);
		createRowIndex++;
	}

	/**
	 * 
	 * @Title createExcelHead
	 * @Description 创建excel表头
	 * @param headList excel表头列表 [{"name":"title","label":"标题","datatype":"数据类型
	 * @param sheet
	 * @param wb
	 * @version
	 */
	private static void createExcelHead(List<Map<String, Object>> headList, HSSFSheet sheet, HSSFWorkbook wb) {

		// 在sheet中添加表头第1行,注意老版本poi对Excel的行数列数有限制short
		HSSFRow row = sheet.createRow(createRowIndex);
		row.setHeightInPoints(20);// 设置行高单位像素,excel 默认行高为13.5 像素值为:(13.5/72)*96=18
		// 设置单元格格式
		HSSFCellStyle cellStyle = setCellStyleByType("head", wb);
		// 创建表头单元格
		HSSFCell cell = null;
		Map<String, Object> tempMap = null;
		for (int i = 0; i < headList.size(); i++) {
			tempMap = headList.get(i);
			cell = row.createCell(i);
			cell.setCellStyle(cellStyle);
			cell.setCellValue(tempMap.get("label") + "");
			// 设置列宽,api 段信息 Set the width (in units of 1/256th of a character
			// width)
			sheet.setColumnWidth(i, 25 * 256);
		}
		createRowIndex++;
	}

	/**
	 * 
	 * @Title setCellStyleByType
	 * @Description 设置单元格格式
	 * @param type
	 * @param wb
	 * @return
	 * @version
	 */
	private static HSSFCellStyle setCellStyleByType(String type, HSSFWorkbook wb) {
		// 创建单元格样式
		HSSFCellStyle cellStyle = wb.createCellStyle();
		// 设置字体
		HSSFFont font = wb.createFont();
		font.setFontName("宋体");
		if (type.equals("title")) {
			font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
			font.setFontHeightInPoints((short) 18);
			cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
		} else if (type.equals("head")) {
			font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
			font.setFontHeightInPoints((short) 12);
			cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
		} else {
			font.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);
			font.setFontHeightInPoints((short) 12);
			cellStyle.setAlignment(HSSFCellStyle.ALIGN_LEFT); // 创建一个居左格式
		}
		cellStyle.setFont(font);
		cellStyle.setBottomBorderColor(HSSFColor.BLACK.index); // 设置单元格的边框颜色.
		cellStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN); // 下边框
		cellStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);// 左边框
		cellStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);// 上边框
		cellStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);// 右边框
		cellStyle.setWrapText(true);// 设置自动换行
		return cellStyle;
	}

	/**
	 * 
	 * @Title createExcelData
	 * @Description 创建excel列表数据
	 * @param datalist 写入的数据列表 [{"title":"test","img":"img"}...]
	 * @param headList excel表头列表 [{"name":"title","label":"标题","datatype":"数据类型"}]
	 * @param sheet 对应Excel文件中的sheet
	 * @param wb 对应一个Excel文件
	 * @version
	 */
	private static void createExcelData(List<Map<String, Object>> datalist, List<Map<String, Object>> headList, HSSFSheet sheet, HSSFWorkbook wb) {
		Map<String, Object> tempMap = null;
		HSSFRow row = null;
		// 设置单元格格式
		HSSFCellStyle cellStyle = setCellStyleByType("data", wb);
		// 设置数据格式
		HSSFDataFormat format = wb.createDataFormat();
		for (int i = 0; i < datalist.size(); i++) {
			tempMap = datalist.get(i);
			row = sheet.createRow(i + createRowIndex);
			row.setHeightInPoints(20);// 设置行高单位像素,excel 默认行高为13.5 像素值为:
										// (13.5/72)*96=18
			createExcelRowData(tempMap, headList, row, cellStyle, format);
		}
	}

	/**
	 * 
	 * @Title createExcelRowData
	 * @Description 创建excel某行数据
	 * @param rowData {"title":"test","img":"img",...}
	 * @param headList excel表头列表 [{"name":"title","label":"标题","datatype":"数据类型
	 * @param row
	 * @param cellStyle
	 * @param format
	 * @version
	 */
	private static void createExcelRowData(Map<String, Object> rowData, List<Map<String, Object>> headList, HSSFRow row, HSSFCellStyle cellStyle, HSSFDataFormat format) {
		HSSFCell cell = null;
		Map<String, Object> tempMap = null;
		Object datatype = null;
		Object cellData = null;
		for (int i = 0; i < headList.size(); i++) {
			cell = row.createCell(i);
			tempMap = headList.get(i);
			cellData = rowData.get(tempMap.get("name"));
			datatype = tempMap.get("datatype");
			setCellDataType(cell, datatype, cellData, cellStyle, format);
		}

	}

	/**
	 * 
	 * @Title setCellDataType
	 * @Description 设置单元格格式并赋值
	 * @param cell 单元格对象
	 * @param datatype 可以为number,date,money,string 单元格数据类型
	 * @param cellData 单元格数据
	 * @param cellStyle
	 * @param format
	 * @version
	 */
	private static void setCellDataType(HSSFCell cell, Object datatype, Object cellData, HSSFCellStyle cellStyle, HSSFDataFormat format) {
		try {
			// 没有数据值默认为“”
			if (cellData == null) {
				cell.setCellStyle(cellStyle);
				cell.setCellValue("");
				return;
			}

			// 没有指定数据类型,默认为字符型
			if (datatype == null) {
				cell.setCellStyle(cellStyle);
				cell.setCellValue(cellData.toString());
				return;
			}

			if (datatype.toString().trim().equalsIgnoreCase("number")) {
				// 数字类型
				// 判断data是否为数值型
				boolean isNum = cellData.toString().matches("^(-?\\d+)(\\.\\d+)?$");
				// 判断data是否为整数(小数部分是否为0)
				boolean isInteger = cellData.toString().matches("^[-\\+]?[\\d]*$");
				// 判断data是否为百分数(是否包含“%”)
				boolean isPercent = cellData.toString().contains("%");

				// 如果单元格内容是数值类型,涉及到金钱(金额、本、利),则设置cell的类型为数值型,设置data的类型为数值类型
				if (isNum && !isPercent) {
					if (isInteger) {
						cellStyle.setDataFormat(format.getBuiltinFormat("#,#0"));// 数据格式只显示整数
					} else {
						cellStyle.setDataFormat(format.getBuiltinFormat("#,##0.00"));// 保留两位小数点
					}
					// 设置单元格格式
					cell.setCellStyle(cellStyle);
					// 设置单元格内容为double类型
					cell.setCellValue(Double.parseDouble(cellData.toString()));
				}
			} else if (datatype.toString().trim().equalsIgnoreCase("date")) {
				// 日期类型
				cellStyle.setDataFormat(format.getFormat("yyyy-MM-dd HH:mm:ss"));
				cell.setCellStyle(cellStyle);
				SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
				Date date = sdf.parse(cellData.toString());
				cell.setCellValue(date);
			} else if (datatype.toString().trim().equalsIgnoreCase("money")) {
				// 货币
				cellStyle.setDataFormat(format.getFormat("¥#,##0"));
				cell.setCellStyle(cellStyle);
				cell.setCellValue(Double.parseDouble(cellData.toString()));
			} else {
				cell.setCellStyle(cellStyle);
				cell.setCellValue(cellData.toString());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	/**
	 * 读取Excel返回的是map对象,其中key是一行,两行,行数,value是map,key是列, value是这行,这列对应的值, 包含第0行
	 * 
	 * @Title: readExcel @param in 输入流 @throws ExcelParseException
	 *         excel文件为空 @return Map<Integer,Map<Integer,String>>
	 *         返回的值只能采用Iterator 来进行循环,因为中间有可能会出现空行数据 @throws
	 */
	public static Map<Integer, Map<Integer, String>> readExcelInclude0Row(InputStream in) throws Exception {
		return readExcel(in, true);
	}

	/**
	 * 读取Excel返回的是map对象,其中key是一行,两行,行数,value是map,key是列, value是这行,这列对应的值, 不包含第0行
	 * 
	 * @Title: readExcel @param in 输入流 @throws ExcelParseException
	 *         excel文件为空 @return Map<Integer,Map<Integer,String>>
	 *         返回的值只能采用Iterator 来进行循环,因为中间有可能会出现空行数据 @throws
	 */
	public static Map<Integer, Map<Integer, String>> readExcelNotInclude0Row(InputStream in) throws Exception {
		return readExcel(in, false);
	}

	/**
	 * 读取Excel返回的是map对象,其中key是一行,两行,行数,value是map,key是列,
	 * 
	 * @Title readExcelInclude0RowByBigData (文件后缀为.xlsx)
	 * @Description
	 * @param in 输入流
	 * @param startRow 数据获取起始行(下标从1开始)
	 * @param fillBlankColSize 需要填空列数
	 * @return Map<Integer,Map<Integer,String>>
	 * @throws Exception
	 * @version
	 */
	public static Map<Integer, Map<Integer, String>> readExcelInclude0RowByBigData(InputStream in, int startRow, int fillBlankColSize) throws Exception {
		SaxReadExcelUtil read = new SaxReadExcelUtil();
		return read.readExcel(in, startRow, fillBlankColSize);
	}

	private static Map<Integer, Map<Integer, String>> readExcel(InputStream in, boolean isInclude0Column) throws Exception {
		Map<Integer, Map<Integer, String>> retValue = new HashMap<Integer, Map<Integer, String>>();
		Workbook wb = getWorkbookByInputStream(in);
		// 得到工作表格数量
		int sheetNum = wb.getNumberOfSheets();
		int loopHead = 0;
		if (!isInclude0Column) {
			loopHead = 1;
		}
		boolean isBlankExcel = true;
		int currentNum = 0;
		for (int i = 0; i < sheetNum; i++) {
			Sheet childSheet = wb.getSheetAt(i);
			// 得到工作表格中的行数
			int rowNum = childSheet.getLastRowNum();
			// 从第一行开始,第0行为表头,默认不读取
			// 循环行
			for (int j = loopHead; j <= rowNum; j++) {
				final Map<Integer, String> columnContents = new HashMap<Integer, String>();
				final Row row = childSheet.getRow(j);
				// final int currentNum = j + 1;
				if (row == null) {
					// retValue.put(currentNum, columnContents);
					continue;
				}
				// 得到列数
				int cellNum = row.getLastCellNum();
				// 标识非空行但是有一定格式的空白行
				boolean isBlankRow = true;
				for (int k = 0; k < cellNum; k++) {
					Cell cell = row.getCell(k);
					if (cell != null && cell.getCellType() != Cell.CELL_TYPE_BLANK) {
						isBlankRow = false;
						break;
					}
				}
				// 非空白行则循环列处理
				if (!isBlankRow) {
					for (int k = 0; k < cellNum; k++) {
						String cellValue = "";
						Cell cell = row.getCell(k);
						if (cell != null) {
							switch (cell.getCellType()) {
							case HSSFCell.CELL_TYPE_NUMERIC:
								if (HSSFDateUtil.isCellDateFormatted(cell)) {
									cellValue = new SimpleDateFormat("yyyy-MM-dd").format(HSSFDateUtil.getJavaDate(cell.getNumericCellValue()));
								} else {
									// 考虑到本系统中的导入的浮点数以金额居多,因此仅保留两位小数,整数取整(避免“.0”)
									DecimalFormat decimalFormat = new DecimalFormat("#.##");
									cellValue = decimalFormat.format(cell.getNumericCellValue());
								}
								break;
							case HSSFCell.CELL_TYPE_STRING:
								cellValue = cell.getStringCellValue();
								break;
							default:
								cell.setCellType(HSSFCell.CELL_TYPE_STRING);
								cellValue = cell.getStringCellValue();
								break;
							}
							if (!cellValue.equals("") && cellValue != null) {
								isBlankExcel = false;
							}
						}
						columnContents.put(k, cellValue);
					}
					retValue.put(currentNum, columnContents);
					currentNum++;
				}
			}
			loopHead = 0;
			if (!isInclude0Column)
				loopHead = 1;
		}
		if (isBlankExcel)
			throw new Exception("excel文件为空");
		return retValue;
	}

	private static Workbook getWorkbookByInputStream(InputStream in) throws Exception {
		Workbook wb = null;
		try {
			wb = create(in);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			throw new Exception(e);
		}
		return wb;
	}

	public static Workbook create(InputStream in) throws Exception {
		Workbook ret = null;
		try {
			ret = WorkbookFactory.create(in);
		} catch (IllegalArgumentException e) {
			throw new Exception("Excel文件无法解析或版本过高!", e);
		}catch (IllegalStateException e) {
			String pattern = "The hyperlink for cell .* references relation .*, but that didn't exist!";
			if(Pattern.matches(pattern, e.getMessage())){
				String value1 = StringUtils.substringBetween(e.getMessage(), "The hyperlink for cell ", "references relation");
				String value2 = StringUtils.substringBetween(e.getMessage(), "references relation ", ", but that didn't exist!");

				throw new Exception("单元格"+value1+"的超链接引用了关系"+value2+",但它不存在!",e);
			}else{
				throw new Exception(e);
			}
		}
		return ret;
	}

	/**
	 * 
	 * @Title main
	 * @Description 测试
	 * @param args
	 * @version
	 */
	public static void main(String[] args) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		List<Map<String, Object>> headList = new ArrayList<Map<String, Object>>();
		Map<String, Object> headMap = new HashMap<String, Object>();
		headMap.put("name", "title");
		headMap.put("label", "标题");
		headMap.put("datatype", "string");
		headList.add(headMap);
		Map<String, Object> headMap1 = new HashMap<String, Object>();
		headMap1.put("name", "author");
		headMap1.put("label", "作者");
		headMap1.put("datatype", "string");
		headList.add(headMap1);
		Map<String, Object> headMap2 = new HashMap<String, Object>();
		headMap2.put("name", "createDate");
		headMap2.put("label", "创建日期");
		headMap2.put("datatype", "date");
		headList.add(headMap2);
		Map<String, Object> headMap3 = new HashMap<String, Object>();
		headMap3.put("name", "count");
		headMap3.put("label", "计数");
		headMap3.put("datatype", "number");
		headList.add(headMap3);

		List<Map<String, Object>> dataList = new ArrayList<Map<String, Object>>();
		Map<String, Object> dataMap = new HashMap<String, Object>();
		dataMap.put("title", "aa");
		dataMap.put("author", "一山");
		dataMap.put("createDate", sdf.format(new Date()));
		dataMap.put("count", 1);
		dataList.add(dataMap);

		Map<String, Object> dataMap1 = new HashMap<String, Object>();
		dataMap1.put("title", "好啊好啊");
		dataMap1.put("createDate", sdf.format(new Date()));
		dataMap1.put("count", 10);
		dataList.add(dataMap1);

		ExcelMsg msg = exportExcel(dataList, headList, "测试", "/res/excel");
		System.out.println(msg.getMsg());
	
	}

}

2.2 引用自写类

2.2.1 ExcelMsg

import java.io.Serializable;

/**
 * @Title ExcelMsg.java
 * @Description excel msg
 */
public class ExcelMsg implements Serializable {

	private static final long serialVersionUID = 1L;
	private String msg = "";
	private boolean success = false;
	private Object obj;// 存返回的对象

	public String getMsg() {
		return msg;
	}

	public void setMsg(String msg) {
		this.msg = msg;
	}

	public boolean isSuccess() {
		return success;
	}

	public void setSuccess(boolean success) {
		this.success = success;
	}

	public Object getObj() {
		return obj;
	}

	public void setObj(Object obj) {
		this.obj = obj;
	}

}

2.2.2 CellDataType

/**
 * 单元格数据类型
 * @Title CellDataType.java
 * @Description  单元格数据类型
 */
public enum CellDataType {
	BOOL, ERROR, FORMULA, INLINESTR, SSTINDEX, NUMBER, DATE, NULL
}

2.2.3 SaxReadExcelUtil

import java.io.InputStream;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.ss.usermodel.BuiltinFormats;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.apache.poi.xssf.model.StylesTable;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;

/**
 * sax excel解析大数据量
 * 
 * @Title SaxReadExcelUtil.java
 * @Description sax excel解析大数据量
 */
public class SaxReadExcelUtil {
	/** excel数据 */
	private static Map<Integer, Map<Integer, String>> dataMap;
	/** 行数据 */
	private static Map<Integer, String> rowMap;
	private static StylesTable stylesTable;
	/** 起始行 */
	private int startRow;
	/** 需要填空列数 */
	private int fillBlankColSize = -1;
	/** 当前行 */
	private int currentRow = 0;
	/** 导入excel列数 */
	private int colSize = 0;

	/**
	 * 读取excel
	 * 
	 * @Title readExcel
	 * @Description
	 * @param filename 文件名 eg:E:/yade/xx123.xlsx
	 * @param startRow 起始行
	 * @param fillBlankColSize 需要填空列数
	 * @return Map<Integer, Map<Integer, String>>
	 * @throws Exception
	 * @version
	 */
	public Map<Integer, Map<Integer, String>> readExcel(String filename, int startRow, int fillBlankColSize) throws Exception {
		dataMap = new HashMap<Integer, Map<Integer, String>>();
		if (StringUtils.isBlank(filename)) {
			throw new Exception("文件名为空");
		}
		this.startRow = startRow;
		this.fillBlankColSize = fillBlankColSize;
		processAllSheets(filename);
		fillBlankCell();// 填补空单元格
		return dataMap;
	}

	/**
	 * 读取excel
	 * 
	 * @Title readExcel
	 * @Description
	 * @param in 输入流对象
	 * @param startRow 起始行
	 * @param fillBlankColSize 需要填空列数
	 * @return Map<Integer, Map<Integer, String>>
	 * @throws Exception
	 * @version
	 */
	public Map<Integer, Map<Integer, String>> readExcel(InputStream in, int startRow, int fillBlankColSize) throws Exception {
		dataMap = new HashMap<Integer, Map<Integer, String>>();
		if (in == null) {
			throw new Exception("文件为空");
		}
		this.startRow = startRow;
		this.fillBlankColSize = fillBlankColSize;
		processAllSheets(in);
		fillBlankCell();// 填补空单元格
		return dataMap;
	}

	/**
	 * 获取所有的sheet
	 * 
	 * @Title processAllSheets
	 * @Description 获取所有的sheet
	 * @param fileName 文件名 eg:E:/yade/xx123.xlsx
	 * @throws Exception
	 * @version
	 */
	private void processAllSheets(String fileName) throws Exception {
		OPCPackage pkg = OPCPackage.open(fileName);
		XSSFReader r = new XSSFReader(pkg);
		stylesTable = r.getStylesTable();
		SharedStringsTable sst = r.getSharedStringsTable();
		XMLReader parser = fetchSheetParser(sst);
		Iterator<InputStream> it = r.getSheetsData();
		while (it.hasNext()) {
			rowMap = null;
			InputStream sheet1 = it.next();
			InputSource sheetSource = new InputSource(sheet1);
			parser.parse(sheetSource);
			sheet1.close();
		}
	}

	/**
	 * 获取所有的sheet
	 * 
	 * @Title processAllSheets
	 * @Description 获取所有的sheet
	 * @throws Exception
	 * @version
	 */
	private void processAllSheets(InputStream in) throws Exception {
		OPCPackage pkg = OPCPackage.open(in);
		XSSFReader r = new XSSFReader(pkg);
		stylesTable = r.getStylesTable();
		SharedStringsTable sst = r.getSharedStringsTable();
		XMLReader parser = fetchSheetParser(sst);
		Iterator<InputStream> it = r.getSheetsData();
		while (it.hasNext()) {
			rowMap = null;
			InputStream sheet1 = it.next();
			InputSource sheetSource = new InputSource(sheet1);
			parser.parse(sheetSource);
			sheet1.close();
		}
	}

	/**
	 * 加载sax 解析器
	 * 
	 * @Title fetchSheetParser
	 * @Description 加载sax 解析器
	 * @param sst
	 * @return
	 * @throws SAXException
	 * @version
	 */
	private XMLReader fetchSheetParser(SharedStringsTable sst) throws SAXException {
		XMLReader parser = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");
		ContentHandler handler = new SheetHandler(sst);
		parser.setContentHandler(handler);
		return parser;
	}

	/**
	 * 列号转数字 AB7-->28 第28列
	 * 
	 * @Title covertRowIdtoInt
	 * @Description 列号转数字 AB7-->28 第28列
	 * @param rowId 行id
	 * @return
	 * @version
	 */
	public static int covertRowIdtoInt(String rowId) {
		int firstDigit = -1;
		for (int c = 0; c < rowId.length(); ++c) {
			if (Character.isDigit(rowId.charAt(c))) {
				firstDigit = c;
				break;
			}
		}
		// AB7-->AB
		// AB是列号, 7是行号
		String newRowId = rowId.substring(0, firstDigit);
		int num = 0;
		int result = 0;
		int length = newRowId.length();
		for (int i = 0; i < length; i++) {
			// 先取最低位,B
			char ch = newRowId.charAt(length - i - 1);
			// B表示的十进制2,ascii码相减,以A的ascii码为基准,A表示1,B表示2
			num = (int) (ch - 'A' + 1);
			// 列号转换相当于26进制数转10进制
			num *= Math.pow(26, i);
			result += num;
		}
		return result;

	}

	private boolean isAccess() {
		if (currentRow >= startRow) {
			return true;
		}
		return false;
	}

	/**
	 * 填补空单元格
	 * 
	 * @Title fillBlankCell
	 * @Description 填补空单元格
	 * @version
	 */
	private void fillBlankCell() {
		if (fillBlankColSize <= 0) {
			return;
		}
		int factFillBlankColSize = fillBlankColSize > colSize ? colSize : fillBlankColSize;// 实际需要填空的列数
		System.out.println(factFillBlankColSize);
		Iterator i = dataMap.entrySet().iterator();
		while (i.hasNext()) {
			Map.Entry e = (Map.Entry) i.next();
			Map<Integer, String> rowData = (Map<Integer, String>) e.getValue();
			for (int k = 0; k < factFillBlankColSize; k++) {
				boolean isExist = false;
				Iterator j = rowData.entrySet().iterator();
				while (j.hasNext()) {
					Map.Entry m = (Map.Entry) j.next();
					if (((Integer) m.getKey()) == k) {
						isExist = true;
						break;
					}
				}
				if (!isExist) {
					rowData.put(k, "");
				}
			}

		}
	}

	public static void main(String[] args) throws Exception {
		SaxReadExcelUtil reader = new SaxReadExcelUtil();
		Map<Integer, Map<Integer, String>> dataMap1 = reader.readExcel("C:/Users/Administrator/Desktop/test111.xlsx", 2,9);
		System.out.println(dataMap1);
		// System.out.println("===========");

		// File file = new File("C:/Users/Administrator/Desktop/test111.xlsx");
		// FileInputStream fileInputStream = new FileInputStream(file);
		// System.out.println(ExcelUtil.readExcelNotInclude0Row(fileInputStream));

		// System.out.println("===========");
		// SaxReadExcelUtil reader2 = new SaxReadExcelUtil();
		// Map<Integer, Map<Integer, String>> dataMap2 =
		// reader2.readExcel(fileInputStream, 2);
		// System.out.println(dataMap2);

	}

	/**
	 * sax解析handler See org.xml.sax.helpers.DefaultHandler javadocs
	 * http://tool.oschina.net/uploads/apidocs/jdk-zh/org/xml/sax/helpers/
	 * DefaultHandler.html
	 * 
	 * @Title SaxReadExcelUtil.java
	 * @Description
	 */
	private class SheetHandler extends DefaultHandler {
		private SharedStringsTable sst;
		private String lastContents;
		private boolean nextIsString;
		private int cellIndex = 0;

		private CellDataType nextDataType = CellDataType.SSTINDEX;
		private final DataFormatter formatter = new DataFormatter();
		private short formatIndex;
		private String formatString;

		private SheetHandler(SharedStringsTable sst) {
			this.sst = sst;
		}

		/**
		 * 开始元素 (获取key 值)
		 */
		@Override
		public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException {
			if (name.equals("dimension")) {
				String dimension = attributes.getValue("ref");
				colSize = covertRowIdtoInt(dimension.substring(dimension.indexOf(":") + 1));
				// TODO
				System.out.println(colSize);
			}
			// c => 单元格
			if (name.equals("c")) {
				// cell position
				String rowId = attributes.getValue("r");
				this.setNextDataType(attributes);
				// 判断是否是新的一行
				if (Pattern.compile("^A[0-9]+$").matcher(rowId).find()) {
					if (rowMap != null && !rowMap.isEmpty() && isAccess()) {
						int index = currentRow - startRow;
						dataMap.put(index, rowMap);
					}
					rowMap = new HashMap<Integer, String>();
					currentRow++;
					cellIndex = 0;
				}
				if (isAccess()) {
					// Figure out if the value is an index in the SST
					String cellType = attributes.getValue("t");
					if (cellType != null && cellType.equals("s")) {
						nextIsString = true;
					} else {
						nextIsString = false;
					}
				}
			}
			lastContents = "";
		}

		@Override
		public void characters(char[] ch, int start, int length) throws SAXException {
			if (isAccess()) {
				lastContents += new String(ch, start, length);
			}
		}

		/**
		 * 获取value
		 */
		@Override
		public void endElement(String uri, String localName, String name) throws SAXException {
			if (isAccess()) {
				if (name.equals("c")) {
					cellIndex++;
				}
				if (nextIsString) {
					int idx = Integer.parseInt(lastContents);
					lastContents = new XSSFRichTextString(sst.getEntryAt(idx)).toString();
					nextIsString = false;
				}
				// v => contents of a cell
				if (name.equals("v")) {
					String cellValue = this.getDataValue(lastContents.trim());
					rowMap.put(cellIndex, cellValue);
				}
			}

		}

		/**
		 * 根据element属性设置数据类型
		 * 
		 * @param attributes
		 */
		public void setNextDataType(Attributes attributes) {
			nextDataType = CellDataType.NUMBER;
			formatIndex = -1;
			formatString = null;
			String cellType = attributes.getValue("t");
			String cellStyleStr = attributes.getValue("s");
			if ("b".equals(cellType)) {
				nextDataType = CellDataType.BOOL;
			} else if ("e".equals(cellType)) {
				nextDataType = CellDataType.ERROR;
			} else if ("inlineStr".equals(cellType)) {
				nextDataType = CellDataType.INLINESTR;
			} else if ("s".equals(cellType)) {
				nextDataType = CellDataType.SSTINDEX;
			} else if ("str".equals(cellType)) {
				nextDataType = CellDataType.FORMULA;
			}
			if (cellStyleStr != null) {
				int styleIndex = Integer.parseInt(cellStyleStr);
				XSSFCellStyle style = stylesTable.getStyleAt(styleIndex);
				formatIndex = style.getDataFormat();
				formatString = style.getDataFormatString();
				if ("m/d/yy" == formatString) {
					nextDataType = CellDataType.DATE;
					// full format is "yyyy-MM-dd hh:mm:ss.SSS";
					formatString = "yyyy-MM-dd";
				}
				if (formatString == null) {
					nextDataType = CellDataType.NULL;
					formatString = BuiltinFormats.getBuiltinFormat(formatIndex);
				}
			}
		}

		/**
		 * 根据数据类型获取数据
		 * 
		 * @param value
		 * @param thisStr
		 * @return
		 */
		public String getDataValue(String value) {
			String thisStr = "";
			switch (nextDataType) {
			// 这几个的顺序不能随便交换,交换了很可能会导致数据错误
			case BOOL:
				char first = value.charAt(0);
				thisStr = first == '0' ? "FALSE" : "TRUE";
				break;
			case ERROR:
				thisStr = "\"ERROR:" + value.toString() + '"';
				break;
			case FORMULA:
				thisStr = '"' + value.toString() + '"';
				break;
			case INLINESTR:
				XSSFRichTextString rtsi = new XSSFRichTextString(value.toString());
				thisStr = rtsi.toString();
				rtsi = null;
				break;
			case SSTINDEX:
				thisStr = value.toString();
				break;
			case NUMBER:
				if (formatString != null) {
					thisStr = formatter.formatRawCellContents(Double.parseDouble(value), formatIndex, formatString).trim();
				} else {
					// 考虑到本系统中的导入的浮点数以金额居多,因此仅保留两位小数,整数取整(避免“.0”)
					DecimalFormat decimalFormat = new DecimalFormat("#.##");
					thisStr = decimalFormat.format(value);
				}
				thisStr = thisStr.replace("_", "").trim();
				break;
			case DATE:
				try {
					thisStr = formatter.formatRawCellContents(Double.parseDouble(value), formatIndex, formatString);
				} catch (NumberFormatException ex) {
					thisStr = value.toString();
				}
				thisStr = thisStr.replace(" ", "");
				break;
			default:
				thisStr = "";
				break;
			}
			return thisStr;
		}

	}

}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值