zoukankan      html  css  js  c++  java
  • POI事件模型处理execl导入功能(只支持07版本的execl)

    由于通过new XSSFWorkbook 这种方式导入导致生产环境端口宕机、通过dump文件和javacore文件分析是导入功能导致的。
    解决办法:自己通过网上写的工具类,不知道是否存在bug。

    package com.yygx.impexptemplate.utils;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
    import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
    import org.apache.poi.openxml4j.opc.OPCPackage;
    import org.apache.poi.xssf.eventusermodel.XSSFReader;
    import org.apache.poi.xssf.eventusermodel.XSSFReader.SheetIterator;
    import org.apache.poi.xssf.model.SharedStringsTable;
    import org.apache.poi.xssf.usermodel.XSSFRichTextString;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.xml.sax.Attributes;
    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;
    
    public class ExcelReaderParse extends DefaultHandler {
    
    	private List<String> rowData = new ArrayList<String>();
    	private List<String[]> sheetData = new ArrayList<String[]>();
    	private Map<Integer, Object> map = new HashMap<Integer, Object>();
    	private String lastContents;
    	private SharedStringsTable sst;
    	private boolean nextIsString;
    	private Integer limit = 0;
    	// 定义前一个元素和当前元素的位置,用来计算其中空的单元格数量,如A6和A8等
    	private String preRef = null, ref = null;
    	// 定义该文档一行最大的单元格数,用来补全一行最后可能缺失的单元格
    	private String maxRef = null;
    	private int curRow = 0;
    	private int maxlimit = 0;
    	private List<String[]> sheetNames ;
    	
    	private int titleRow = 2;
    
    	public int getSheetRow() {
    		return titleRow;
    	}
    
    	public void setSheetRow(int sheetRow) {
    		this.titleRow = sheetRow;
    	}
    
    	public List<String[]> getSheetNames() {
    		return sheetNames;
    	}
    
    	public void setSheetNames(List<String[]> sheetNames) {
    		this.sheetNames = sheetNames;
    	}
    
    	public Map<Integer, Object> getMap() {
    		return map;
    	}
    
    	public void setMap(Map<Integer, Object> map) {
    		this.map = map;
    	}
    
    	/**
    	 * 读取所有工作簿的入口方法
    	 * 
    	 * @param path
    	 * @throws Exception
    	 */
    	@Autowired
    	public void process(InputStream inputStream) {
    		OPCPackage pkg = null;
    		InputStream sheet = null;
    		try {
    			pkg = OPCPackage.open(inputStream);
    			XSSFReader r = new XSSFReader(pkg);
    			SharedStringsTable sst = r.getSharedStringsTable();
    
    			XMLReader parser = fetchSheetParser(sst);
    
    			// Iterator<InputStream> sheets = r.getSheetsData();
    			SheetIterator sheets = (SheetIterator) r.getSheetsData();
    			String sheetName = null;
    			int sheetNum = 0;
    			while (sheets.hasNext()) {
    				sheet = sheets.next();
    				if(sheetNum == 0){
    					sheetName = sheets.getSheetName();
    				}
    				InputSource sheetSource = new InputSource(sheet);
    				parser.parse(sheetSource);
    				sheet.close();
    
    				map.put(sheetNum, this.sheetData);
    				this.sheetData = new ArrayList<String[]>();
    				sheetNum++;
    				curRow = 0;
    			}
    			List<String[]> list = new ArrayList<String[]>();
    			list.add(new String[]{sheetName});
    			this.setSheetNames(list);
    		} catch (InvalidFormatException e) {
    			throw new RuntimeException(e.getMessage());
    		} catch (IOException e) {
    			throw new RuntimeException(e.getMessage());
    		} catch (OpenXML4JException e) {
    			throw new RuntimeException(e.getMessage());
    		} catch (SAXException e) {
    			throw new RuntimeException(e.getMessage());
    		} finally {
    			try {
    				pkg.close();
    				sheet.close();
    			} catch (IOException e) {
    				// TODO Auto-generated catch block
    				throw new RuntimeException(e.getMessage());
    			}
    		}
    	}
    
    	/**
    	 * 读取第一个工作簿的入口方法
    	 * 
    	 * @param path
    	 * @throws RuntimeException
    	 */
    	private void readOneSheet(String path) throws RuntimeException {
    		// TODO Auto-generated method stub
    		OPCPackage pkg = null;
    		InputStream sheet = null;
    		try {
    			pkg = OPCPackage.open(path);
    			XSSFReader r = new XSSFReader(pkg);
    			SharedStringsTable sst = r.getSharedStringsTable();
    			XMLReader parser = fetchSheetParser(sst);
    			sheet = r.getSheet("rId1");
    			InputSource sheetSource = new InputSource(sheet);
    			parser.parse(sheetSource);
    			map.put(0, this.sheetData);
    			this.sheetData.clear();
    		} catch (InvalidFormatException e) {
    			throw new RuntimeException(e.getMessage());
    		} catch (IOException e) {
    			throw new RuntimeException(e.getMessage());
    		} catch (OpenXML4JException e) {
    			throw new RuntimeException(e.getMessage());
    		} catch (SAXException e) {
    			throw new RuntimeException(e.getMessage());
    		} finally {
    			try {
    				pkg.close();
    				sheet.close();
    			} catch (IOException e) {
    				// TODO Auto-generated catch block
    				throw new RuntimeException(e.getMessage());
    			}
    		}
    	}
    
    	private XMLReader fetchSheetParser(SharedStringsTable sst)
    			throws RuntimeException {
    		// TODO Auto-generated method stub
    		XMLReader parser;
    		try {
    			parser = XMLReaderFactory
    					.createXMLReader("org.apache.xerces.parsers.SAXParser");
    			this.sst = sst;
    			parser.setContentHandler(this);
    			return parser;
    		} catch (SAXException e) {
    			// TODO Auto-generated catch block
    			throw new RuntimeException(e.getMessage());
    		}
    
    	}
    
    	public void startElement(String uri, String localName, String name,
    			Attributes attributes) throws SAXException {
    		// c => 单元格
    		if (name.equals("c")) {
    			// 前一个单元格的位置
    			if (preRef == null) {
    				preRef = attributes.getValue("r");
    			} else {
    				preRef = ref;
    			}
    			// 当前单元格的位置
    			ref = attributes.getValue("r");
    
    			// 如果下一个元素是 SST 的索引,则将nextIsString标记为true
    			String cellType = attributes.getValue("t");
    			if (cellType != null && cellType.equals("s")) {
    				nextIsString = true;
    			} else {
    				nextIsString = false;
    			}
    		}
    		// 置空
    		lastContents = "";
    	}
    
    	public void endElement(String uri, String localName, String name)
    			throws SAXException {
    		// 根据SST的索引值的到单元格的真正要存储的字符串
    		// 这时characters()方法可能会被调用多次
    		if (nextIsString) {
    			try {
    				int idx = Integer.parseInt(lastContents);
    				lastContents = new XSSFRichTextString(sst.getEntryAt(idx))
    						.toString();
    				nextIsString = false;
    			} catch (Exception e) {
    				e.printStackTrace();
    			}
    		}
    
    		// v => 单元格的值,如果单元格是字符串则v标签的值为该字符串在SST中的索引
    		// 将单元格内容加入rowlist中,在这之前先去掉字符串前后的空白符
    		if (name.equals("v")) {
    			String value = lastContents.trim();
    //			if (value.equals("销售与客服支撑")) {
    //				System.out.println();
    //			}
    
    			// 补全单元格之间的空单元格
    			if (!ref.equals(preRef)) {
    				int len = countNullCell(ref, preRef);
    				for (int i = 0; i < len; i++) {
    					rowData.add(limit, "");
    					limit++;
    				}
    			} else if (ref.equals(preRef) && limit == 0 && !ref.contains("A")) {
                	int len = letterToNum(ref);
                    for(int i=0;i<len-1;i++){  
                        rowData.add(limit,"");
                        limit++; 
                    }  
    			}
    
    			rowData.add(limit, value);
    			limit++;
    		} else if (name.equals("row")) {
    			// 如果标签名称为 row ,这说明已到行尾,调用 optRows() 方法
    			// System.out.println(rowData);
    			if(curRow == titleRow) {
            		maxlimit = limit;
            	}else if(curRow == 0) {
            		maxlimit = limit;
            	}
    			if (limit != maxlimit) {
    				int len = maxlimit - limit;
    				for (int i = 0; i < len; i++) {
    					rowData.add(limit, "");
    					limit++;
    				}
    			}
    			sheetData.add(rowData.toArray(new String[limit]));
    			rowData.clear();
    			limit = 0;
    			curRow++;
    			preRef = null;
    			ref = null;
    		}
    	}
    
    	/**
    	 * 计算两个单元格之间的单元格数目(同一行)
    	 * 
    	 * @param ref
    	 * @param preRef
    	 * @return
    	 */
    	public int countNullCell(String ref, String preRef) {
    		// excel2007最大行数是1048576,最大列数是16384,最后一列列名是XFD
    		String xfd = ref.replaceAll("\d+", "");
    		String xfd_1 = preRef.replaceAll("\d+", "");
    
    		xfd = fillChar(xfd, 3, '@', true);
    		xfd_1 = fillChar(xfd_1, 3, '@', true);
    
    		char[] letter = xfd.toCharArray();
    		char[] letter_1 = xfd_1.toCharArray();
    		int res = (letter[0] - letter_1[0]) * 26 * 26
    				+ (letter[1] - letter_1[1]) * 26 + (letter[2] - letter_1[2]);
    		return res - 1;
    	}
    
    	/**
    	 * 字符串的填充
    	 * 
    	 * @param str
    	 * @param len
    	 * @param let
    	 * @param isPre
    	 * @return
    	 */
    	String fillChar(String str, int len, char let, boolean isPre) {
    		int len_1 = str.length();
    		if (len_1 < len) {
    			if (isPre) {
    				for (int i = 0; i < (len - len_1); i++) {
    					str = let + str;
    				}
    			} else {
    				for (int i = 0; i < (len - len_1); i++) {
    					str = str + let;
    				}
    			}
    		}
    		return str;
    	}
    
    	public void characters(char[] ch, int start, int length)
    			throws SAXException {
    		// 得到单元格内容的值
    		lastContents += new String(ch, start, length);
    	}
    	
    	// 将字母转换成数字
    	public int letterToNum(String input) {
    		
    		StringBuffer sb = new StringBuffer();
    		for (int i = 0; i < input.length(); i++) {
    			char c = input.charAt(i);
    			if ((c <= 'z' && c >= 'a') || (c <= 'Z' && c >= 'A')) {
    				sb.append(c);
    			}
    		}
    		
    		StringBuilder builder = new StringBuilder();
    		for (byte b : sb.toString().toLowerCase().getBytes()) {
    			builder.append(b - 96);
    		}
    		return Integer.valueOf(builder.toString());
    	}
    }
    

      

  • 相关阅读:
    Vue中调用另一个组件中自定义事件
    docker下安装MySQL
    docker下安装Redis
    .NET Core简介
    Object(Asp.NET核心机制内置对象汇总)
    .NET MVC5简介(六)HttpHandler
    .NET MVC5简介(五)管道处理模型IHttpModule
    hibernate有什么作用
    hibernate编写时没有提示
    触发器insert
  • 原文地址:https://www.cnblogs.com/wuhaidong/p/10190073.html
Copyright © 2011-2022 走看看