通过excel导入数据功能分析与实现

一个项目可能会有大量的录入数据,通过手动在页面上添,是非常麻烦的事情.可以采用excel表格导入数据的方式,减轻用户的手动压力.

实现步骤说明 :

1.从页面下载模板(也就是excel导出功能只不过数据为空就可以)

建好规定的一个excel模板文件(当然也可以使用POI写代码来画,但比较麻烦),提供给用户按格式放入数据.

例如:

2.用户下载到模板后,往里放入数据.在上传到服务器 

实现步骤:1.通过fileupload得到输入流,2.使用POI解析输入流,得到数据集合或者封装到实体类3.存入数据库

得到流数据的两种方式:

第一个:Spring本身提供了CommonsMultipartResolver这个类,只要在配置文件中配置上,

<!-- 支持上传文件 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 上传文件最大值 -->
		<property name="maxUploadSize" value="10240" />
<!-- 缓存最大值 -->
		<property name="maxInMemorySize" value="1024" />
<!-- 编码格式 -->
		<property name="defaultEncoding" value="UTF-8" />
</bean>

然后方法中获取request对象,强转成MultipartHttpServletRequest对象,获取inputStream即可得到上传的数据流.

MultipartHttpServletRequest mRequest = (MultipartHttpServletRequest) request;

ServletInputStream inputStream = mRequest.getInputStream();
第二个:使用commons-fileupload这个包,spring也是通过它来实现的.大致方法
InputStream inputStream = null;
DiskFileItemFactory factory = new DiskFileItemFactory();
FileUpload fileUpload = new FileUpload(factory);
fileUpload.setSizeMax(102400);
fileUpload.setHeaderEncoding("UTF-8");
fileUpload.setFileSizeMax(1024);
List<FileItem> fileItems = fileUpload.parseRequest(request);
for (FileItem item:fileItems){
	inputStream = item.getInputStream();
}
注:request只能被fileupload解析一次.如果项目配置了CommonsMultipartResolver,直接通过第一种转化request的方式即可.SpringBoot项目是配置好的.使用第二种方式无法获取到数据流

POI解析excel基本代码

//获取输入流
		ServletInputStream inputStream = request.getInputStream();
		//通过poi解析流为hssfworkbook对象:如果是xls格式对应HSSFWorkbook,
		// 如果是xlsx对应着XSSFWorkbook,需要导入poi-ooxml的包
		HSSFWorkbook workbook = new HSSFWorkbook(inputStream);
		//获取sheet页
		HSSFSheet sheet = workbook.getSheetAt(0);
		//遍历表格数据
        //行对象
		Iterator<Row> rowIterator = sheet.rowIterator();
		while (rowIterator.hasNext()){ 
            //得到行对象
			Row row = rowIterator.next();
            //得到每个单元格的迭代器
			Iterator<Cell> cellIterator = row.cellIterator();
            //获取值(略)
           //封装数据(略)
		}
       //调用DAO层,存数据即可

 到这里功能就实现啦.

下面放一个工具类ExcelHelper :

可以用来导出,解析数据的一些功能



import org.apache.poi.POIXMLException;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
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.xssf.usermodel.XSSFWorkbook;

