java 100萬條數據以內的Excel 導入到數據庫 適用於2003和2007版

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;


import jxl.Workbook;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
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.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import com.jfinal.aop.Before;
import com.jfinal.core.Controller;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.plugin.activerecord.tx.Tx;

public class ExcelUtils {

	
	
	/**
	 * 讀取excel文件 添加到數據庫  小批量插入 低於2萬條
	 * @since 1.0
	 * @param big 是否是大數據插入只適用於2007版本的Excel
	 * @param size 多少條數據插入一次
	 * @param excelUrl 文件地址
	 * @param tableName 表明
	 * @param primaryKey 主鍵
	 * @param attrs 屬性
	 * @return
	 * @throws IOException
	 * <br><b>作者: @author WangDong</b>
	 * <br>創建時間:2017-12-29 上午11:44:01
	 */
	@Before({Tx.class})
	public static Record readExcelToSql(Boolean big ,Integer size,String excelUrl,String tableName,String primaryKey,Object[] attrs)
			throws IOException ,SQLException{
		long starTime=System.currentTimeMillis();
		int saveCount = 0;
		int count = 0;
		boolean flag = false;
		Record record = new Record();
		String suffix = excelUrl.substring(excelUrl.lastIndexOf(".") + 1)
				.trim();
		StringBuffer into = new StringBuffer("insert into "+tableName+" (");
		into.append(primaryKey);
		for (int i = 0; i < attrs.length; i++) {
			into.append(",");
			into.append(attrs[i]);
		}
		into.append(") values ");
		
		StringBuffer values = new StringBuffer();
		List<Object> parms = new ArrayList<Object>();
		try {
			if (CommCode.EXCEL_SUFFIX_XLS.equals(suffix)) {
				// 2003
				InputStream in = new FileInputStream(excelUrl);
				HSSFWorkbook workbook = new HSSFWorkbook(in);
				for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
					HSSFSheet sheet = workbook.getSheetAt(i);
					if (null == sheet)
						continue;
					int lastRowNum = sheet.getLastRowNum();
					for (int j = 0; j <= lastRowNum; j++) {
						HSSFRow row = sheet.getRow(j);
						if (null == row) {
							continue;
						}
						if(j != 0 && flag){
							values.append(",");
						}
						values.append("(?");
						parms.add(UUID.randomUUID().toString());
						for (int a = 0; a < attrs.length; a++) {
							values.append(",");
							HSSFCell cell = row.getCell(a);
							cell.setCellType(Cell.CELL_TYPE_STRING);
							values.append("?");
							parms.add(StringUtils.isNotBlank(cell.getStringCellValue())?cell.getStringCellValue():null);
							flag = true;
						}
						values.append(")");
						count ++;
						if(count % size == 0){
							int upateMySQL = insertMySQL(into.toString()+values.toString(), parms);
							saveCount += upateMySQL;
							parms.clear();
							values.setLength(0);
							flag = false;
						}
						if(j == lastRowNum && (lastRowNum+1) % size != 0){
							int upateMySQL = insertMySQL(into.toString()+values.toString(), parms);
							saveCount += upateMySQL;
							parms.clear();
							values.setLength(0);
							flag = false;
						}
					}
				}
			    long endTime=System.currentTimeMillis();
			    long  time=endTime-starTime;
				if(saveCount != count){
					record.set("state", false);
					record.set("msg", "插入數據出現異常,成功條數與文件條數不一致,相差"+(count-saveCount)+"條!");
				}else{
					record.set("state", true);
					record.set("msg", "成功插入"+saveCount+"條數據!用時:"+time/1000+"秒");
				}
			} else if (CommCode.EXCEL_SUFFIX_XLSX.equals(suffix)) {
				if(big){
					return readBigExcelToSql(size, excelUrl, tableName, primaryKey, attrs);
					
				}
					// 2007
				// OPCPackage pkg = OPCPackage.open(filename);  
					InputStream in = new FileInputStream(excelUrl);
					XSSFWorkbook workbook = new XSSFWorkbook(in);
					for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
						XSSFSheet sheet = workbook.getSheetAt(i);
						if (null == sheet)
							continue;
						int lastRowNum = sheet.getLastRowNum();
						for (int j = 0; j <= lastRowNum; j++) {
							XSSFRow row = sheet.getRow(j);
							if (null == row) {
								continue;
							}
							if(j != 0  && flag){
								values.append(",");
							}
							values.append("(?");
							parms.add(UUID.randomUUID().toString());
							for (int a = 0; a < attrs.length; a++) {
								values.append(",");
								XSSFCell cell = row.getCell(a);
								cell.setCellType(Cell.CELL_TYPE_STRING);
								values.append("?");
								parms.add(StringUtils.isNotBlank(cell.getStringCellValue())?cell.getStringCellValue():null);
								flag = true;
							}
							values.append(")");
							count ++;
							if(count % size == 0){
								int upateMySQL = insertMySQL(into.toString()+values.toString(), parms);
								saveCount += upateMySQL;
								parms.clear();
								values.setLength(0);
								flag = false;
							}
							if(j == lastRowNum && (lastRowNum+1) % size != 0){
								int upateMySQL = insertMySQL(into.toString()+values.toString(), parms);
								saveCount += upateMySQL;
								parms.clear();
								values.setLength(0);
								flag = false;
							}
						}
					}
					long endTime=System.currentTimeMillis();
					long  time=endTime-starTime;
					if(saveCount != count){
						record.set("state", false);
						record.set("msg", "插入數據出現異常,成功條數與文件條數不一致,相差"+(count-saveCount)+"條!");
					}else{
						record.set("state", true);
						record.set("msg", "成功插入"+saveCount+"條數據!用時:"+time/1000+"秒");
					}
					
			}else{
				record.set("state", false);
				record.set("msg", "您選擇的Excel版本不是2003版或2007版,或者不是Excel文件!");
			}
		} catch (Exception e) {
			record.set("state", false);
			record.set("msg", "插入數據過程中出現系統異常!請聯繫系統人員!!!");
		}
		
		return record;
	}

	
	
	
	/**
	 * 讀取excel文件 添加到數據庫
	 * @since 1.0
	 * @param size 多少條數據插入一次
	 * @param excelUrl 文件地址
	 * @param tableName 表明
	 * @param primaryKey 主鍵
	 * @param attrs 屬性
	 * @return
	 * @throws Exception 
	 */
	@Before({Tx.class})
	public static Record readBigExcelToSql(final Integer size,String excelUrl,String tableName,final String primaryKey,final Object[] attrs)
			throws Exception  ,SQLException{
		final long starTime=System.currentTimeMillis();
		int saveCount = 0;
		int count = 0;
		final Record record = new Record();
		boolean flag = false;
		final StringBuffer into = new StringBuffer("insert into "+tableName+" (");
		into.append(primaryKey);
		for (int i = 0; i < attrs.length; i++) {
			into.append(",");
			into.append(attrs[i]);
		}
		into.append(") values ");

		StringBuffer values = new StringBuffer();
		List<Object> parms = new ArrayList<Object>();

		 final BigExcelReader excel2007 = new BigExcelReader(excelUrl) {
			
			@Override
			protected void outputRow(String[] datas, int[] rowTypes, int rowIndex) {
				Record data = new Record();
				for (int i = 0; i<datas.length;i++) {
					data.set(primaryKey, UUID.randomUUID().toString());
					data.set(attrs[i].toString(), datas[i]);
				}
				list.add(data);
			}
			
		};	
		  // 執行解析  
		excel2007.parse();  
		try {
			//int[] batchSave = Db.batchSave(tableName, BigExcelReader.list, size);
			for (int i = 0; i <  BigExcelReader.list.size(); i++) {
				if (null == BigExcelReader.list.get(i)) {
					continue;
				}
				if(i != 0  && flag){
					values.append(",");
				}
				values.append("(?");
				parms.add(BigExcelReader.list.get(i).get(primaryKey));
				for (int j = 0; j < attrs.length; j++) {
					values.append(",?");
					parms.add(BigExcelReader.list.get(i).get(attrs[j].toString()));
				}
				values.append(")");
				count ++;
				flag = true;
				if(count % size == 0 && count != BigExcelReader.list.size()){
					int upateMySQL = insertMySQL(into.toString()+values.toString(), parms);
					saveCount += upateMySQL;
					parms.clear();
					values.setLength(0);
					flag = false;
				}
				if(count % size != 0 && count == BigExcelReader.list.size()){
					int upateMySQL = insertMySQL(into.toString()+values.toString(), parms);
					saveCount += upateMySQL;
					parms.clear();
					values.setLength(0);
					flag = false;
				}
			}
		} catch (Exception e) {
			// TODO: handle exception
			BigExcelReader.list.clear();
			record.set("state", false);
			record.set("msg", "插入數據過程中出現系統異常!請聯繫系統人員!!!");
			return record;
		}
		BigExcelReader.list.clear();

		long endTime=System.currentTimeMillis();
		long  time=endTime-starTime;
		if(saveCount != count){
			record.set("state", false);
			record.set("msg", "插入數據出現異常,成功條數與文件條數不一致,相差"+(count-saveCount)+"條!");
		}else{
			record.set("state", true);
			record.set("msg", "成功插入"+saveCount+"條數據!用時:"+time/1000+"秒");
		}
		return record;
	

	}
	
	
	/** 插入到數據庫
	 *
	 * @since 1.0
	 * @param sql
	 * @param parms
	 * @return
	 * <br><b>作者: @author WangDong</b>
	 * <br>創建時間:2017-12-29 下午2:44:19
	 */
	@Before({Tx.class})
	public static int insertMySQL(String sql,List<Object> parms){
		return Db.update(sql,parms.toArray());
	}
}
package com.jiazheng.utils;

