大数据量的excel文件读取——excel2007

2 篇文章 0 订阅

    excel2007文件格式与之前版本不同,之前版本采用的是微软自己的存储格式。07版内容的存储采用XML格式,所以,理所当然的,对大数据量的xlsx文件的读取采用的也是XML的处理方式SAX。

    同之前的版本一样,大数据量文件的读取采用的是事件模型eventusermodel。usermodel模式需要将文件一次性全部读到内存中,07版的既然采用的存储模式是xml,解析用的DOM方式也是如此,这种模式操作简单,容易上手,但是对于大量数据占用的内存也是相当可观,在Eclipse中经常出现内存溢出。

    下面就是采用eventusermodel对07excel文件读取。

    同上篇,我将当前行的单元格数据存储到List中,抽象出 optRows 方法,该方法会在每行末尾时调用,方法参数为当前行索引curRow(int型)及存有行内单元格数据的List。继承类只需实现该行级方法即可。


补充:今天发现 读取2007的脚本存在存在一处问题,在遇到空单元格时会跳过该单元格,由于工作紧张没有时间去解决该问题,这里给出一个暂时的处理办法。打开文件,在开始菜单中选择"查找和选择","定位条件",选择"空值",确定,这时会找出所有的空单元格,直接按空格,然后Ctrl+enter,就会将所有空单元格填入一个空格,保存即可。

 

2010.6.10补充:空单元格的问题已经解决,在2007的文档中空单元格是不存储的,单元格的r属性是单元格位置信息,格式为[A-Z]+[0-9]+。字母部分是列索引,数字部分是行索引。

 

抽象类:XxlsAbstract ,作用:遍历excel文件,提供行级操作方法 optRows

Java代码
  1. package com.gaosheng.util.xls;  
  2.   
  3. import java.io.InputStream;  
  4. import java.sql.SQLException;  
  5. import java.util.ArrayList;  
  6. import java.util.Iterator;  
  7. import java.util.List;  
  8.   
  9. import org.apache.poi.xssf.eventusermodel.XSSFReader;  
  10. import org.apache.poi.xssf.model.SharedStringsTable;  
  11. import org.apache.poi.xssf.usermodel.XSSFRichTextString;  
  12. import org.apache.poi.openxml4j.opc.OPCPackage;  
  13. import org.xml.sax.Attributes;  
  14. import org.xml.sax.InputSource;  
  15. import org.xml.sax.SAXException;  
  16. import org.xml.sax.XMLReader;  
  17. import org.xml.sax.helpers.DefaultHandler;  
  18. import org.xml.sax.helpers.XMLReaderFactory;  
  19.   
  20. /** 
  21.  * XSSF and SAX (Event API) 
  22.  */  
  23. public abstract class XxlsAbstract extends DefaultHandler {  
  24.     private SharedStringsTable sst;  
  25.     private String lastContents;  
  26.     private boolean nextIsString;  
  27.   
  28.     private int sheetIndex = -1;  
  29.     private List<String> rowlist = new ArrayList<String>();  
  30.     private int curRow = 0;     //当前行  
  31.     private int curCol = 0;     //当前列索引  
  32.     private int preCol = 0;     //上一列列索引  
  33.     private int titleRow = 0;   //标题行,一般情况下为0  
  34.     private int rowsize = 0;    //列数  
  35.       
  36.     //excel记录行操作方法,以行索引和行元素列表为参数,对一行元素进行操作,元素为String类型  
  37. //  public abstract void optRows(int curRow, List<String> rowlist) throws SQLException ;  
  38.       
  39.     //excel记录行操作方法,以sheet索引,行索引和行元素列表为参数,对sheet的一行元素进行操作,元素为String类型  
  40.     public abstract void optRows(int sheetIndex,int curRow, List<String> rowlist) throws SQLException;  
  41.       
  42.     //只遍历一个sheet,其中sheetId为要遍历的sheet索引,从1开始,1-3  
  43.     public void processOneSheet(String filename,int sheetId) throws Exception {  
  44.         OPCPackage pkg = OPCPackage.open(filename);  
  45.         XSSFReader r = new XSSFReader(pkg);  
  46.         SharedStringsTable sst = r.getSharedStringsTable();  
  47.           
  48.         XMLReader parser = fetchSheetParser(sst);  
  49.   
  50.         // rId2 found by processing the Workbook  
  51.         // 根据 rId# 或 rSheet# 查找sheet  
  52.         InputStream sheet2 = r.getSheet("rId"+sheetId);  
  53.         sheetIndex++;  
  54.         InputSource sheetSource = new InputSource(sheet2);  
  55.         parser.parse(sheetSource);  
  56.         sheet2.close();  
  57.     }  
  58.   
  59.     /** 
  60.      * 遍历 excel 文件 
  61.      */  
  62.     public void process(String filename) throws Exception {  
  63.         OPCPackage pkg = OPCPackage.open(filename);  
  64.         XSSFReader r = new XSSFReader(pkg);  
  65.         SharedStringsTable sst = r.getSharedStringsTable();  
  66.   
  67.         XMLReader parser = fetchSheetParser(sst);  
  68.   
  69.         Iterator<InputStream> sheets = r.getSheetsData();  
  70.         while (sheets.hasNext()) {  
  71.             curRow = 0;  
  72.             sheetIndex++;  
  73.             InputStream sheet = sheets.next();  
  74.             InputSource sheetSource = new InputSource(sheet);  
  75.             parser.parse(sheetSource);  
  76.             sheet.close();  
  77.         }  
  78.     }  
  79.   
  80.     public XMLReader fetchSheetParser(SharedStringsTable sst)  
  81.             throws SAXException {  
  82.         XMLReader parser = XMLReaderFactory  
  83.                 .createXMLReader("org.apache.xerces.parsers.SAXParser");  
  84.         this.sst = sst;  
  85.         parser.setContentHandler(this);  
  86.         return parser;  
  87.     }  
  88.   
  89.     public void startElement(String uri, String localName, String name,  
  90.             Attributes attributes) throws SAXException {  
  91.         // c => 单元格  
  92.         if (name.equals("c")) {  
  93.             // 如果下一个元素是 SST 的索引,则将nextIsString标记为true  
  94.             String cellType = attributes.getValue("t");  
  95.             String rowStr = attributes.getValue("r");  
  96.             curCol = this.getRowIndex(rowStr);  
  97.             if (cellType != null && cellType.equals("s")) {  
  98.                 nextIsString = true;  
  99.             } else {  
  100.                 nextIsString = false;  
  101.             }  
  102.         }  
  103.         // 置空  
  104.         lastContents = "";  
  105.     }  
  106.   
  107.     public void endElement(String uri, String localName, String name)  
  108.             throws SAXException {  
  109.         // 根据SST的索引值的到单元格的真正要存储的字符串  
  110.         // 这时characters()方法可能会被调用多次  
  111.         if (nextIsString) {  
  112.             try {  
  113.                 int idx = Integer.parseInt(lastContents);  
  114.                 lastContents = new XSSFRichTextString(sst.getEntryAt(idx))  
  115.                         .toString();  
  116.             } catch (Exception e) {  
  117.   
  118.             }  
  119.         }  
  120.   
  121.         // v => 单元格的值,如果单元格是字符串则v标签的值为该字符串在SST中的索引  
  122.         // 将单元格内容加入rowlist中,在这之前先去掉字符串前后的空白符  
  123.         if (name.equals("v")) {  
  124.             String value = lastContents.trim();  
  125.             value = value.equals("")?" ":value;  
  126.             int cols = curCol-preCol;  
  127.             if (cols>1){  
  128.                 for (int i = 0;i < cols-1;i++){  
  129.                     rowlist.add(preCol,"");  
  130.                 }  
  131.             }  
  132.             preCol = curCol;  
  133.             rowlist.add(curCol-1, value);  
  134.         }else {  
  135.             //如果标签名称为 row ,这说明已到行尾,调用 optRows() 方法  
  136.             if (name.equals("row")) {  
  137.                 int tmpCols = rowlist.size();  
  138.                 if(curRow>this.titleRow && tmpCols<this.rowsize){  
  139.                     for (int i = 0;i < this.rowsize-tmpCols;i++){  
  140.                         rowlist.add(rowlist.size(), "");  
  141.                     }  
  142.                 }  
  143.                 try {  
  144.                     optRows(sheetIndex,curRow,rowlist);  
  145.                 } catch (SQLException e) {  
  146.                     e.printStackTrace();  
  147.                 }  
  148.                 if(curRow==this.titleRow){  
  149.                     this.rowsize = rowlist.size();  
  150.                 }  
  151.                 rowlist.clear();  
  152.                 curRow++;  
  153.                 curCol = 0;  
  154.                 preCol = 0;  
  155.             }  
  156.         }  
  157.     }  
  158.   
  159.     public void characters(char[] ch, int start, int length)  
  160.             throws SAXException {  
  161.         //得到单元格内容的值  
  162.         lastContents += new String(ch, start, length);  
  163.     }  
  164.       
  165.     //得到列索引,每一列c元素的r属性构成为字母加数字的形式,字母组合为列索引,数字组合为行索引,  
  166.     //如AB45,表示为第(A-A+1)*26+(B-A+1)*26列,45行  
  167.     public int getRowIndex(String rowStr){  
  168.         rowStr = rowStr.replaceAll("[^A-Z]""");  
  169.         byte[] rowAbc = rowStr.getBytes();  
  170.         int len = rowAbc.length;  
  171.         float num = 0;  
  172.         for (int i=0;i<len;i++){  
  173.             num += (rowAbc[i]-'A'+1)*Math.pow(26,len-i-1 );  
  174.         }  
  175.         return (int) num;  
  176.     }  
  177.   
  178.     public int getTitleRow() {  
  179.         return titleRow;  
  180.     }  
  181.   
  182.     public void setTitleRow(int titleRow) {  
  183.         this.titleRow = titleRow;  
  184.     }  
  185. }  

 

