EXcel解析

maven依赖

 

	        <dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi</artifactId>
			<version>3.5-FINAL</version>
		</dependency>
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi-ooxml</artifactId>
			<version>3.5-FINAL</version>
		</dependency>

 

解析:

1 解析标题行

2 解析数据行

3 解析结果的抽象

4 解析过程需要考虑容错,容易理解

 

package com.enterprise.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
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;

/**
 * 解析Excel的工具类
 * 
 * @author chen.kuan 2015年11月16日
 * 
 */
public class POIParser {

	public static boolean isExcel(String fileName) {
		int dotIndex = fileName.lastIndexOf(".");
		if (dotIndex < 0) {
			return false;
		}
		String fileSuffix = fileName.substring(dotIndex);
		if (!".xls.xlsx.".contains(fileSuffix)) {
			return false;
		}
		return true;
	}

	private boolean ignoreHeadLine = false;

	public POIParser() {
		this(false);
	}

	/**
	 * @param ignoreHeadLine
	 *            是否忽略标题行
	 */
	public POIParser(boolean ignoreHeadLine) {
		this.ignoreHeadLine = ignoreHeadLine;
	}

	/**
	 * @param is
	 *            输入流,此输入流不管解析成功还是失败都会被释放
	 * @return
	 */
	public POIParseResult doParse(InputStream is) {
		try {
			POIParseResult result = new POIParseResult();

			Workbook workbook = null;
			try {
				workbook = WorkbookFactory.create(is);
			} catch (InvalidFormatException e) {
				result.setFormatError(e);
				return result;
			} catch (IOException e) {
				result.setException(e);
				return result;
			}

			Sheet sheet = workbook.getSheetAt(0);
			Row headRow = sheet.getRow(0);
			if (headRow == null) {
				result.setEmpty();
				return result;
			}

			short cellNumbers = headRow.getLastCellNum(); // LastCellNum可作为单元格的数量理解,不解析LastCellNum对应的单元格,lastCellNumber-1作为最后一列的索引
			if (!ignoreHeadLine) {
				// 处理表头
				String[] columnNames = new String[cellNumbers];
				for (int c = 0; c < cellNumbers; c++) {
					Cell cell = headRow.getCell(c);
					columnNames[c] = cell.getStringCellValue().trim();
				}
				result.setColumnNames(columnNames);
			}

			// 解析数据行
			List<String[]> rowDatas = new ArrayList<String[]>();
			// 确认数据行的startIndex
			int startIndex = -1;
			if (!ignoreHeadLine) {
				startIndex = 1;
			} else {
				startIndex = 0;
			}
			for (int r = startIndex; r <= sheet.getLastRowNum(); r++) { // getLastRowNum,getRow从0开始编号,
																		// 0表示第一行,getLastRowNum表示最后一行,最后一行需要被解析
				Row row = sheet.getRow(r);
				if (row == null) {
					continue;
				}
				String[] rowData = new String[cellNumbers];
				for (int c = 0; c < cellNumbers; c++) {
					Cell cell = row.getCell(c);
					if (cell == null) {
						rowData[c] = "";
					} else {
						rowData[c] = getStringCellValue(cell);
					}
				}
				rowDatas.add(rowData);
			}
			result.setRowDatas(rowDatas);

			result.setSuccess(); // set success
			return result;
		} finally {
			// close resource quietly
			try {
				is.close();
			} catch (IOException e) {
			}
		}
	}

	private String getStringCellValue(Cell cell) {
		String value = null;
		switch (cell.getCellType()) {
		case Cell.CELL_TYPE_NUMERIC: // 数字
			if (HSSFDateUtil.isCellDateFormatted(cell)) { // 日期
				value = new SimpleDateFormat("yyyy-MM-dd").format(cell.getDateCellValue());
			} else {
				DecimalFormat df = new DecimalFormat("0");
				value = df.format(cell.getNumericCellValue());
			}
			break;
		case Cell.CELL_TYPE_STRING: // 字符串
			value = cell.getStringCellValue();
			break;
		case Cell.CELL_TYPE_FORMULA: // 公式
			double numericValue = cell.getNumericCellValue();
			if (HSSFDateUtil.isValidExcelDate(numericValue)) { // 日期类型
				value = new SimpleDateFormat("yyyy-MM-dd").format(cell.getDateCellValue());
			} else {
				value = String.valueOf(numericValue);
			}
			break;
		case Cell.CELL_TYPE_BLANK: // 空白
			value = "";
			break;
		case Cell.CELL_TYPE_BOOLEAN: // Boolean
			value = String.valueOf(cell.getBooleanCellValue());
			break;
		case Cell.CELL_TYPE_ERROR: // Error,返回错误码
			value = String.valueOf(cell.getErrorCellValue());
			break;
		default:
			value = "";
			break;
		}
		return value;
	}

	// ---------------------------------------
	public static class POIParseResult {
		private boolean result = false; // 解析结果是否成功
		private boolean formatContainsError = false; // 格式是否错误
		private InvalidFormatException formatException;
		private Exception exception;
		private boolean isEmpty = false; // excel文件的内容是否为空
		private String[] columnNames;
		private List<String[]> rowDatas;

		public List<String[]> getRowDatas() {
			return rowDatas;
		}