import java.io.InputStream;  
import java.util.ArrayList;  
import java.util.List;  
  
import java.io.File;  
import java.io.IOException;  
import java.util.Date;  
  
import org.apache.commons.lang3.time.DateFormatUtils;  
import org.apache.poi.hssf.usermodel.HSSFDateUtil;  
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.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;  

import com.jfinal.plugin.activerecord.Record;
  
/** 大批量Excel數據讀取  只適用於2007版本
 *
 * <br>創建日期:2018-1-3
 * <br><b>Copyright 2018 DCKEJI All Rights Reserved</b>
 * @author WangDong
 * @since 1.0
 * @version 1.0
 */
public abstract class BigExcelReader{  
      
    enum xssfDataType {  
        BOOL, ERROR, FORMULA, INLINESTR, SSTINDEX, NUMBER,  
    }  
      
    public static final int ERROR = 1;  
    public static final int BOOLEAN = 1;  
    public static final int NUMBER = 2;  
    public static final int STRING = 3;  
    public static final int DATE = 4;  
    public static final String DATE_FORMAT_STR = "yyyy-MM-dd HH:mm:ss";  
    public static List<Record> list = new ArrayList<Record>();
      
//  private DataFormatter formatter = new DataFormatter();  
    private InputStream sheet;  
    private XMLReader parser;  
    private InputSource sheetSource;  
    private int index = 0;  
      