继承类:XxlsBig,作用:将数据转出到数据库临时表

Java代码
  1. package com.gaosheng.util.examples.xls;  
  2.   
  3. import java.io.FileInputStream;  
  4. import java.io.IOException;  
  5. import java.sql.Connection;  
  6. import java.sql.DriverManager;  
  7. import java.sql.PreparedStatement;  
  8. import java.sql.SQLException;  
  9. import java.sql.Statement;  
  10. import java.util.List;  
  11. import java.util.Properties;  
  12.   
  13. import com.gaosheng.util.xls.XxlsAbstract;  
  14.   
  15. public class XxlsBig extends XxlsAbstract {  
  16.     public static void main(String[] args) throws Exception {  
  17.         XxlsBig howto = new XxlsBig("temp_table");  
  18.         howto.processOneSheet("F:/new.xlsx",1);  
  19.         howto.process("F:/new.xlsx");  
  20.         howto.close();  
  21.     }  
  22.       
  23.     public XxlsBig(String tableName) throws SQLException{  
  24.         this.conn = getNew_Conn();  
  25.         this.statement = conn.createStatement();  
  26.         this.tableName = tableName;  
  27.     }  
  28.   
  29.     private Connection conn = null;  
  30.     private Statement statement = null;  
  31.     private PreparedStatement newStatement = null;  
  32.   
  33.     private String tableName = "temp_table";  
  34.     private boolean create = true;  
  35.       
  36.     public void optRows(int sheetIndex,int curRow, List<String> rowlist) throws SQLException {  
  37.         if (sheetIndex == 0 && curRow == 0) {  
  38.             StringBuffer preSql = new StringBuffer("insert into " + tableName  
  39.                     + " values(");  
  40.             StringBuffer table = new StringBuffer("create table " + tableName  
  41.                     + "(");  
  42.             int c = rowlist.size();  
  43.             for (int i = 0; i < c; i++) {  
  44.                 preSql.append("?,");  
  45.                 table.append(rowlist.get(i));  
  46.                 table.append("  varchar2(100) ,");  
  47.             }  
  48.   
  49.             table.deleteCharAt(table.length() - 1);  
  50.             preSql.deleteCharAt(preSql.length() - 1);  
  51.             table.append(")");  
  52.             preSql.append(")");  
  53.             if (create) {  
  54.                 statement = conn.createStatement();  
  55.                 try{  
  56.                     statement.execute("drop table "+tableName);  
  57.                 }catch(Exception e){  
  58.                       
  59.                 }finally{  
  60.                     System.out.println("表 "+tableName+" 删除成功");  
  61.                 }  
  62.                 if (!statement.execute(table.toString())) {  
  63.                     System.out.println("创建表 "+tableName+" 成功");  
  64.                     // return;  
  65.                 } else {  
  66.                     System.out.println("创建表 "+tableName+" 失败");  
  67.                     return;  
  68.                 }  
  69.             }  
  70.             conn.setAutoCommit(false);  
  71.             newStatement = conn.prepareStatement(preSql.toString());  
  72.   
  73.         } else if(curRow>0) {  
  74.             // 一般行  
  75.             int col = rowlist.size();  
  76.             for (int i = 0; i < col; i++) {  
  77.                 newStatement.setString(i + 1, rowlist.get(i).toString());  
  78.             }  
  79.             newStatement.addBatch();  
  80.             if (curRow % 1000 == 0) {  
  81.                 newStatement.executeBatch();  
  82.                 conn.commit();  
  83.             }  
  84.         }  
  85.     }  
  86.       
  87.     private static Connection getNew_Conn() {  
  88.         Connection conn = null;  
  89.         Properties props = new Properties();  
  90.         FileInputStream fis = null;  
  91.   
  92.         try {  
  93.             fis = new FileInputStream("D:/database.properties");  
  94.             props.load(fis);  
  95.             DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());  
  96.             // String jdbcURLString =  
  97.             // "jdbc:oracle:thin:@192.168.0.28:1521:orcl";  
  98.             StringBuffer jdbcURLString = new StringBuffer();  
  99.             jdbcURLString.append("jdbc:oracle:thin:@");  
  100.             jdbcURLString.append(props.getProperty("host"));  
  101.             jdbcURLString.append(":");  
  102.             jdbcURLString.append(props.getProperty("port"));  
  103.             jdbcURLString.append(":");  
  104.             jdbcURLString.append(props.getProperty("database"));  
  105.             conn = DriverManager.getConnection(jdbcURLString.toString(), props  
  106.                     .getProperty("user"), props.getProperty("password"));  
  107.         } catch (Exception e) {  
  108.             e.printStackTrace();  
  109.         } finally {  
  110.             try {  
  111.                 fis.close();  
  112.             } catch (IOException e) {  
  113.                 e.printStackTrace();  
  114.             }  
  115.         }  
  116.         return conn;  
  117.     }  
  118.       
  119.     public int close() {  
  120.         try {  
  121.             newStatement.executeBatch();  
  122.             conn.commit();  
  123.             System.out.println("数据写入完毕");  
  124.             this.newStatement.close();  
  125.             this.statement.close();  
  126.             this.conn.close();  
  127.             return 1;  
  128.         } catch (SQLException e) {  
  129.             return 0;  
  130.         }  
  131.     }  
  132. }  

 继承类:XxlsPrint,作用:将数据输出到控制台