		public void setRowDatas(List<String[]> rowDatas) {
			this.rowDatas = rowDatas;
		}

		public String[] getColumnNames() {
			return columnNames;
		}

		public void setColumnNames(String[] columnNames) {
			this.columnNames = columnNames;
		}

		public Exception getException() {
			return exception;
		}

		public void setException(Exception exception) {
			this.exception = exception;
		}

		public void setSuccess() {
			result = true;
		}

		public boolean isSuccess() {
			return result;
		}

		public void setFormatError(InvalidFormatException formatException) {
			formatContainsError = false;
			this.formatException = formatException;
		}

		public InvalidFormatException getFormatException() {
			return formatException;
		}

		public boolean containsFormatError() { // 判断是否excel发生了格式错误
			return formatContainsError;
		}

		public void setEmpty() {
			isEmpty = true;
		}

		public boolean isEmpty() {
			return isEmpty;
		}

	}

	// -----------------
	public static void main(String[] args) throws FileNotFoundException {
		String path = "C:\\Users\\WALKER\\Desktop\\O2O\\a.xlsx";
		File file = new File(path);
		if (!POIParser.isExcel(file.getName())) {
			System.err.println("Not excel,file=" + file.getAbsolutePath());
		} else {
			System.out.println("Starting parsing excel,file=" + file.getAbsolutePath());
		}

		InputStream is = new FileInputStream(file);

		POIParser parser = new POIParser();
		POIParseResult result = parser.doParse(is);

		if (result.isSuccess()) {
			String[] columnNames = result.getColumnNames();
			StringBuilder buffer = new StringBuilder();
			for (int i = 0; i < columnNames.length; i++) {
				buffer.append(columnNames[i]).append(" ");
			}
			System.out.println("Column names == " + buffer.toString());

			List<String[]> rowDatas = result.getRowDatas();
			for (int i = 0; i < rowDatas.size(); i++) {
				String[] rowData = rowDatas.get(i);
				buffer.setLength(0);
				for (int j = 0; j < rowData.length; j++) {
					buffer.append(rowData[j]).append(" ");
				}
				System.out.println("第" + i + "行数据:" + buffer.toString());
			}
		}
	}

}


 

 

 测试数据



 

执行伤处应用程序,输出如下,和excel的内容是一致的

Starting parsing excel,file=C:\Users\WALKER\Desktop\O2O\a.xlsx
Column names == 扫码支付商家账户 ship 
第0行数据:111 a 
第1行数据:222 b 
第2行数据:333 c 
第3行数据:v  

 

------------------------

 其它:

构造的测试案列不足够多,有些情况可能没考虑

解析代码可能有些地方没想到,在某种场景下将出错

 

-------------------------------------------------------------------------

一个用于处理excel批量上传O2O商家的例子:

需要考虑:

1 没有上传文件

2 excel格式错误,导致无法解析

3 excel为空

4 excel中有非法的数据行

 

@RequestMapping("/uploadO2OMerchants")
	@ResponseBody
	public AjaxResult uploadO2OMerchants(MultipartHttpServletRequest request) {
		MultipartFile file = request.getFile("file");
		if (file == null) {
			return AjaxResult.failed("上传的文件不允许为空");
		}
		String orignalFile = file.getOriginalFilename();
		if (!POIParser.isExcel(orignalFile)) {
			return AjaxResult.failed("上传的文件不是excel");
		}

		InputStream is = null;
		try {
			is = file.getInputStream();
		} catch (IOException e) {
			return AjaxResult.failed("文件解析失败");
		}

		POIParser parser = new POIParser();
		POIParseResult parseResult = parser.doParse(is);
		if (!parseResult.isSuccess()) {
			if (parseResult.isEmpty()) {
				return AjaxResult.failed("上传文件为空");
			}
			logger.error("Fail to parse excel,file=" + orignalFile, parseResult.getException());
			if (parseResult.containsFormatError()) {
				return AjaxResult.failed("文件解析失败,格式错误");
			}
			return AjaxResult.failed("文件解析失败");
		} else {
			List<String[]> rowDatas = parseResult.getRowDatas();
			if (rowDatas == null) {
				return AjaxResult.failed("文件格式不正确,没有设置商家");
			}
			List<String> fails = new ArrayList<String>();
			List<String> successes = new ArrayList<String>();
			for (String[] rowData : rowDatas) {
				String username = rowData[0]; // 取第0列作为user_name,如果有其它列舍去之
				if (StringUtils.isBlank(username)) {
					continue;
				}
				Result result = null;
				try {
					result = o2oService.addScanCodePayMerchant(username.trim(), super.getCurrentUsername());
				} catch (RuntimeException e) {
					logger.error("Fail to addScanCodePayMerchant ", e);
					fails.add(username);
					continue;
				}
				if (result.isSuccess()) {
					successes.add(username);
				} else {
					fails.add(username);
				}
			}
			Map<String, Object> ajaxResultMap = new HashMap<String, Object>();
			ajaxResultMap.put("fails", fails);
			ajaxResultMap.put("successes", successes);
			return AjaxResult.success(ajaxResultMap);
		}
	}

 

猜你喜欢

转载自curious.iteye.com/blog/2257157
今日推荐