    /** 
     * 讀大數據量Excel 
     *  
     * @param filename 文件名 
     * @param maxColNum 讀取的最大列數 
     * @throws IOException 
     * @throws OpenXML4JException 
     * @throws SAXException 
     */  
    public BigExcelReader(String filename) throws IOException, OpenXML4JException, SAXException{  
    	OPCPackage pkg = OPCPackage.open(filename);  
        init(pkg);  
    }  
      
    /** 
     * 讀大數據量Excel 
     *  
     * @param file Excel文件 
     * @param maxColNum 讀取的最大列數 
     * @throws IOException 
     * @throws OpenXML4JException 
     * @throws SAXException 
     */  
    public BigExcelReader(File file) throws IOException, OpenXML4JException, SAXException{  
    	OPCPackage pkg = OPCPackage.openOrCreate(file);  
        init(pkg);  
    }  
      
    /** 
     * 讀大數據量Excel 
     *  
     * @param in Excel文件輸入流 
     * @throws IOException 
     * @throws OpenXML4JException 
     * @throws SAXException 
     */  
    public BigExcelReader(InputStream in) throws IOException, OpenXML4JException, SAXException{
         OPCPackage pkg = OPCPackage.open(in);  
         init(pkg);  
    }  
      
    /** 
     * 初始化 將Excel轉換爲XML 
     *  
     * @param pkg 
     * @throws IOException 
     * @throws OpenXML4JException 
     * @throws SAXException 
     */  
    private void init(OPCPackage pkg) throws IOException, OpenXML4JException, SAXException{  
        XSSFReader xssfReader = new XSSFReader(pkg);  
        SharedStringsTable sharedStringsTable = xssfReader.getSharedStringsTable();  
        StylesTable stylesTable = xssfReader.getStylesTable();  
        sheet = xssfReader.getSheet("rId1");  
        parser = fetchSheetParser(sharedStringsTable, stylesTable);  
        sheetSource = new InputSource(sheet);  
    }  
      