Java代码
  1. package com.gaosheng.util.examples.xls;  
  2.   
  3. import java.sql.SQLException;  
  4. import java.util.List;  
  5.   
  6. import com.gaosheng.util.xls.XxlsAbstract;  
  7.   
  8. public class XxlsPrint extends XxlsAbstract {  
  9.   
  10.     @Override  
  11.     public void optRows(int sheetIndex,int curRow, List<String> rowlist) throws SQLException {  
  12.         for (int i = 0; i < rowlist.size(); i++) {  
  13.             System.out.print("'" + rowlist.get(i) + "',");  
  14.         }  
  15.         System.out.println();  
  16.     }  
  17.   
  18.     public static void main(String[] args) throws Exception {  
  19.         XxlsPrint howto = new XxlsPrint();  
  20.         howto.processOneSheet("F:/new.xlsx",1);  
  21. //      howto.processAllSheets("F:/new.xlsx");  
  22.     }  
  23. }  

 源代码在附件中,还包含了说明文件、数据库配置文件、以及整合xls文件和xlsx文件读取的类:Xls2Do。

Java代码
  1.   

    小弟刚进公司,目前有一项任务要把客户数据迁移到数据库中,由于客户提供的数据都存储在excel中,有些文件数据量还很大,在usermodel模式下经常内存溢出,于是只能采用直接通过pl/sql往数据库复制或是用eventusermodel模式读取。直接复制倒是简单,但是速度太慢,一次复制的太多也会内存溢出,我没那耐心,没办法,只能用第二种办法了。在google上找,发现相关示例太少了,幸好在docjar找到了一个示例,自己又改了一下,把原来的例子改为抽象类,提供了一个 optRows() 方法来对行级数据进行操作。

 

     usermodel模式对excel操作前需要将文件全部转入内存,对较大文件来说内存开销很大。但是其使用简单。

     eventusermodel模式采用事件模型,对文件边读取边处理,内存消耗较低,效率高,因为不用等待文件全部装入内存。但使用较复杂。

补充:今天发现 读取2007的脚本存在存在一处问题,在遇到空单元格时会跳过该单元格,由于工作紧张没有时间去解决该问题,这里给出一个暂时的处理办法。打开文件,在开始菜单中选择"查找和选择","定位条件",选择"空值",确定,这时会找出所有的空单元格,直接按空格,然后Ctrl+enter,就会将所有空单元格填入一个空格,保存即可。

 

    下面展示的是excel2003及其之前版本的大文件读取方法。

 

抽象类 HxlsAbstract:

Java代码
  1. package com.gaosheng.util.xls;  
  2. import java.io.FileInputStream;  
  3. import java.io.FileNotFoundException;  
  4. import java.io.IOException;  
  5. import java.io.PrintStream;  
  6. import java.sql.SQLException;  
  7. import java.util.ArrayList;  
  8. import java.util.List;  
  9.   
  10. import org.apache.poi.hssf.eventusermodel.FormatTrackingHSSFListener;  
  11. import org.apache.poi.hssf.eventusermodel.HSSFEventFactory;  
  12. import org.apache.poi.hssf.eventusermodel.HSSFListener;  
  13. import org.apache.poi.hssf.eventusermodel.HSSFRequest;  
  14. import org.apache.poi.hssf.eventusermodel.MissingRecordAwareHSSFListener;  
  15. import org.apache.poi.hssf.eventusermodel.EventWorkbookBuilder.SheetRecordCollectingListener;  
  16. import org.apache.poi.hssf.eventusermodel.dummyrecord.LastCellOfRowDummyRecord;  
  17. import org.apache.poi.hssf.eventusermodel.dummyrecord.MissingCellDummyRecord;  
  18. import org.apache.poi.hssf.model.HSSFFormulaParser;  
  19. import org.apache.poi.hssf.record.BOFRecord;  
  20. import org.apache.poi.hssf.record.BlankRecord;  
  21. import org.apache.poi.hssf.record.BoolErrRecord;  
  22. import org.apache.poi.hssf.record.BoundSheetRecord;  
  23. import org.apache.poi.hssf.record.FormulaRecord;  
  24. import org.apache.poi.hssf.record.LabelRecord;  
  25. import org.apache.poi.hssf.record.LabelSSTRecord;  
  26. import org.apache.poi.hssf.record.NoteRecord;  
  27. import org.apache.poi.hssf.record.NumberRecord;  
  28. import org.apache.poi.hssf.record.RKRecord;  
  29. import org.apache.poi.hssf.record.Record;  
  30. import org.apache.poi.hssf.record.SSTRecord;  
  31. import org.apache.poi.hssf.record.StringRecord;  
  32. import org.apache.poi.hssf.usermodel.HSSFWorkbook;  
  33. import org.apache.poi.poifs.filesystem.POIFSFileSystem;  
  34.   
  35. public abstract class HxlsAbstract implements HSSFListener {  
  36.     private int minColumns;  
  37.     private POIFSFileSystem fs;  
  38.     private PrintStream output;  
  39.   
  40.     private int lastRowNumber;  
  41.     private int lastColumnNumber;  
  42.   
  43.     /** Should we output the formula, or the value it has? */  
  44.     private boolean outputFormulaValues = true;  
  45.   
  46.     /** For parsing Formulas */  
  47.     private SheetRecordCollectingListener workbookBuildingListener;  
  48.     private HSSFWorkbook stubWorkbook;  
  49.   
  50.     // Records we pick up as we process  
  51.     private SSTRecord sstRecord;  
  52.     private FormatTrackingHSSFListener formatListener;  
  53.   
  54.     /** So we known which sheet we're on */  
  55.     private int sheetIndex = -1;  
  56.     private BoundSheetRecord[] orderedBSRs;  
  57.     @SuppressWarnings("unchecked")  
  58.     private ArrayList boundSheetRecords = new ArrayList();  
  59.   
  60.     // For handling formulas with string results  
  61.     private int nextRow;  
  62.     private int nextColumn;  
  63.     private boolean outputNextStringRecord;  
  64.   
  65.     private int curRow;  
  66.     private List<String> rowlist;  
  67.     @SuppressWarnings"unused")  
  68.     private String sheetName;  
  69.   
  70.     public HxlsAbstract(POIFSFileSystem fs)  
  71.             throws SQLException {  
  72.         this.fs = fs;  
  73.         this.output = System.out;  
  74.         this.minColumns = -1;  
  75.         this.curRow = 0;  
  76.         this.rowlist = new ArrayList<String>();  
  77.     }  
  78.   
  79.     public HxlsAbstract(String filename) throws IOException,  
  80.             FileNotFoundException, SQLException {  
  81.         this(new POIFSFileSystem(new FileInputStream(filename)));  
  82.     }  
  83.       
  84.     //excel记录行操作方法,以行索引和行元素列表为参数,对一行元素进行操作,元素为String类型  
  85. //  public abstract void optRows(int curRow, List<String> rowlist) throws SQLException ;  
  86.       
  87.     //excel记录行操作方法,以sheet索引,行索引和行元素列表为参数,对sheet的一行元素进行操作,元素为String类型  
  88.     public abstract void optRows(int sheetIndex,int curRow, List<String> rowlist) throws SQLException;  
  89.       
  90.     /** 
  91.      * 遍历 excel 文件 
  92.      */  
  93.     public void process() throws IOException {  
  94.         MissingRecordAwareHSSFListener listener = new MissingRecordAwareHSSFListener(  
  95.                 this);  
  96.         formatListener = new FormatTrackingHSSFListener(listener);  
  97.   
  98.         HSSFEventFactory factory = new HSSFEventFactory();  
  99.         HSSFRequest request = new HSSFRequest();  
  100.   
  101.         if (outputFormulaValues) {  
  102.             request.addListenerForAllRecords(formatListener);  
  103.         } else {  
  104.             workbookBuildingListener = new SheetRecordCollectingListener(  
  105.                     formatListener);  
  106.             request.addListenerForAllRecords(workbookBuildingListener);  
  107.         }  
  108.   
  109.         factory.processWorkbookEvents(request, fs);  
  110.     }  
  111.       
  112.     /** 
  113.      * HSSFListener 监听方法,处理 Record 
  114.      */  
  115.     @SuppressWarnings("unchecked")  
  116.     public void processRecord(Record record) {  
  117.         int thisRow = -1;  
  118.         int thisColumn = -1;  
  119.         String thisStr = null;  
  120.         String value = null;  
  121.           
  122.         switch (record.getSid()) {  
  123.         case BoundSheetRecord.sid:  
  124.             boundSheetRecords.add(record);  
  125.             break;  
  126.         case BOFRecord.sid:  
  127.             BOFRecord br = (BOFRecord) record;  
  128.             if (br.getType() == BOFRecord.TYPE_WORKSHEET) {  
  129.                 // Create sub workbook if required  
  130.                 if (workbookBuildingListener != null && stubWorkbook == null) {  
  131.                     stubWorkbook = workbookBuildingListener  
  132.                             .getStubHSSFWorkbook();  
  133.                 }  
  134.   
  135.                 // Works by ordering the BSRs by the location of  
  136.                 // their BOFRecords, and then knowing that we  
  137.                 // process BOFRecords in byte offset order  
  138.                 sheetIndex++;  
  139.                 if (orderedBSRs == null) {  
  140.                     orderedBSRs = BoundSheetRecord  
  141.                             .orderByBofPosition(boundSheetRecords);  
  142.                 }  
  143.                 sheetName = orderedBSRs[sheetIndex].getSheetname();  
  144.             }  
  145.             break;  
  146.   
  147.         case SSTRecord.sid:  
  148.             sstRecord = (SSTRecord) record;  
  149.             break;  
  150.   
  151.         case BlankRecord.sid:  
  152.             BlankRecord brec = (BlankRecord) record;  
  153.   
  154.             thisRow = brec.getRow();  
  155.             thisColumn = brec.getColumn();  
  156.             thisStr = "";  
  157.             break;  
  158.         case BoolErrRecord.sid:  
  159.             BoolErrRecord berec = (BoolErrRecord) record;  
  160.   
  161.             thisRow = berec.getRow();  
  162.             thisColumn = berec.getColumn();  
  163.             thisStr = "";  
  164.             break;  
  165.   
  166.         case FormulaRecord.sid:  
  167.             FormulaRecord frec = (FormulaRecord) record;  
  168.   
  169.             thisRow = frec.getRow();  
  170.             thisColumn = frec.getColumn();  
  171.   
  172.             if (outputFormulaValues) {  
  173.                 if (Double.isNaN(frec.getValue())) {  
  174.                     // Formula result is a string  
  175.                     // This is stored in the next record  
  176.                     outputNextStringRecord = true;  
  177.                     nextRow = frec.getRow();  
  178.                     nextColumn = frec.getColumn();  
  179.                 } else {  
  180.                     thisStr = formatListener.formatNumberDateCell(frec);  
  181.                 }  
  182.             } else {  
  183.                 thisStr = '"' + HSSFFormulaParser.toFormulaString(stubWorkbook,  
  184.                         frec.getParsedExpression()) + '"';  
  185.             }  
  186.             break;  
  187.         case StringRecord.sid:  
  188.             if (outputNextStringRecord) {  
  189.                 // String for formula  
  190.                 StringRecord srec = (StringRecord) record;  
  191.                 thisStr = srec.getString();  
  192.                 thisRow = nextRow;  
  193.                 thisColumn = nextColumn;  
  194.                 outputNextStringRecord = false;  
  195.             }  
  196.             break;  
  197.   
  198.         case LabelRecord.sid:  
  199.             LabelRecord lrec = (LabelRecord) record;  
  200.   
  201.             curRow = thisRow = lrec.getRow();  
  202.             thisColumn = lrec.getColumn();  
  203.             value = lrec.getValue().trim();  
  204.             value = value.equals("")?" ":value;  
  205.             this.rowlist.add(thisColumn, value);  
  206.             break;  
  207.         case LabelSSTRecord.sid:  
  208.             LabelSSTRecord lsrec = (LabelSSTRecord) record;  
  209.   
  210.             curRow = thisRow = lsrec.getRow();  
  211.             thisColumn = lsrec.getColumn();  
  212.             if (sstRecord == null) {  
  213.                 rowlist.add(thisColumn, " ");  
  214.             } else {  
  215.                 value =  sstRecord  
  216.                 .getString(lsrec.getSSTIndex()).toString().trim();  
  217.                 value = value.equals("")?" ":value;  
  218.                 rowlist.add(thisColumn,value);  
  219.             }  
  220.             break;  
  221.         case NoteRecord.sid:  
  222.             NoteRecord nrec = (NoteRecord) record;  
  223.   
  224.             thisRow = nrec.getRow();  
  225.             thisColumn = nrec.getColumn();  
  226.             // TODO: Find object to match nrec.getShapeId()  
  227.             thisStr = '"' + "(TODO)" + '"';  
  228.             break;  
  229.         case NumberRecord.sid:  
  230.             NumberRecord numrec = (NumberRecord) record;  
  231.   
  232.             curRow = thisRow = numrec.getRow();  
  233.             thisColumn = numrec.getColumn();  
  234.             value = formatListener.formatNumberDateCell(numrec).trim();  
  235.             value = value.equals("")?" ":value;  
  236.             // Format  
  237.             rowlist.add(thisColumn, value);  
  238.             break;  
  239.         case RKRecord.sid:  
  240.             RKRecord rkrec = (RKRecord) record;  
  241.   
  242.             thisRow = rkrec.getRow();  
  243.             thisColumn = rkrec.getColumn();  
  244.             thisStr = '"' + "(TODO)" + '"';  
  245.             break;  
  246.         default:  
  247.             break;  
  248.         }  
  249.   
  250.         // 遇到新行的操作  
  251.         if (thisRow != -1 && thisRow != lastRowNumber) {  
  252.             lastColumnNumber = -1;  
  253.         }  
  254.   
  255.         // 空值的操作  
  256.         if (record instanceof MissingCellDummyRecord) {  
  257.             MissingCellDummyRecord mc = (MissingCellDummyRecord) record;  
  258.             curRow = thisRow = mc.getRow();  
  259.             thisColumn = mc.getColumn();  
  260.             rowlist.add(thisColumn," ");  
  261.         }  
  262.   
  263.         // 如果遇到能打印的东西,在这里打印  
  264.         if (thisStr != null) {  
  265.             if (thisColumn > 0) {  
  266.                 output.print(',');  
  267.             }  
  268.             output.print(thisStr);  
  269.         }  
  270.   
  271.         // 更新行和列的值  
  272.         if (thisRow > -1)  
  273.             lastRowNumber = thisRow;  
  274.         if (thisColumn > -1)  
  275.             lastColumnNumber = thisColumn;  
  276.   
  277.         // 行结束时的操作  
  278.         if (record instanceof LastCellOfRowDummyRecord) {  
  279.             if (minColumns > 0) {  
  280.                 // 列值重新置空  
  281.                 if (lastColumnNumber == -1) {  
  282.                     lastColumnNumber = 0;  
  283.                 }  
  284.             }  
  285.             // 行结束时, 调用 optRows() 方法  
  286.             lastColumnNumber = -1;  
  287.             try {  
  288.                 optRows(sheetIndex,curRow, rowlist);  
  289.             } catch (SQLException e) {  
  290.                 e.printStackTrace();  
  291.             }  
  292.             rowlist.clear();  
  293.         }  
  294.     }  
  295. }  

 

