sooxin-JAVA

          使用POI來處理Excel和Word文件格式

          7.3  使用POI來處理Excel和Word文件格式

          Microsoft的Office系列產(chǎn)品擁有大量的用戶,Word、Excel也成為辦公文件的首選。在Java中,已經(jīng)有很多對于Word、Excel的開源的解決方案,其中比較出色的是Apache的Jakata項目的POI子項目。該項目的官方網(wǎng)站是http://jakarta.apache.org/poi/。

          POI包括一系列的API,它們可以操作基于MicroSoft OLE 2 Compound Document Format的各種格式文件,可以通過這些API在Java中讀寫Excel、Word等文件。POI是完全的Java Excel和Java Word解決方案。POI子項目包括:POIFS、HSSF、HDF、HPSF。表7-2對它們進行了簡要介紹。

          表7-2  POI子項目介紹

           

          子項目名

           

          說明

           

          POIFS(POI File System)

           

          POIFS是POI項目中最早的最基礎(chǔ)的一個模塊,是Java到OLE 2 Compound Document Format的接口,支持讀寫功能,所有的其他項目都依賴與該項目。

           

          HSSF(Horrible Spreadsheet Format)

           

          HSSF是Java到Microsoft Excel 97(-2002)文件的接口,支持讀寫功能

           

          HWPF(Horrible Word Processing Format)

           

          HWPF是Java到Microsoft Word 97文件的接口,支持讀寫功能,但目前該模塊還處于剛開始開發(fā)階段,只能實現(xiàn)一些簡單文件的操作,在后續(xù)版本中,會提供更強大的支持

           

          HPSF(Horrible Property Set Format)

           

          HPSF 是Java到OLE 2 Compound Document Format文件的屬性設(shè)置的接口,屬性設(shè)置通常用來設(shè)置文檔的屬性(標題,作者,最后修改日期等),還可以設(shè)置用戶定義的屬性。HPSF支持讀寫功能,當前發(fā)布版本中直支持讀功能。

          7.3.1  對Excel的處理類

          下面通過HSSF提供的接口對Excel文件經(jīng)行處理。首先需要下載POI的包,可以到apache的官方網(wǎng)站下載,地址為:http://apache.justdn.org/jakarta/poi/,本書采用的是poi-2.5.1-final-20040804.jar,讀者可以下載當前的穩(wěn)定版本。把下載的包按照前面介紹的方式加入Build Path,然后新建一個ch7.poi包,并創(chuàng)建一個ExcelReader類。

          ExcelReader類可以讀取一個XLS文件,然后將其內(nèi)容逐行提取出來,寫入文本文件。其代碼如下。

          代碼7.6

          public class ExcelReader {

             // 創(chuàng)建文件輸入流

             private BufferedReader reader = null;

             // 文件類型

             private String filetype;

             // 文件二進制輸入流

             private InputStream is = null;

             // 當前的Sheet

             private int currSheet;

             // 當前位置

             private int currPosition;

             // Sheet數(shù)量

             private int numOfSheets;

             // HSSFWorkbook

             HSSFWorkbook workbook = null;

             // 設(shè)置Cell之間以空格分割

             private static String EXCEL_LINE_DELIMITER = " ";

             // 設(shè)置最大列數(shù)

             private static int MAX_EXCEL_COLUMNS = 64;

             // 構(gòu)造函數(shù)創(chuàng)建一個ExcelReader

             public ExcelReader(String inputfile) throws IOException, Exception {

                // 判斷參數(shù)是否為空或沒有意義

                if (inputfile == null || inputfile.trim().equals("")) {

                   throw new IOException("no input file specified");

                }

                // 取得文件名的后綴名賦值給filetype

                this.filetype = inputfile.substring(inputfile.lastIndexOf(".") + 1);

                // 設(shè)置開始行為0

                currPosition = 0;

                // 設(shè)置當前位置為0

                currSheet = 0;

                // 創(chuàng)建文件輸入流

                is = new FileInputStream(inputfile);

                // 判斷文件格式

                if (filetype.equalsIgnoreCase("txt")) {

                   // 如果是txt則直接創(chuàng)建BufferedReader讀取

                   reader = new BufferedReader(new InputStreamReader(is));

                }

          else if (filetype.equalsIgnoreCase("xls")) {

                   // 如果是Excel文件則創(chuàng)建HSSFWorkbook讀取

                   workbook = new HSSFWorkbook(is);

                   // 設(shè)置Sheet數(shù)

                   numOfSheets = workbook.getNumberOfSheets();

                }

          else {

                   throw new Exception("File Type Not Supported");

                }

             }

             // 函數(shù)readLine讀取文件的一行

             public String readLine() throws IOException {

                // 如果是txt文件則通過reader讀取

                if (filetype.equalsIgnoreCase("txt")) {

                   String str = reader.readLine();

                   // 空行則略去,直接讀取下一行

                   while (str.trim().equals("")) {

                      str = reader.readLine();

                   }

                   return str;

                }

                // 如果是XLS文件則通過POI提供的API讀取文件

                else if (filetype.equalsIgnoreCase("xls")) {

                   // 根據(jù)currSheet值獲得當前的sheet

                   HSSFSheet sheet = workbook.getSheetAt(currSheet);

                   // 判斷當前行是否到但前Sheet的結(jié)尾

                   if (currPosition > sheet.getLastRowNum()) {

                      // 當前行位置清零

                      currPosition = 0;

                      // 判斷是否還有Sheet

                      while (currSheet != numOfSheets - 1) {

                         // 得到下一張Sheet

                         sheet = workbook.getSheetAt(currSheet + 1);

                         // 當前行數(shù)是否已經(jīng)到達文件末尾

                         if (currPosition == sheet.getLastRowNum()) {

                            // 當前Sheet指向下一張Sheet

                            currSheet++;

                            continue;

                         } else {

                            // 獲取當前行數(shù)

                            int row = currPosition;

                            currPosition++;

                            // 讀取當前行數(shù)據(jù)

                            return getLine(sheet, row);

                         }

                      }

                      return null;

                   }

                   // 獲取當前行數(shù)

                   int row = currPosition;

                   currPosition++;

                   // 讀取當前行數(shù)據(jù)

                   return getLine(sheet, row);

                }

                return null;

             }

             // 函數(shù)getLine返回Sheet的一行數(shù)據(jù)

             private String getLine(HSSFSheet sheet, int row) {

                // 根據(jù)行數(shù)取得Sheet的一行

                HSSFRow rowline = sheet.getRow(row);

                // 創(chuàng)建字符創(chuàng)緩沖區(qū)

                StringBuffer buffer = new StringBuffer();

                // 獲取當前行的列數(shù)

                int filledColumns = rowline.getLastCellNum();

                HSSFCell cell = null;

                // 循環(huán)遍歷所有列

                for (int i = 0; i < filledColumns; i++) {

                   // 取得當前Cell

                   cell = rowline.getCell((short) i);

                   String cellvalue = null;

                   if (cell != null) {

                      // 判斷當前Cell的Type

                      switch (cell.getCellType()) {

                      // 如果當前Cell的Type為NUMERIC

                      case HSSFCell.CELL_TYPE_NUMERIC: {

                         // 判斷當前的cell是否為Date

                         if (HSSFDateUtil.isCellDateFormatted(cell)) {

                            // 如果是Date類型則,取得該Cell的Date值

                            Date date = cell.getDateCellValue();

                            // 把Date轉(zhuǎn)換成本地格式的字符串

                            cellvalue = cell.getDateCellValue().toLocaleString();

                         }

                         // 如果是純數(shù)字

                         else {

                            // 取得當前Cell的數(shù)值

                            Integer num = new Integer((int) cell

                                  .getNumericCellValue());

                            cellvalue = String.valueOf(num);

                         }

                         break;

                      }

                      // 如果當前Cell的Type為STRIN

                      case HSSFCell.CELL_TYPE_STRING:

                         // 取得當前的Cell字符串

                         cellvalue = cell.getStringCellValue().replaceAll("'", "''");

                         break;

                      // 默認的Cell值

                      default:

                         cellvalue = " ";

                      }

                   } else {

                      cellvalue = "";

                   }

                   // 在每個字段之間插入分割符

                   buffer.append(cellvalue).append(EXCEL_LINE_DELIMITER);

                }

                // 以字符串返回該行的數(shù)據(jù)

                return buffer.toString();

             }

             // close函數(shù)執(zhí)行流的關(guān)閉操作

             public void close() {

                // 如果is不為空,則關(guān)閉InputSteam文件輸入流

                if (is != null) {

                   try {

                      is.close();

                   } catch (IOException e) {

                      is = null;

                   }

                }

                // 如果reader不為空則關(guān)閉BufferedReader文件輸入流

                if (reader != null) {

                   try {

                      reader.close();

                   } catch (IOException e) {

                      reader = null;

                   }

                }

             }

          }

          7.3.2  ExcelReader的運行效果

          下面創(chuàng)建一個main函數(shù),用來測試上面的ExcelReader類,代碼如下。

          代碼7.7

              public static void main(String[] args) {

                  try{

                      ExcelReader er=new ExcelReader("c:\\xp.xls");  

                      String line=er.readLine();

                      while(line != null){

                          System.out.println(line);

                          line=er.readLine();

                      }

                      er.close();

                  }catch(Exception e){

                      e.printStackTrace();

                  }

              }

          main函數(shù)先創(chuàng)建一個ExcelReader類,然后調(diào)用它提供的接口readLine,對XLS文件進行讀取,打印到控制臺,處理前的XLS文件如圖7-12所示。

          圖7-12  處理前的XLS文件內(nèi)容

          運行main函數(shù)進行內(nèi)容提取后,Eclipse的控制臺輸出如圖7-13所示。

          圖7-13  輸出結(jié)果

          可以看到,Excel文件中的內(nèi)容已經(jīng)被成功的輸出了出來。

          7.3.3  POI中Excel文件Cell的類型

          在讀取每一個Cell的值的時候,通過getCellType方法獲得當前Cell的類型,在Excel中Cell有6種類型,如表7-3所示。

          表7-3  Cell的類型

           

          CellType

           

          說明

           

          CELL_TYPE_BLANK

           

          空值

           

          CELL_TYPE_BOOLEAN

           

          布爾型

           

          CELL_TYPE_ERROR

           

          錯誤

           

          CELL_TYPE_FORMULA

           

          公式型

           

          CELL_TYPE_STRING

           

          字符串型

           

          CELL_TYPE_NUMERIC

           

          數(shù)值型

          本例采用了CELL_TYPE_STRING和CELL_TYPE_NUMERIC類型,因為在Excel文件中只有字符串和數(shù)字。如果Cell的Type為CELL_TYPE_NUMERIC時,還需要進一步判斷該Cell的數(shù)據(jù)格式,因為它有可能是Date類型,在Excel中的Date類型也是以Double類型的數(shù)字存儲的。Excel中的Date表示當前時間與1900年1月1日相隔的天數(shù),所以需要調(diào)用HSSFDateUtil的isCellDateFormatted方法,判斷該Cell的數(shù)據(jù)格式是否是Excel Date類型。如果是,則調(diào)用getDateCellValue方法,返回一個Java類型的Date。

          實際上Excel的數(shù)據(jù)格式有很多,還支持用戶自定義的類型,在Excel中,選擇一個單元格然后右鍵選擇“設(shè)置單元格格式”,在彈出的單元格格式中選中“數(shù)字”,如圖7-14所示。

          圖7-14  Excel的單元格格式

          圖中的數(shù)據(jù)有數(shù)值、貨幣、時間、日期、文本等格式。這些數(shù)據(jù)格式在POI中的HSSFDataFormat類里都有相應(yīng)的定義。

          HSSFDataFormat是HSSF子項目里面定義的一個類。類HSSFDataFormat允許用戶新建數(shù)據(jù)格式類型。HSSFDataFormat類包含靜態(tài)方法static java.lang.String getBuiltinFormat(short index),它可以根據(jù)編號返回內(nèi)置數(shù)據(jù)類型。另外static short getBuiltinFormat(java.lang.String format)方法則可以根據(jù)數(shù)據(jù)類型返回其編號,static java.util.List getBuiltinFormats()可以返回整個內(nèi)置的數(shù)據(jù)格式列表。

          在HSSFDataFormat里一共定義了49種內(nèi)置的數(shù)據(jù)格式,如表7-4所示。

          表7-4  HSSFDataFormat的數(shù)據(jù)格式

           

          內(nèi)置數(shù)據(jù)類型

           

          編號

           

          "General"

           

          0

           

          "0"

           

          1

           

          "0.00"

           

          2

           

          "#,##0"

           

          3

           

          "#,##0.00"

           

          4

           

          "($#,##0_);($#,##0)"

           

          5

           

          "($#,##0_);[Red]($#,##0)"

           

          6

           

          "($#,##0.00);($#,##0.00)"

           

          7

           

          "($#,##0.00_);[Red]($#,##0.00)"

           

          8

           

          "0%"

           

          9

           

          "0.00%"

           

          0xa

           

          "0.00E+00"

           

          0xb

           

          "# ?/?"

           

          0xc

           

          "# ??/??"

           

          0xd

           

          "m/d/yy"

           

          0xe

           

          "d-mmm-yy"

           

          0xf

           

          "d-mmm"

           

          0x10

           

          "mmm-yy"

           

          0x11

           

          "h:mm AM/PM"

           

          0x12

           

          "h:mm:ss AM/PM"

           

          0x13

           

          "h:mm"

           

          0x14

           

          "h:mm:ss"

           

          0x15

           

          "m/d/yy h:mm"

           

          0x16

           

          保留為過國際化用

           

          0x17 - 0x24

           

          "(#,##0_);(#,##0)"

           

          0x25

           

          "(#,##0_);[Red](#,##0)"

           

          0x26

           

          "(#,##0.00_);(#,##0.00)"

           

          0x27

           

          "(#,##0.00_);[Red](#,##0.00)"

           

          0x28

           

          "_($*#,##0_);_($*(#,##0);_($* \"-\"_);_(@_)"

           

          0x29

           

          "_(*#,##0.00_);_(*(#,##0.00);_(*\"-\"??_);_(@_)"

           

          0x2a

           

          "_($*#,##0.00_);_($*(#,##0.00);_($*\"-\"??_);_(@_)"

           

          0x2b

           

          "_($*#,##0.00_);_($*(#,##0.00);_($*\"-\"??_);_(@_)"

           

          0x2c

           

          "mm:ss"

           

          0x2d

           

          "[h]:mm:ss"

           

          0x2e

           

          "mm:ss.0"

           

          0x2f

           

          "##0.0E+0"

           

          0x30

           

          "@" - This is text format

           

          0x31

          在上面表中,字符串類型所對應(yīng)的是數(shù)據(jù)格式為"@"(最后一行),也就是HSSFDataFormat中定義的值為0x31(49)的那行。Date類型的值的范圍是0xe-0x11,本例子中的Date格式為""m/d/yy"",在HSSFDataFormat定義的值為0xe(14)。

          需要注意的一點是,所創(chuàng)建的Excel必須是在Microsoft Excel 97到Excel XP的版本上的,如果在Excel 2003中創(chuàng)建文件后,在使用POI進行解析時,可能會出現(xiàn)問題。它會把Date類型當作自定義類型。POI目前只提供對Microsoft Excel XP以下的版本的支持,在以后的版本中,希望會提供對Microsoft Excel 2003更好的支持。

          7.3.4  對Word的處理類

          除了支持對Excel文件的讀取外,POI還提供對Word的DOC格式文件的讀取。但在它的發(fā)行版本中沒有發(fā)布對Word支持的模塊,需要另外下載一個POI的擴展的Jar包。用戶可以到http://www.ibiblio.org/maven2/org/textmining/tm-extractors/0.4/下載,本書采用的是tm-extractors-0.4_zip。

          下載后,把該包加入工程的Build Path中,然后在ch7.poi包下新建一個類WordReader,該類提供一個靜態(tài)方法readDoc,讀取一個DOC文件并返回文本。函數(shù)內(nèi)容很簡單,就是調(diào)用WordExtractor的API來提取DOC的內(nèi)容到字符串,該函數(shù)的代碼如下。

          代碼7.8

          public static String readDoc(String doc) throws Exception {

              // 創(chuàng)建輸入流讀取DOC文件

              FileInputStream in = new FileInputStream(new File(doc));

              WordExtractor extractor = null;

              String text = null;

              // 創(chuàng)建WordExtractor

              extractor = new WordExtractor();

              // 對DOC文件進行提取

              text = extractor.extractText(in);

              return text;

          }

          在同一個類里創(chuàng)建一個main函數(shù),測試WordReader,該main函數(shù)代碼如下。

          代碼7.9

          public static void main(String[] args) {

                  try{

                     String text = WordReader.readDoc("c:/test.doc");

                     System.out.println(text);

                  }catch(Exception e){

                      e.printStackTrace();

                  }

              }

          處理前的Doc文件如圖7-15所示。

          圖7-15  處理前的Word文檔

          使用代碼處理后的文本如圖7-16所示。

          圖7-16  處理后的結(jié)果

          可以看到Word文檔內(nèi)的文本已經(jīng)全部被提取了出來。

          posted on 2007-11-01 20:56 sooxin 閱讀(733) 評論(1)  編輯  收藏 所屬分類: JAVA

          Feedback

          # re: 使用POI來處理Excel和Word文件格式 2015-12-24 22:29 ere

          sdfdsfdsfdfdssd  回復(fù)  更多評論   


          主站蜘蛛池模板: 珲春市| 都昌县| 历史| 蛟河市| 湘乡市| 兰西县| 喀什市| 通许县| 日喀则市| 苏尼特左旗| 方正县| 泗水县| 沿河| 额敏县| 库车县| 中西区| 吴忠市| 大方县| 昭平县| 会昌县| 稷山县| 白朗县| 汤阴县| 城市| 东安县| 徐州市| 达州市| 郯城县| 墨竹工卡县| 内黄县| 克拉玛依市| 广元市| 双辽市| 格尔木市| 武穴市| 桂平市| 冕宁县| 鹤庆县| 台东县| 玛多县| 洛南县|