    /** 
     * 執行解析操作 
     *  
     * @return 讀取的Excel行數 
     */  
    public int parse(){  
        try {  
            parser.parse(sheetSource);  
        }   
        catch (IOException e) {  
            e.printStackTrace();  
        }   
        catch (SAXException e) {  
            e.printStackTrace();  
        }  
        finally{  
            if(sheet != null){  
                try {  
                    sheet.close();  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  
            }  
        }  
        return index;  
    }  
      
    private XMLReader fetchSheetParser(SharedStringsTable sharedStringsTable, StylesTable stylesTable) {  
        XMLReader parser = null;
		try {
			parser = XMLReaderFactory.createXMLReader(  
                    "org.apache.xerces.parsers.SAXParser"  
            );
		} catch (SAXException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}  
        ContentHandler handler = new SheetHandler(sharedStringsTable, stylesTable);  
        parser.setContentHandler(handler);  
        return parser;  
    }  
      
    /** 
     * SAX解析的處理類 
     * 每解析一行數據後通過outputRow(String[] datas, int[] rowTypes, int rowIndex)方法進行輸出 
     *  
     * @author zpin 
     */  
    private class SheetHandler extends DefaultHandler {  
        private SharedStringsTable sharedStringsTable; // 存放映射字符串  
        private StylesTable stylesTable;// 存放單元格樣式  
        private String readValue;// 存放讀取值  
        private xssfDataType dataType;// 單元格類型  
        private String[] rowDatas;// 存放一行中的所有數據  
        private int[] rowTypes;// 存放一行中所有數據類型  
        private int colIdx;// 當前所在列  
          
        private short formatIndex;  
//      private String formatString;// 對數值型的數據直接讀爲數值,不對其格式化,所以隱掉此處  
          
        private SheetHandler(SharedStringsTable sst,StylesTable stylesTable) {  
            this.sharedStringsTable = sst;  
            this.stylesTable = stylesTable;  
        }  
          
        public void startElement(String uri, String localName, String name,  
                Attributes attributes) throws SAXException {  
            if(name.equals("c")) {// c > 單元格  
                colIdx = getColumn(attributes);  
                String cellType = attributes.getValue("t");  
                String cellStyle = attributes.getValue("s");  
                  
                this.dataType = xssfDataType.NUMBER;  
                if ("b".equals(cellType)){  
                    this.dataType = xssfDataType.BOOL;  
                }  
                else if ("e".equals(cellType)){  
                    this.dataType = xssfDataType.ERROR;  
                }  
                else if ("inlineStr".equals(cellType)){  
                    this.dataType = xssfDataType.INLINESTR;  
                }  
                else if ("s".equals(cellType)){  
                    this.dataType = xssfDataType.SSTINDEX;  
                }  
                else if ("str".equals(cellType)){  
                    this.dataType = xssfDataType.FORMULA;  
                }  
                else if(cellStyle != null){  
                    int styleIndex = Integer.parseInt(cellStyle);    
                    XSSFCellStyle style = stylesTable.getStyleAt(styleIndex);    
                    this.formatIndex = style.getDataFormat();    
//                  this.formatString = style.getDataFormatString();    
                }  
            }  
            // 解析到一行的開始處時,初始化數組  
            else if(name.equals("row")){  
                int cols = getColsNum(attributes);// 獲取該行的單元格數  
                rowDatas = new String[cols];  
                rowTypes = new int[cols];  
            }  
            readValue = "";  
        }  
          
        public void endElement(String uri, String localName, String name)  
                throws SAXException {  
            if(name.equals("v")) { // 單元格的值  
                switch(this.dataType){  
                    case BOOL: {  
                        char first = readValue.charAt(0);  
                        rowDatas[colIdx] = first == '0' ? "FALSE" : "TRUE";  
                        rowTypes[colIdx] = BOOLEAN;  
                        break;  
                    }  
                    case ERROR: {  
                        rowDatas[colIdx] = "ERROR:" + readValue.toString();  
                        rowTypes[colIdx] = ERROR;  
                        break;  
                    }  
                    case INLINESTR: {  
                        rowDatas[colIdx] = new XSSFRichTextString(readValue).toString();  
                        rowTypes[colIdx] = STRING;  
                        break;  
                    }  
                    case SSTINDEX:{  
                        int idx = Integer.parseInt(readValue);    
                        rowDatas[colIdx] = new XSSFRichTextString(sharedStringsTable.getEntryAt(idx)).toString();  
                        rowTypes[colIdx] = STRING;  
                        break;  
                    }  
                    case FORMULA:{  
                        rowDatas[colIdx] = readValue;  
                        rowTypes[colIdx] = STRING;  
                        break;  
                    }  
                    case NUMBER:{  
                        // 判斷是否是日期格式    
                        if (HSSFDateUtil.isADateFormat(formatIndex, readValue)) {    
                            Double d = Double.parseDouble(readValue);    
                            Date date = HSSFDateUtil.getJavaDate(d);    
                            rowDatas[colIdx] = DateFormatUtils.format(date, DATE_FORMAT_STR);  
                            rowTypes[colIdx] = DATE;  
                        }   
//                      else if (formatString != null){  
//                          cellData.value = formatter.formatRawCellContents(Double.parseDouble(cellValue), formatIndex, formatString);  
//                          cellData.dataType = NUMBER;  
//                      }  
                        else{  
                            rowDatas[colIdx] = readValue;  
                            rowTypes[colIdx] = NUMBER;  
                        }  
                        break;  
                    }  
                }  
            }  
            // 當解析的一行的末尾時,輸出數組中的數據  
            else if(name.equals("row")){  
                outputRow(rowDatas, rowTypes, index++);  
            }  
        }  
  
        public void characters(char[] ch, int start, int length)  
                throws SAXException {  
            readValue += new String(ch, start, length);  
        }  
    }  
      
    /** 
     * 輸出每一行的數據 
     *  
     * @param datas 數據 
     * @param rowTypes 數據類型 
     * @param rowIndex 所在行 
     */  
    protected abstract void outputRow(String[] datas, int[] rowTypes, int rowIndex);  
      
    private int getColumn(Attributes attrubuts) {    
        String name = attrubuts.getValue("r");   
        int column = -1;    
        for (int i = 0; i < name.length(); ++i) {  
            if (Character.isDigit(name.charAt(i))) {  
                break;  
            }  
            int c = name.charAt(i);    
            column = (column + 1) * 26 + c - 'A';    
        }    
        return column;    
    }  
      
    private int getColsNum(Attributes attrubuts){  
        String spans = attrubuts.getValue("spans");  
        String cols = spans.substring(spans.indexOf(":") + 1);  
        return Integer.parseInt(cols);  
    }  
  
}  




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章