继承类: HxlsBig,作用:将excel中数据转储到数据库临时表中,实现optRows方法

 

Java代码
  1. package com.gaosheng.util.examples.xls;  
  2. import java.io.FileInputStream;  
  3. import java.io.FileNotFoundException;  
  4. import java.io.IOException;  
  5. import java.io.PrintStream;  
  6. import java.sql.Connection;  
  7. import java.sql.DriverManager;  
  8. import java.sql.PreparedStatement;  
  9. import java.sql.SQLException;  
  10. import java.sql.Statement;  
  11. import java.util.List;  
  12. import java.util.Properties;  
  13.   
  14. import org.apache.poi.poifs.filesystem.POIFSFileSystem;  
  15.   
  16. import com.gaosheng.util.xls.HxlsAbstract;  
  17.   
  18.   
  19. public class HxlsBig extends HxlsAbstract{  
  20.       
  21.     public static void main(String[] args) throws Exception {  
  22.         // XLS2CSVmra xls2csv = new XLS2CSVmra(args[0], minColumns);  
  23.         HxlsBig xls2csv = new HxlsBig("E:/up.xls","hxls_temp");  
  24.         xls2csv.process();  
  25.         xls2csv.close();  
  26.     }  
  27.       
  28.     public HxlsBig(POIFSFileSystem fs, PrintStream output,String tableName)  
  29.             throws SQLException {  
  30.         super(fs);  
  31.         this.conn = getNew_Conn();  
  32.         this.statement = conn.createStatement();  
  33.         this.tableName = tableName;  
  34.     }  
  35.   
  36.     public HxlsBig(String filename,String tableName) throws IOException,  
  37.             FileNotFoundException, SQLException {  
  38.         this(new POIFSFileSystem(new FileInputStream(filename)), System.out,tableName);  
  39.     }  
  40.   
  41.     private Connection conn = null;  
  42.     private Statement statement = null;  
  43.     private PreparedStatement newStatement = null;  
  44.   
  45.     private String tableName = "temp_table";  
  46.     private boolean create = true;  
  47. //  private int sheetIndex = 0;  
  48.       
  49.     public void optRows(int sheetIndex,int curRow, List<String> rowlist) throws SQLException {  
  50.         if (curRow == 0 && sheetIndex == 0 ) {  
  51.             StringBuffer preSql = new StringBuffer("insert into " + tableName  
  52.                     + " values(");  
  53.             StringBuffer table = new StringBuffer("create table " + tableName  
  54.                     + "(");  
  55.             int c = rowlist.size();  
  56.             for (int i = 0; i < c; i++) {  
  57.                 preSql.append("?,");  
  58.                 table.append(rowlist.get(i));  
  59.                 table.append("  varchar2(100) ,");  
  60.             }  
  61.   
  62.             table.deleteCharAt(table.length() - 1);  
  63.             preSql.deleteCharAt(preSql.length() - 1);  
  64.             table.append(")");  
  65.             preSql.append(")");  
  66.             if (create) {  
  67.                 statement = conn.createStatement();  
  68.                 try{  
  69.                     statement.execute("drop table "+tableName);  
  70.                 }catch(Exception e){  
  71.                       
  72.                 }finally{  
  73.                     System.out.println("表 "+tableName+" 删除成功");  
  74.                 }  
  75.                 if (!statement.execute(table.toString())) {  
  76.                     System.out.println("创建表 "+tableName+" 成功");  
  77.                     // return;  
  78.                 } else {  
  79.                     System.out.println("创建表 "+tableName+" 失败");  
  80.                     return;  
  81.                 }  
  82.             }  
  83.             conn.setAutoCommit(false);  
  84.             newStatement = conn.prepareStatement(preSql.toString());  
  85.   
  86.         }else if(curRow > 0) {  
  87.             // 一般行  
  88.             int col = rowlist.size();  
  89.             for (int i = 0; i < col; i++) {  
  90.                 newStatement.setString(i + 1, rowlist.get(i).toString());  
  91.             }  
  92.             newStatement.addBatch();  
  93.             if (curRow % 1000 == 0) {  
  94.                 newStatement.executeBatch();  
  95.                 conn.commit();  
  96.             }  
  97.         }  
  98.     }  
  99.       
  100.     private static Connection getNew_Conn() {  
  101.         Connection conn = null;  
  102.         Properties props = new Properties();  
  103.         FileInputStream fis = null;  
  104.   
  105.         try {  
  106.             fis = new FileInputStream("D:/database.properties");  
  107.             props.load(fis);  
  108.             DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());  
  109.             StringBuffer jdbcURLString = new StringBuffer();  
  110.             jdbcURLString.append("jdbc:oracle:thin:@");  
  111.             jdbcURLString.append(props.getProperty("host"));  
  112.             jdbcURLString.append(":");  
  113.             jdbcURLString.append(props.getProperty("port"));  
  114.             jdbcURLString.append(":");  
  115.             jdbcURLString.append(props.getProperty("database"));  
  116.             conn = DriverManager.getConnection(jdbcURLString.toString(), props  
  117.                     .getProperty("user"), props.getProperty("password"));  
  118.         } catch (Exception e) {  
  119.             e.printStackTrace();  
  120.         } finally {  
  121.             try {  
  122.                 fis.close();  
  123.             } catch (IOException e) {  
  124.                 e.printStackTrace();  
  125.             }  
  126.         }  
  127.         return conn;  
  128.     }  
  129.       
  130.     public int close() {  
  131.         try {  
  132.             newStatement.executeBatch();  
  133.             conn.commit();  
  134.             System.out.println("数据写入完毕");  
  135.             this.newStatement.close();  
  136.             this.statement.close();  
  137.             this.conn.close();  
  138.             return 1;  
  139.         } catch (SQLException e) {  
  140.             return 0;  
  141.         }  
  142.     }  
  143.   
  144. }  

 

继承类 : HxlsPrint,作用:将excel中数据输出到控制台,实现optRows方法

 