import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ExcelHelper {
	private static final int NO_DATA = -1;
	private static final int ROW_DATA = 0;
	private static final int CELL_DATA = 1;

	public Map<String, Object> valueToMap(Class<?> clazz, Object value) {
		Map<String, Object> valueMap = new HashMap<String, Object>();
		for (Field field : clazz.getDeclaredFields()) {
			String attrName = field.getName();
			String methodName = "get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
			try {
				Method m = clazz.getMethod(methodName);
				if (m != null) {
					Object oVal = m.invoke(value);
					if (oVal != null) {
						valueMap.put(attrName, oVal);
					}
				}
			} catch (Exception e) {
			}
		}
		return valueMap;
	}

	public void export(OutputStream out, File templateFile, Map<String, Object> datas)
			throws FileNotFoundException, IOException {
		Workbook workbook = null;
		FileInputStream in = null;
		try {
			in = new FileInputStream(templateFile);
			workbook = new XSSFWorkbook(in);// 先尝试用xlsx格式读
		} catch (FileNotFoundException e) {
			throw e;
		} catch (POIXMLException e) {// 异常后,使用xls格式读
			in = new FileInputStream(templateFile);
			workbook = new HSSFWorkbook(in);
		}
		Sheet sheet = workbook.getSheetAt(0);
		fillSheet(sheet, datas);
		workbook.write(out);
		out.flush();
		out.close();
		in.close();
	}

	@SuppressWarnings("rawtypes")
	protected void fillSheet(Sheet sheet, Map<String, Object> datas) {
		int i = sheet.getFirstRowNum();
		int end = sheet.getLastRowNum();
		while (i <= end) {
			Row row = sheet.getRow(i);
			int rowState = NO_DATA;
			for (Iterator<Cell> it = row.cellIterator(); it.hasNext();) {
				Cell cell = it.next();
				String cellValue = cell.getStringCellValue();
				if (hasRowExpression(cell)) {// 是否行数据
					rowState = ROW_DATA;
					break;// 发现行数据即刻跳出
				} else if (isExpressionValue(cellValue)) {
					rowState = CELL_DATA;
					Object newValue = getExpressionValue(datas, cellValue);
					if (newValue != null) {
						cell.setCellValue(newValue.toString());
					}
				} else {
					rowState = NO_DATA;
				}
			}
			if (rowState == ROW_DATA) {
				Object rowsObject = datas.get("rows");
				if (rowsObject != null) {
					if (rowsObject instanceof Collection) {
						Collection rows = (Collection) rowsObject;
						for (Iterator it = rows.iterator(); it.hasNext();) {
							Object rowData = it.next();
							Row target = sheet.getRow(i);
							if (it.hasNext()) {
								if (i < end) {
									insertRow(sheet, i, 1);
									Row source = sheet.getRow(++i);
									copyRow(source, target);
								} else if (i == end) {
									Row newRow = sheet.createRow(++i);
									copyRow(target, newRow);
								}
								end++;
							}
							processRow(target, rowData);
						}
					}
				} else {
					sheet.removeRow(row);
				}
			}
			i++;
		}
	}

	private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat();

	protected void processRow(Row target, Object rowData) {
		for (Iterator<Cell> cellIterator = target.cellIterator(); cellIterator.hasNext();) {
			Cell cell = cellIterator.next();
			if (hasRowExpression(cell)) {// 是否行数据
				String newValue = getRowExpressionValue(rowData, cell.getCellComment().getString().getString());
				if (newValue != null) {
					if (newValue.matches("[\\d\\.]+")) {// number
						cell.setCellValue(Double.parseDouble(newValue));
					} else if (newValue.matches("\\d{4}-\\d{2}-\\d{2}")) {
						try {
							cell.setCellValue(DATE_FORMAT.parse(newValue));
						} catch (ParseException e) {
							cell.setCellValue(newValue);
						}
					} else {
						cell.setCellValue(newValue);
					}
				}
				cell.removeCellComment();
			}
		}
	}

	protected void copyRow(Row source, Row target) {
		for (int i = source.getFirstCellNum(); i < source.getLastCellNum(); i++) {
			Cell sourceCell = source.getCell(i);
			Cell targetCell = target.createCell(i);
			targetCell.setCellStyle(sourceCell.getCellStyle());
			targetCell.setCellType(sourceCell.getCellType());
			targetCell.setCellComment(sourceCell.getCellComment());
		}
	}

	protected boolean isExpressionValue(String cellValue) {
		// 检查是否包含表达式
		return cellValue.matches("[\\s\\S]*\\$\\{\\s*[^\\{\\s]+\\s*\\}[\\s\\S]*");
	}

	protected boolean hasRowExpression(Cell cell) {
		if (cell == null || cell.getCellComment() == null)
			return false;
		String comment = cell.getCellComment().getString().getString();
		// 检查是否包含表达式是否包含row标示
		return comment.matches("[\\s\\S]*\\$\\{\\s*\\w+.\\w+\\s*\\}[s\\S]*");
	}

	private static final Pattern PARAMETER_PATTERN = Pattern.compile("\\$\\{\\s*([^\\{\\s]+)\\s*\\}");

	protected Object getExpressionValue(Map<String, Object> datas, String expression) {
		Matcher m = PARAMETER_PATTERN.matcher(expression);
		while (m.find()) {
			String target = m.group();
			String key = m.group(1);
			Object val = datas.get(key);
			String replacement = val != null ? val.toString() : "";
			do {
				expression = expression.replace(target, replacement);
			} while (expression.contains(target));
		}
		return expression;
	}

	private static final Pattern ROW_PATTERN = Pattern.compile("\\$\\{\\s*row.(\\w+)\\s*\\}");

	protected String getRowExpressionValue(Object object, String expression) {
		Matcher m = ROW_PATTERN.matcher(expression);
		while (m.find()) {
			String target = m.group();
			String key = m.group(1);
			Object val = getAttribute(object, key);
			String replacement = val != null ? val.toString() : "";
			do {
				expression = expression.replace(target, replacement);
			} while (expression.contains(target));
		}
		return expression;
	}

	@SuppressWarnings("unchecked")
	private Object getAttribute(Object object, String attr) {
		String val = "";
		if (object instanceof Map) {
			Map<String, Object> dataMap = (Map<String, Object>) object;
			Object oVal = dataMap.get(attr);
			if (oVal != null) {
				val = oVal.toString();
			}
		} else {
			try {
				String methodName = "get" + attr.substring(0, 1).toUpperCase() + attr.substring(1);
				Object oVal = object.getClass().getMethod(methodName).invoke(object);
				if (oVal != null) {
					val = oVal.toString();
				}
			} catch (Exception e) {
			}
		}
		return val;
	}

	public static void insertRow(Sheet sheet, int starRow, int rows) {
		sheet.shiftRows(starRow + 1, sheet.getLastRowNum(), rows, true, false);
		starRow = starRow - 1;
		for (int i = 0; i < rows; i++) {
			starRow = starRow + 1;
			Row sourceRow = sheet.getRow(starRow);
			Row targetRow = sheet.createRow(starRow + 1);
			targetRow.setHeight(sourceRow.getHeight());
			Cell sourceCell = null;
			Cell targetCell = null;
			for (int m = sourceRow.getFirstCellNum(); m < sourceRow.getLastCellNum(); m++) {
				sourceCell = sourceRow.getCell(m);
				targetCell = targetRow.createCell(m);
				targetCell.setCellStyle(sourceCell.getCellStyle());
				targetCell.setCellType(sourceCell.getCellType());
			}
		}
	}

	public List<Map<String, Object>> readRows(InputStream inputFile, FileInputStream templateFile)
			throws FileNotFoundException, IOException {
		Workbook source = new HSSFWorkbook(inputFile);
		Workbook template = new HSSFWorkbook(templateFile);
		List<Map<String, Object>> datas = extractSheet(source.getSheetAt(0), template.getSheetAt(0));
		try {
			inputFile.close();
			templateFile.close();
		} catch (IOException e) {
		}
		return datas;
	}

	public List<Map<String, Object>> readRows(File inputFile, File templateFile)
			throws FileNotFoundException, IOException {
		Workbook source = null;
		Workbook template = null;
		InputStream in = null;
		InputStream tis = null;
		try {
			in = new FileInputStream(inputFile);
			tis = new FileInputStream(templateFile);
			template = new XSSFWorkbook(tis);// 先尝试用xlsx格式读
			source = new XSSFWorkbook(in);// 先尝试用xlsx格式读
		} catch (FileNotFoundException e) {
			throw e;
		} catch (POIXMLException e) {// 异常后,使用xls格式读
			in = new FileInputStream(inputFile);
			tis = new FileInputStream(templateFile);
			source = new HSSFWorkbook(in);
			template = new HSSFWorkbook(tis);
		}
		List<Map<String, Object>> datas = extractSheet(source.getSheetAt(0), template.getSheetAt(0));
		try {
			in.close();
			tis.close();
		} catch (IOException e) {
		}
		return datas;
	}

	protected List<Map<String, Object>> extractSheet(Sheet sheet, Sheet template) {
		List<Map<String, Object>> datas = new ArrayList<Map<String, Object>>();
		int idx = template.getFirstRowNum();
		while (idx <= template.getLastRowNum()) {
			Row templateRow = template.getRow(idx);
			boolean found = false;
			Map<Short, String> templateData = new HashMap<Short, String>();
			for (short i = 0; i <= templateRow.getLastCellNum(); i++) {
				Cell cell = templateRow.getCell(i);
				if (hasRowExpression(cell)) {
					Matcher m = ROW_PATTERN.matcher(cell.getCellComment().getString().getString());
					m.find();
					String attributeName = m.group(1);
					if (attributeName != null && !"".equals(attributeName)) {
						templateData.put(i, attributeName);
					}
					found = true;
				}
			}
			if (found) {// 找到模板中的行
				for (int i = idx; i <= sheet.getLastRowNum(); i++) {
					Row dataRow = sheet.getRow(i);
					Map<String, Object> rowData = new HashMap<String, Object>();
					for (Short key : templateData.keySet()) {
						String attributeName = templateData.get(key);
						Cell dataCell = dataRow.getCell(key);
						if (dataCell != null) {
							if (dataCell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
								if (HSSFDateUtil.isCellDateFormatted(dataCell)) {
									SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
									SimpleDateFormat _sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy",
											Locale.UK);
									Date date = null;
									try {
										date = _sdf.parse(
												HSSFDateUtil.getJavaDate(dataCell.getNumericCellValue()).toString());
									} catch (ParseException e) {
										// TODO Auto-generated catch block
										e.printStackTrace();
									}
									// 如果是date类型则 ,获取该cell的date值
									rowData.put(attributeName, sdf.format(date));
								} else { // 纯数字
									rowData.put(attributeName, dataCell.getNumericCellValue());
								}
							} else {
								rowData.put(attributeName, dataCell.getStringCellValue());
							}
						}
					}
					datas.add(rowData);
				}
			}
			idx++;
		}
		return datas;
	}
}

猜你喜欢

转载自blog.csdn.net/weixin_40648180/article/details/84632514
今日推荐