java解析获取Excel中的数据--同时兼容2003及2007

java解析Excel(兼容2003及2007)


刚开始从网上找了个例子使用new HSSFWorkbook(new FileInputStream(excelFile))来读取Workbook,
对Excel2003以前(包括2003)的版本没有问题,但读取Excel2007时发生如下异常:
org.apache.poi.poifs.filesystem.OfficeXmlFileException: The supplied data appears to be in the Office 2007+ XML. You are calling the part of POI that deals with OLE2 Office Documents. You need to call a different part of POI to process this data (eg XSSF instead of HSSF)

        该错误意思是说,文件中的数据是用Office2007+XML保存的,而现在却调用OLE2 Office文档处理,应该使用POI不同的部分来处理这些数据,比如使用XSSF来代替HSSF。

        于是按提示使用XSSF代替HSSF,用new XSSFWorkbook(excelFile)来读取Workbook,对Excel2007没有问题了,可是在读取Excel2003以前(包括2003)的版本时却发生了如下新异常:
org.apache.poi.openxml4j.exceptions.InvalidOperationException: Can't open the specified file: '*.xls'
        该错误是说,操作无效,不能打开指定的xls文件。

        到网上查了下,原来是XSSF不能读取Excel2003以前(包括2003)的版本,这样的话,就需要在读取前判断文件是2003前的版本还是2007的版本,然后对应调用HSSF或XSSF来读取。
        这种做法比较麻烦,看了下API,发现XSSF和HSSF虽然在不同的包里,但却引用了同一接口Workbook,于是想到了这样的读取方法:
        Workbook book = null;
        try {
            book = new XSSFWorkbook(excelFile);
        } catch (Exception ex) {
            book = new HSSFWorkbook(new FileInputStream(excelFile));
        }
        
本认为程序应该没错了吧,但一运行还是报错(当时用得是poi3.6的zip包):

java.lang.ClassNotFoundException: org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheet

网上搜了下,是少poi-ooxml-schemas-xxx.jar包,根据提示在Apache网站上(http://labs.renren.com/apache-mirror//poi/release/bin/)下载了3.7的zip文件(poi-bin-3.7-20101029.zip),解压后将poi相关的包和xml相关的包都放上去。

在各版本的Excel中测试,没有发生异常,问题解决。

下面是POI的API网址,不过是英文的:
POI API Documentation
http://poi.apache.org/apidocs/index.html

 

   转入正题:以下是代码,代码也是从别人的代码拿过来的,其中修改了部分

  1. package com.execl;  
  2.   
  3. import java.io.File;  
  4.   
  5. import java.io.FileInputStream;  
  6.   
  7. import java.io.IOException;  
  8.   
  9. import java.io.InputStream;  
  10.   
  11. import java.util.ArrayList;  
  12.   
  13. import java.util.List;  
  14.   
  15. import org.apache.poi.hssf.usermodel.HSSFCell;  
  16. import org.apache.poi.hssf.usermodel.HSSFWorkbook;  
  17.   
  18. import org.apache.poi.ss.usermodel.Cell;  
  19.   
  20. import org.apache.poi.ss.usermodel.Row;  
  21.   
  22. import org.apache.poi.ss.usermodel.Sheet;  
  23.   
  24. import org.apache.poi.ss.usermodel.Workbook;  
  25.   
  26. import org.apache.poi.xssf.usermodel.XSSFWorkbook;  
  27.   
  28. /** 
  29.  *  
  30.  * @描述:测试excel读取 
  31.  *  
  32.  *               导入的jar包 
  33.  *  
  34.  *               poi-3.8-beta3-20110606.jar 
  35.  *  
  36.  *               poi-ooxml-3.8-beta3-20110606.jar 
  37.  *  
  38.  *               poi-examples-3.8-beta3-20110606.jar 
  39.  *  
  40.  *               poi-excelant-3.8-beta3-20110606.jar 
  41.  *  
  42.  *               poi-ooxml-schemas-3.8-beta3-20110606.jar 
  43.  *  
  44.  *               poi-scratchpad-3.8-beta3-20110606.jar 
  45.  *  
  46.  *               xmlbeans-2.3.0.jar 
  47.  *  
  48.  *               dom4j-1.6.1.jar 
  49.  *  
  50.  *               jar包官网下载地址:http://poi.apache.org/download.html 
  51.  *  
  52.  *               下载poi-bin-3.8-beta3-20110606.zipp 
  53.  *  
  54.  * @作者:建宁 
  55.  *  
  56.  * @时间:2012-08-29 下午16:27:15 
  57.  */  
  58.   
  59. public class ImportExecl  
  60. {  
  61.   
  62.     /** 总行数 */  
  63.   
  64.     private int totalRows = 0;  
  65.   
  66.     /** 总列数 */  
  67.   
  68.     private int totalCells = 0;  
  69.   
  70.     /** 错误信息 */  
  71.   
  72.     private String errorInfo;  
  73.   
  74.     /** 构造方法 */  
  75.   
  76.     public ImportExecl()  
  77.     {  
  78.   
  79.     }  
  80.   
  81.     /** 
  82.      *  
  83.      * @描述:得到总行数 
  84.      *  
  85.      * @作者:建宁 
  86.      *  
  87.      * @时间:2012-08-29 下午16:27:15 
  88.      *  
  89.      * @参数:@return 
  90.      *  
  91.      * @返回值:int 
  92.      */  
  93.   
  94.     public int getTotalRows()  
  95.     {  
  96.   
  97.         return totalRows;  
  98.   
  99.     }  
  100.   
  101.     /** 
  102.      *  
  103.      * @描述:得到总列数 
  104.      *  
  105.      * @作者:建宁 
  106.      *  
  107.      * @时间:2012-08-29 下午16:27:15 
  108.      *  
  109.      * @参数:@return 
  110.      *  
  111.      * @返回值:int 
  112.      */  
  113.   
  114.     public int getTotalCells()  
  115.     {  
  116.   
  117.         return totalCells;  
  118.   
  119.     }  
  120.   
  121.     /** 
  122.      *  
  123.      * @描述:得到错误信息 
  124.      *  
  125.      * @作者:建宁 
  126.      *  
  127.      * @时间:2012-08-29 下午16:27:15 
  128.      *  
  129.      * @参数:@return 
  130.      *  
  131.      * @返回值:String 
  132.      */  
  133.   
  134.     public String getErrorInfo()  
  135.     {  
  136.   
  137.         return errorInfo;  
  138.   
  139.     }  
  140.   
  141.     /** 
  142.      *  
  143.      * @描述:验证excel文件 
  144.      *  
  145.      * @作者:建宁 
  146.      *  
  147.      * @时间:2012-08-29 下午16:27:15 
  148.      *  
  149.      * @参数:@param filePath 文件完整路径 
  150.      *  
  151.      * @参数:@return 
  152.      *  
  153.      * @返回值:boolean 
  154.      */  
  155.   
  156.     public boolean validateExcel(String filePath)  
  157.     {  
  158.   
  159.         /** 检查文件名是否为空或者是否是Excel格式的文件 */  
  160.   
  161.         if (filePath == null || !(WDWUtil.isExcel2003(filePath) || WDWUtil.isExcel2007(filePath)))  
  162.         {  
  163.   
  164.             errorInfo = "文件名不是excel格式";  
  165.   
  166.             return false;  
  167.   
  168.         }  
  169.   
  170.         /** 检查文件是否存在 */  
  171.   
  172.         File file = new File(filePath);  
  173.   
  174.         if (file == null || !file.exists())  
  175.         {  
  176.   
  177.             errorInfo = "文件不存在";  
  178.   
  179.             return false;  
  180.   
  181.         }  
  182.   
  183.         return true;  
  184.   
  185.     }  
  186.   
  187.     /** 
  188.      *  
  189.      * @描述:根据文件名读取excel文件 
  190.      *  
  191.      * @作者:建宁 
  192.      *  
  193.      * @时间:2012-08-29 下午16:27:15 
  194.      *  
  195.      * @参数:@param filePath 文件完整路径 
  196.      *  
  197.      * @参数:@return 
  198.      *  
  199.      * @返回值:List 
  200.      */  
  201.   
  202.     public List<List<String>> read(String filePath)  
  203.     {  
  204.   
  205.         List<List<String>> dataLst = new ArrayList<List<String>>();  
  206.   
  207.         InputStream is = null;  
  208.   
  209.         try  
  210.         {  
  211.   
  212.             /** 验证文件是否合法 */  
  213.   
  214.             if (!validateExcel(filePath))  
  215.             {  
  216.   
  217.                 System.out.println(errorInfo);  
  218.   
  219.                 return null;  
  220.   
  221.             }  
  222.   
  223.             /** 判断文件的类型,是2003还是2007 */  
  224.   
  225.             boolean isExcel2003 = true;  
  226.   
  227.             if (WDWUtil.isExcel2007(filePath))  
  228.             {  
  229.   
  230.                 isExcel2003 = false;  
  231.   
  232.             }  
  233.   
  234.             /** 调用本类提供的根据流读取的方法 */  
  235.   
  236.             File file = new File(filePath);  
  237.   
  238.             is = new FileInputStream(file);  
  239.   
  240.             dataLst = read(is, isExcel2003);  
  241.   
  242.             is.close();  
  243.   
  244.         }  
  245.         catch (Exception ex)  
  246.         {  
  247.   
  248.             ex.printStackTrace();  
  249.   
  250.         }  
  251.         finally  
  252.         {  
  253.   
  254.             if (is != null)  
  255.             {  
  256.   
  257.                 try  
  258.                 {  
  259.   
  260.                     is.close();  
  261.   
  262.                 }  
  263.                 catch (IOException e)  
  264.                 {  
  265.   
  266.                     is = null;  
  267.   
  268.                     e.printStackTrace();  
  269.   
  270.                 }  
  271.   
  272.             }  
  273.   
  274.         }  
  275.   
  276.         /** 返回最后读取的结果 */  
  277.   
  278.         return dataLst;  
  279.   
  280.     }  
  281.   
  282.     /** 
  283.      *  
  284.      * @描述:根据流读取Excel文件 
  285.      *  
  286.      * @作者:建宁 
  287.      *  
  288.      * @时间:2012-08-29 下午16:40:15 
  289.      *  
  290.      * @参数:@param inputStream 
  291.      *  
  292.      * @参数:@param isExcel2003 
  293.      *  
  294.      * @参数:@return 
  295.      *  
  296.      * @返回值:List 
  297.      */  
  298.   
  299.     public List<List<String>> read(InputStream inputStream, boolean isExcel2003)  
  300.     {  
  301.   
  302.         List<List<String>> dataLst = null;  
  303.   
  304.         try  
  305.         {  
  306.   
  307.             /** 根据版本选择创建Workbook的方式 */  
  308.   
  309.             Workbook wb = null;  
  310.   
  311.             if (isExcel2003)  
  312.             {  
  313.                 wb = new HSSFWorkbook(inputStream);  
  314.             }  
  315.             else  
  316.             {  
  317.                 wb = new XSSFWorkbook(inputStream);  
  318.             }  
  319.             dataLst = read(wb);  
  320.   
  321.         }  
  322.         catch (IOException e)  
  323.         {  
  324.   
  325.             e.printStackTrace();  
  326.   
  327.         }  
  328.   
  329.         return dataLst;  
  330.   
  331.     }  
  332.   
  333.     /** 
  334.      *  
  335.      * @描述:读取数据 
  336.      *  
  337.      * @作者:建宁 
  338.      *  
  339.      * @时间:2012-08-29 下午16:50:15 
  340.      *  
  341.      * @参数:@param Workbook 
  342.      *  
  343.      * @参数:@return 
  344.      *  
  345.      * @返回值:List<List<String>> 
  346.      */  
  347.   
  348.     private List<List<String>> read(Workbook wb)  
  349.     {  
  350.   
  351.         List<List<String>> dataLst = new ArrayList<List<String>>();  
  352.   
  353.         /** 得到第一个shell */  
  354.   
  355.         Sheet sheet = wb.getSheetAt(0);  
  356.   
  357.         /** 得到Excel的行数 */  
  358.   
  359.         this.totalRows = sheet.getPhysicalNumberOfRows();  
  360.   
  361.         /** 得到Excel的列数 */  
  362.   
  363.         if (this.totalRows >= 1 && sheet.getRow(0) != null)  
  364.         {  
  365.   
  366.             this.totalCells = sheet.getRow(0).getPhysicalNumberOfCells();  
  367.   
  368.         }  
  369.   
  370.         /** 循环Excel的行 */  
  371.   
  372.         for (int r = 0; r < this.totalRows; r++)  
  373.         {  
  374.   
  375.             Row row = sheet.getRow(r);  
  376.   
  377.             if (row == null)  
  378.             {  
  379.   
  380.                 continue;  
  381.   
  382.             }  
  383.   
  384.             List<String> rowLst = new ArrayList<String>();  
  385.   
  386.             /** 循环Excel的列 */  
  387.   
  388.             for (int c = 0; c < this.getTotalCells(); c++)  
  389.             {  
  390.   
  391.                 Cell cell = row.getCell(c);  
  392.   
  393.                 String cellValue = "";  
  394.   
  395.                 if (null != cell)  
  396.                 {  
  397.                     // 以下是判断数据的类型  
  398.                     switch (cell.getCellType())  
  399.                     {  
  400.                     case HSSFCell.CELL_TYPE_NUMERIC: // 数字  
  401.                         cellValue = cell.getNumericCellValue() + "";  
  402.                         break;  
  403.   
  404.                     case HSSFCell.CELL_TYPE_STRING: // 字符串  
  405.                         cellValue = cell.getStringCellValue();  
  406.                         break;  
  407.   
  408.                     case HSSFCell.CELL_TYPE_BOOLEAN: // Boolean  
  409.                         cellValue = cell.getBooleanCellValue() + "";  
  410.                         break;  
  411.   
  412.                     case HSSFCell.CELL_TYPE_FORMULA: // 公式  
  413.                         cellValue = cell.getCellFormula() + "";  
  414.                         break;  
  415.   
  416.                     case HSSFCell.CELL_TYPE_BLANK: // 空值  
  417.                         cellValue = "";  
  418.                         break;  
  419.   
  420.                     case HSSFCell.CELL_TYPE_ERROR: // 故障  
  421.                         cellValue = "非法字符";  
  422.                         break;  
  423.   
  424.                     default:  
  425.                         cellValue = "未知类型";  
  426.                         break;  
  427.                     }  
  428.                 }  
  429.   
  430.                 rowLst.add(cellValue);  
  431.   
  432.             }  
  433.   
  434.             /** 保存第r行的第c列 */  
  435.   
  436.             dataLst.add(rowLst);  
  437.   
  438.         }  
  439.   
  440.         return dataLst;  
  441.   
  442.     }  
  443.   
  444.     /** 
  445.      *  
  446.      * @描述:main测试方法 
  447.      *  
  448.      * @作者:建宁 
  449.      *  
  450.      * @时间:2012-08-29 下午17:12:15 
  451.      *  
  452.      * @参数:@param args 
  453.      *  
  454.      * @参数:@throws Exception 
  455.      *  
  456.      * @返回值:void 
  457.      */  
  458.   
  459.     public static void main(String[] args) throws Exception  
  460.     {  
  461.   
  462.         ImportExecl poi = new ImportExecl();  
  463.   
  464.         // List<List<String>> list = poi.read("d:/aaa.xls");  
  465.   
  466.         List<List<String>> list = poi.read("c:/book.xlsx");  
  467.   
  468.         if (list != null)  
  469.         {  
  470.   
  471.             for (int i = 0; i < list.size(); i++)  
  472.             {  
  473.   
  474.                 System.out.print("第" + (i) + "行");  
  475.   
  476.                 List<String> cellList = list.get(i);  
  477.   
  478.                 for (int j = 0; j < cellList.size(); j++)  
  479.                 {  
  480.   
  481.                     // System.out.print("    第" + (j + 1) + "列值:");  
  482.   
  483.                     System.out.print("    " + cellList.get(j));  
  484.   
  485.                 }  
  486.                 System.out.println();  
  487.   
  488.             }  
  489.   
  490.         }  
  491.   
  492.     }  
  493.   
  494. }  
  495.   
  496. /** 
  497.  *  
  498.  * @描述:工具类 
  499.  *  
  500.  * @作者:建宁 
  501.  *  
  502.  * @时间:2012-08-29 下午16:30:40 
  503.  */  
  504.   
  505. class WDWUtil  
  506. {  
  507.   
  508.     /** 
  509.      *  
  510.      * @描述:是否是2003的excel,返回true是2003 
  511.      *  
  512.      * @作者:建宁 
  513.      *  
  514.      * @时间:2012-08-29 下午16:29:11 
  515.      *  
  516.      * @参数:@param filePath 文件完整路径 
  517.      *  
  518.      * @参数:@return 
  519.      *  
  520.      * @返回值:boolean 
  521.      */  
  522.   
  523.     public static boolean isExcel2003(String filePath)  
  524.     {  
  525.   
  526.         return filePath.matches("^.+\\.(?i)(xls)$");  
  527.   
  528.     }  
  529.   
  530.     /** 
  531.      *  
  532.      * @描述:是否是2007的excel,返回true是2007 
  533.      *  
  534.      * @作者:建宁 
  535.      *  
  536.      * @时间:2012-08-29 下午16:28:20 
  537.      *  
  538.      * @参数:@param filePath 文件完整路径 
  539.      *  
  540.      * @参数:@return 
  541.      *  
  542.      * @返回值:boolean 
  543.      */  
  544.   
  545.     public static boolean isExcel2007(String filePath)  
  546.     {  
  547.   
  548.         return filePath.matches("^.+\\.(?i)(xlsx)$");  
  549.   
  550.     }  
  551.   
  552. }  

 

java解析获取Excel中的数据--同时兼容2003及2007

java解析获取Excel中的数据--同时兼容2003及2007