Java代码
  1. package com.gaosheng.util.examples.xls;  
  2. import java.io.FileNotFoundException;  
  3. import java.io.IOException;  
  4. import java.sql.SQLException;  
  5. import java.util.List;  
  6.   
  7. import com.gaosheng.util.xls.HxlsAbstract;  
  8.   
  9.   
  10. public class HxlsPrint extends HxlsAbstract{  
  11.   
  12.     public HxlsPrint(String filename) throws IOException,  
  13.             FileNotFoundException, SQLException {  
  14.         super(filename);  
  15.     }  
  16.   
  17.     @Override  
  18.     public void optRows(int sheetIndex,int curRow, List<String> rowlist) throws SQLException {  
  19.         for (int i = 0 ;i< rowlist.size();i++){  
  20.             System.out.print("'"+rowlist.get(i)+"',");  
  21.         }  
  22.         System.out.println();  
  23.     }  
  24.       
  25.     public static void main(String[] args){  
  26.         HxlsPrint xls2csv;  
  27.         try {  
  28.             xls2csv = new HxlsPrint("E:/new.xls");  
  29.             xls2csv.process();  
  30.         } catch (FileNotFoundException e) {  
  31.             e.printStackTrace();  
  32.         } catch (IOException e) {  
  33.             e.printStackTrace();  
  34.         } catch (SQLException e) {  
  35.             e.printStackTrace();  
  36.         }  
  37.           
  38.     }  
  39. }  

 

excel2007的大数据量读取见下篇,附件中包含了2003等较早版本的xls文件的示例,也包含了2007版的示例

 

目前公司接的项目都有很多功能的数据都要依靠excel导入,因此对excel中数据的验证必不可少。

先来看一下目前存在的问题:

一:在每处导入的程序中都会包括excel读取、数据验证、错误数据的导出或错误的输出,每次都是拷贝、粘帖、修改,本来不同的地方只有验证部分,但由于格式、验证的不同,在修改过程中还要对excel的读取、错误的导出进行修改、调试,造成工作效率的降低和时间的浪费。

二:由于人员更替频繁,每个人的风格都不一样,对于错误的显示和输出都不一样,客户看到的结果是每处导入的地方返回的错误结果也不一样,有的只是提醒一句成功、失败,有的则会把错误的记录导出excel供客户下载修改。客户对此也有很多抱怨。

解决思路:

在excel导入中我们关心的(也是唯一不同的)是数据的验证、保存,对于读取、错误记录导出并不关心,那就该把这两部分分离出来,这样的好处有:1.导入时不再关心excel的读取和错误信息的导出,编码及调试时不再为这部分付出时间和精力,加快开发效率。2.降低耦合度,目前对excel的操作使用的是jxl,如果以后改为poi那只需要需改excel操作的实现即可。3.统一,所有的导入使用相同的excel操作实现,如果excel读取操作有bug则只需修改一处(写此代码的起因就是一个同事出现的一个bug引起的),而且对错误记录的输出也有统一的输出。

解决办法:

限于本人的表达能力,要想讲清楚太费时间和篇幅了,在这里就直接上代码了

首先是抽象类 ImportDataMultiSheet,包括excel读取、错误记录导出的实现,支持多sheet及合并单元格的处理

 

Java代码
  1. import java.io.File;  
  2. import java.io.IOException;  
  3. import java.lang.reflect.Method;  
  4. import java.text.DateFormat;  
  5. import java.text.SimpleDateFormat;  
  6. import java.util.ArrayList;  
  7. import java.util.HashMap;  
  8. import java.util.List;  
  9. import java.util.Locale;  
  10. import java.util.Map;  
  11. import java.util.TimeZone;  
  12.   
  13. import org.gaosheng.util.exception.EntityException;  
  14.   
  15. import jxl.Cell;  
  16. import jxl.CellType;  
  17. import jxl.DateCell;  
  18. import jxl.NumberCell;  
  19. import jxl.Range;  
  20. import jxl.Sheet;  
  21. import jxl.Workbook;  
  22. import jxl.format.Colour;  
  23. import jxl.write.Label;  
  24. import jxl.write.WritableCellFormat;  
  25. import jxl.write.WritableFont;  
  26. import jxl.write.WritableSheet;  
  27. import jxl.write.WritableWorkbook;  
  28.   
  29. /** 
  30.  * jxl导入excel类,继承类实现验证方法 
  31.  *  
  32.  * @author gaosheng 
  33.  *  
  34.  */  
  35. public abstract class ImportDataMultiSheet {  
  36.   
  37.     private int startRow = 1;  
  38.     private int startColumn = 0;  
  39.     private int minRows = 1;  
  40.     private int minColumns = 1;  
  41.     private int maxRows = -1;  
  42.     private int maxColumns = -1;  
  43.     private Map<Integer, Method> methodMap;  
  44.     private Map<Integer, List<String>> holdColumns;  
  45.     private List<String>[] titiles ;  
  46.     private List<MeregRange> meregRangeList ;  
  47.     private Cell curCell;  
  48.     private Cell[] curRowCells;  
  49.     private int successcount = 0;  
  50.       
  51.     private String[] columnMethods = null;  
  52.     private int[] needHoldColumns = null;  
  53.     private File importExcel;  
  54.     private File errorExcel;  
  55.     private boolean hasError = false;  
  56.     private List<String> errors = new ArrayList<String>();  
  57.   
  58.     /** 
  59.      * 启动导入 
  60.      *  
  61.      * @return boolean 
  62.      * @throws SecurityException 
  63.      * @throws NoSuchMethodException 
  64.      * @throws EntityException 
  65.      */  
  66.     public boolean execute() throws SecurityException, NoSuchMethodException,  
  67.             EntityException {  
  68.         setMethodMap();  
  69.         setHoldColumns();  
  70.         Workbook work = null;  
  71.         try {  
  72.             work = Workbook.getWorkbook(importExcel);  
  73.         } catch (Exception e) {  
  74.             throw new EntityException("Excel表格读取异常!批量导入失败!<br/>");  
  75.         }  
  76.   
  77.         //数据总行数  
  78.         int totalRows = 0;  
  79.         Sheet sheet = null;  
  80.         WritableWorkbook writew = null;  
  81.         WritableSheet writes = null;  
  82.           
  83.         int sheet_num = work.getNumberOfSheets();  
  84.         // 全局验证  
  85.         if (!this.validGlobal(work.getSheets())) {  
  86.             throw new EntityException("导入文件格式错误");  
  87.         }  
  88.         try {  
  89.             for (int sheet_index = 0; sheet_index < sheet_num ;sheet_index++) {  
  90.                 sheet = work.getSheet(sheet_index);  
  91.                 meregRangeList = new ArrayList<MeregRange>();  
  92.                 int columns = sheet.getColumns();  
  93.                 int rows = sheet.getRows();  
  94.                 totalRows += rows;  
  95.   
  96.                 for (Range range : sheet.getMergedCells()) {  
  97.                     Cell topleft = range.getTopLeft();  
  98.                     Cell bottomRight = range.getBottomRight();  
  99.                     meregRangeList.add(new MeregRange(topleft.getRow(),topleft.getColumn(),bottomRight.getRow(),bottomRight.getColumn(),getCellValue(topleft)));  
  100.                 }  
  101.                   
  102.                 writew = Workbook.createWorkbook(errorExcel);  
  103.                 writes = writew.createSheet("ErrorReport"0);  
  104.                 Label label;  
  105.                 WritableCellFormat wcf;  
  106.                 titiles = new List[startRow];  
  107.                 List<String>  list = null;  
  108.                 for (int i = 0; i < startRow; i++) {  
  109.                     list = new ArrayList<String>();  
  110.                     for (int j = 0; j < columns; j++) {  
  111.                         label = new Label(j, i, getCellValue(sheet.getCell(j, i)));  
  112.                         writes.addCell(label);  
  113.                         list.add(getValue(sheet.getCell(j, i)));  
  114.                     }  
  115.                     titiles[i] = list;  
  116.                 }  
  117.                 label = new Label(columns, startRow - 1"错误详细");  
  118.                 WritableFont wf0 = new WritableFont(WritableFont.TIMES, 12);  
  119.                 wcf = new WritableCellFormat(wf0);  
  120.                 label.setCellFormat(wcf);  
  121.                 writes.addCell(label);  
  122.   
  123.                 int wi = startRow;  
  124.                 // -------------------------  
  125.                 StringBuffer info_temp = null;  
  126.                 String result = null;  
  127.                 Method method = null;  
  128.                 for (int i = startRow; i < rows; i++) {  
  129.                     curRowCells = sheet.getRow(i);  
  130.                     if (curRowCells == null || curRowCells.length < minColumns) {  
  131.                         continue;  
  132.                     }  
  133.                     boolean[] wj = new boolean[columns];  
  134.                     info_temp = new StringBuffer();  
  135.                     for (int j = startColumn; j < columns; j++) {  
  136.                         curCell = sheet.getCell(j, i);  
  137.                           
  138. //                      System.out.print(String.format("%-30.30s", this.getValue(curCell))+"  ");  
  139.                         result = everyCell();  
  140.                         if (result != null) {  
  141.                             method = methodMap.get(j);  
  142.                             if (method == null) {  
  143.                                 continue;  
  144.                             }  
  145.                             result = (String) method.invoke(thisnull);  
  146.                         }  
  147.                         if (result != null) {  
  148.                             info_temp.append(result);  
  149.                             info_temp.append(" ");  
  150.                             wj[j] = true;  
  151.                         }  
  152.                         if (holdColumns.get(j) != null) {  
  153.                             holdColumns.get(j).add(this.getValue(curCell));  
  154.                         }  
  155.                         if (info_temp.length() > 0) {  
  156.                             errors.add("sheet "+sheet.getName()+" 中第 " + (i + 1) + " 行 :"  
  157.                                     + info_temp.toString());  
  158.                         }  
  159.                     }  
  160. //                  System.out.println();  
  161.                     if (info_temp.length() > 1) {  
  162.                         for (int ii = startColumn; ii < columns; ii++) {  
  163.                             Cell c_temp = sheet.getCell(ii, i);  
  164.                             label = new Label(ii, wi, c_temp.getContents().trim());  
  165.                             wcf = new WritableCellFormat();  
  166.                             if (wj[ii])  
  167.                                 wcf.setBackground(Colour.RED);  
  168.                             label.setCellFormat(wcf);  
  169.                             writes.addCell(label);  
  170.                         }  
  171.                         label = new Label(columns, wi, info_temp.toString());  
  172.                         WritableFont wf = new WritableFont(WritableFont.TIMES,  
  173.                                 12);  
  174.                         wf.setColour(Colour.RED);  
  175.                         wcf = new WritableCellFormat(wf);  
  176.                         label.setCellFormat(wcf);  
  177.                         writes.addCell(label);  
  178.                         wi++;  
  179.                     } else {  
  180.                         this.save();  
  181.                         successcount ++;  
  182.                     }  
  183.                 }  
  184.             }  
  185.         } catch (Exception e) {  
  186.             e.printStackTrace();  
  187.             this.hasError = true;  
  188.             errors.add("sheet "+sheet.getName()+" 第"+this.curCell.getRow() +" 行 第 "this.curCell.getColumn()+" 列 :"+this.getCurCell().getContents()+" 遇到错误");  
  189.             return false;  
  190.         } finally {  
  191.             try {  
  192.                 writew.write();  
  193.                 writew.close();  
  194.                 work.close();  
  195.             } catch (IOException e) {  
  196.                 e.printStackTrace();  
  197.             }  
  198.         }  
  199.         if (successcount < totalRows - sheet_num*startRow) {  
  200.             this.hasError = true;  
  201.         }  
  202.         return true;  
  203.     }  
  204.   
  205.     /** 
  206.      * 全局验证,验证对行数和列数的要求 
  207.      *  
  208.      * @return 
  209.      */  
  210.     public boolean validGlobal(Sheet[] sheets) {  
  211.         for (int i = 0; i < sheets.length; i++) {  
  212.             if (minRows != -1 && sheets[i].getRows() < minRows) {  
  213.                 return false;  
  214.             } else if (minColumns != -1 && sheets[i].getColumns() < minColumns) {  
  215.                 return false;  
  216.             } else if (maxRows != -1 && sheets[i].getRows() > maxRows) {  
  217.                 return false;  
  218.             } else if (maxColumns != -1 && sheets[i].getColumns() > maxColumns) {  
  219.                 return false;  
  220.             }  
  221.         }  
  222.         return true;  
  223.     }  
  224.   
  225.     /** 
  226.      * 一行数据验证成功后保存 
  227.      * @return boolean 
  228.      */  
  229.     public abstract boolean save();  
  230.       
  231.     /** 
  232.      * 对每一个单元格进行的操作 
  233.      * @return boolean 
  234.      */  
  235.     public abstract String everyCell();  
  236.       
  237.     /** 
  238.      * 初始化存储验证列方法的Map 
  239.      *  
  240.      * @throws SecurityException 
  241.      * @throws NoSuchMethodException 
  242.      */  
  243.     @SuppressWarnings("unchecked")  
  244.     private void setMethodMap() throws SecurityException, NoSuchMethodException {  
  245.         methodMap = new HashMap<Integer, Method>();  
  246.         if (columnMethods == null) {  
  247.             Method[] methods = this.getClass().getMethods();  
  248.             for (int i = 0; i < methods.length; i++) {  
  249.                 if (methods[i].getName().startsWith("validColumn_")) {  
  250.                     String column = methods[i].getName().substring(  
  251.                             methods[i].getName().indexOf("_") + 1);  
  252.                     try {  
  253.                         methodMap.put(Integer.parseInt(column), methods[i]);  
  254.                     } catch (Exception e) {  
  255.                         throw new NumberFormatException("默认列明必须为数字");  
  256.                     }  
  257.                 }  
  258.             }  
  259.         } else {  
  260.             Class<ImportDataMultiSheet> class1 = (Class<ImportDataMultiSheet>) this.getClass();  
  261.             for (int i = 0; i < columnMethods.length; i++) {  
  262.                 methodMap.put(i, class1.getMethod(columnMethods[i], null));  
  263.             }  
  264.         }  
  265.     }  
  266.   
  267.     /** 
  268.      * 初始化存储保留列的Map,保留列用于验证某些列值时需引用其他列的情况 
  269.      */  
  270.     private void setHoldColumns() {  
  271.         holdColumns = new HashMap<Integer, List<String>>();  
  272.         if (needHoldColumns == null) {  
  273.             return;  
  274.         }  
  275.         for (int i = 0; i < needHoldColumns.length; i++) {  
  276.             holdColumns.put(needHoldColumns[i], new ArrayList<String>());  
  277.         }  
  278.     }  
  279.   
  280.     /** 
  281.      * 获得给定单元格的实际值,对于时间会返回 'yyyy-MM-dd HH:mm:ss' 格式的字符串 
  282.      *  
  283.      * @param cell 
  284.      * @return String 
  285.      */  
  286.     public static String getCellValue(Cell cell) {  
  287.         if (cell.getType().equals(CellType.NUMBER)) {  
  288.             return Double.toString(((NumberCell) cell).getValue());  
  289.         } else if (cell.getType().equals(CellType.DATE)) {  
  290.             TimeZone gmt = TimeZone.getTimeZone("GMT");  
  291.             DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss",  
  292.                     Locale.getDefault());  
  293.             dateFormat.setTimeZone(gmt);  
  294.             return dateFormat.format(((DateCell) cell).getDate());  
  295.         } else if (cell.getType().equals(CellType.EMPTY)) {  
  296.             return null;  
  297.         } else {  
  298.             return cell.getContents().trim();  
  299.         }  
  300.     }  
  301.   
  302.     public String getValue(Cell cell){  
  303.         String value = getCellValue(cell);  
  304.         if (value == null || getCellValue(cell).equals("")) {  
  305.             for(MeregRange meregRange:meregRangeList){  
  306.                 if (meregRange.isInRange(cell.getRow(), cell.getColumn())) {  
  307.                     return meregRange.getValue();  
  308.                 }  
  309.             }  
  310.             return value;  
  311.         }else {  
  312.             return value;  
  313.         }  
  314.     }  
  315.       
  316.     /** 
  317.      * 防止空指针 
  318.      *  
  319.      * @param object 
  320.      * @return String 
  321.      */  
  322.     public String fixNull(Object object) {  
  323.         return object == null ? "" : object.toString();  
  324.     }  
  325.   
  326.     public int getMinRows() {  
  327.         return minRows;  
  328.     }  
  329.   
  330.     public void setMinRows(int minRows) {  
  331.         this.minRows = minRows;  
  332.     }  
  333.   
  334.     public int getMinColumns() {  
  335.         return minColumns;  
  336.     }  
  337.   
  338.     public void setMinColumns(int minColumns) {  
  339.         this.minColumns = minColumns;  
  340.     }  
  341.   
  342.     public int getMaxRows() {  
  343.         return maxRows;  
  344.     }  
  345.   
  346.     public void setMaxRows(int maxRows) {  
  347.         this.maxRows = maxRows;  
  348.     }  
  349.   
  350.     public int getMaxColumns() {  
  351.         return maxColumns;  
  352.     }  
  353.   
  354.     public void setMaxColumns(int maxColumns) {  
  355.         this.maxColumns = maxColumns;  
  356.     }  
  357.   
  358.     public String[] getColumnMethods() {  
  359.         return columnMethods;  
  360.     }  
  361.   
  362.     public void setColumnMethods(String[] columnMethods) {  
  363.         this.columnMethods = columnMethods;  
  364.     }  
  365.   
  366.     public File getImportExcel() {  
  367.         return importExcel;  
  368.     }  
  369.   
  370.     public void setImportExcel(File importExcel) {  
  371.         this.importExcel = importExcel;  
  372.     }  
  373.   
  374.     public File getErrorExcel() {  
  375.         return errorExcel;  
  376.     }  
  377.   
  378.     public void setErrorExcel(File errorExcel) {  
  379.         this.errorExcel = errorExcel;  
  380.     }  
  381.   
  382.     public boolean isHasError() {  
  383.         return hasError;  
  384.     }  
  385.   
  386.     public int[] getNeedHoldColumns() {  
  387.         return needHoldColumns;  
  388.     }  
  389.   
  390.     public void setNeedHoldColumns(int[] needHoldColumns) {  
  391.         this.needHoldColumns = needHoldColumns;  
  392.     }  
  393.   
  394.     public Map<Integer, List<String>> getHoldColumns() {  
  395.         return holdColumns;  
  396.     }  
  397.   
  398.     public int getStartRow() {  
  399.         return startRow;  
  400.     }  
  401.   
  402.     public void setStartRow(int startRow) {  
  403.         this.startRow = startRow;  
  404.     }  
  405.   
  406.     public int getStartColumn() {  
  407.         return startColumn;  
  408.     }  
  409.   
  410.     public void setStartColumn(int startColumn) {  
  411.         this.startColumn = startColumn;  
  412.     }  
  413.   
  414.     public Cell getCurCell() {  
  415.         return curCell;  
  416.     }  
  417.   
  418.     public List<String> getErrors() {  
  419.         return errors;  
  420.     }  
  421.   
  422.     public Cell[] getCurRowCells() {  
  423.         return curRowCells;  
  424.     }  
  425.   
  426.     public List<String>[] getTitiles() {  
  427.         return titiles;  
  428.     }  
  429.   
  430.     public int getSuccesscount() {  
  431.         return successcount;  
  432.     }  
  433.   
  434. }  

 

 下面是一个实现类的范例:

 

 

Java代码
  1. import java.io.File;  
  2. import java.util.List;  
  3.   
  4. import jxl.Cell;  
  5.   
  6. import org.gaosheng.util.exception.EntityException;  
  7. import org.gaosheng.util.xls.ImportDataMultiSheet;  
  8.   
  9. public class ImportDatemultiImp extends ImportDataMultiSheet {  
  10.   
  11.     public static void main(String[] args) throws SecurityException, NoSuchMethodException, EntityException {  
  12.         File importFile = new File("F:/test.xls");  
  13.         File errorFile = new File("F:/error.xls");  
  14.         ImportDatemultiImp importDateImp = new ImportDatemultiImp();  
  15.         importDateImp.setImportExcel(importFile);  
  16.         importDateImp.setErrorExcel(errorFile);  
  17.         importDateImp.setStartRow(1);  
  18.         importDateImp.execute();  
  19.         importDateImp.getErrorExcel();  
  20.         for (String error : importDateImp.getErrors()) {  
  21.             System.out.println(error);  
  22.         }  
  23.     }  
  24.   
  25.     //对每一个单元格的执行的统一操作,返回值为错误信息,没有错误则返回null  
  26.     public String everyCell() {  
  27.         Cell cell = this.getCurCell();  
  28.         List<String>  semList = this.getTitiles()[2];  
  29.         List<String> courseList = this.getTitiles()[3];  
  30.         if (cell.getRow() > 3 && cell.getColumn() > 3) {  
  31.             String cellvalue = this.getValue(cell);  
  32.             String course_name = courseList.get(cell.getColumn());  
  33.             String reg_no = this.getValue(this.getCurRowCells()[1]);   
  34.             String stuname = this.getValue(this.getCurRowCells()[2]);  
  35.             if (cellvalue != null && !cellvalue.equals("") && course_name !=null && !course_name.equals("") && reg_no != null && !reg_no.equals("")) {  
  36.   
  37.             }else {  
  38.                 return "无效成绩";  
  39.             }  
  40.         }  
  41.         return null;  
  42.     }  
  43.   
  44.     //定义每一列的验证,默认方法名是validColumn_+列索引,也可以用setColumnMethods(String[] columnMethods)指定列的验证方法 返回值为错误信息,没有错误则返回null  
  45.     public String validColumn_1(){  
  46.         if (!this.getCurCell().getContents().equals("name")) {  
  47.             return "姓名错误";  
  48.         }  
  49.         return null;  
  50.     }  
  51.       
  52.     public String validColumn_2(){  
  53.         if (!this.getCurCell().getContents().equals("passwd")) {  
  54.             return "密码错误";  
  55.         }  
  56.         return null;  
  57.     }  
  58.   
  59.     public String validColumn_3(){  
  60.       
  61.         return null;  
  62.     }  
  63.   
  64.     //验证成功后保存记录  
  65.     public boolean save() {  
  66.         return false;  
  67.     }  
  68. }  
 
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值