2012-07-23 32 views
2

如何使用Apache POI提供的事件API獲取Excel工作表的合併區域(合併單元格)?如何使用apache POI的事件API獲取合併區域?

使用「傳統的」類似於DOM的解析風格有稱爲Sheet.getNumMergedRegions()Sheet.getMergedRegion(int)的方法。不幸的是,我需要處理大量的Excel文件,即使我允許使用的最高Xmx值(在此項目中)出現內存不足錯誤。所以我想使用事件API,但無法找到如何獲取合併區域的信息,我需要知道這些信息才能正確「理解」內容......

使用給定的示例這裏: http://poi.apache.org/spreadsheet/how-to.html#xssf_sax_api 我得到合併區域的每個單元格的事件(儘管它們中只有第一個包含任何文本內容)。所以也許,如果沒有更直接的方式,這將有助於瞭解如何將這些合併的單元格(安全地)與其他(空單元格)區分開來...

回答

2

我不確定合併的位置細胞信息被存儲,但我確信它不會與細胞數據本身,因爲這不是Excel的方式。

我建議你做的是創建一個沒有合併單元格的簡單文件。然後,獲取一份副本,並添加一個合併的單元格。解壓縮這兩個文件(.xlsx是xml文件的zip文件),並對它們進行區分。這將很快向您顯示將單元格標記爲合併的設置。 (我的預感是它會在表單設置的某個位置,靠近開始位置,但不靠近單元格值BICBW)

一旦您知道合併的單元格細節存在的位置,可以查看XSSF UserModel使用合併單元格的代碼來了解它們是如何工作的,它們如何被操縱,選項是什麼等等。考慮到這一點,您可以查看文件格式文檔以獲取完整的細節,但這些代碼可以是有點重和細緻,首先要去。最後,你可以添加你的代碼來使用合併的信息細節,一旦你知道從哪裏得到它!

+0

你說得對 - 我是在錯誤的地方尋找。有一些名爲「mergeCell」的元素具有「ref」屬性。 ref的值是例如「A1:B3」。現在,我似乎必須解釋該字符串(「A1:B3」)才能獲得所有合併區域的列/行索引。謝謝! – Patter 2012-07-24 11:33:04

+0

那麼,正確的地方在哪裏?是「mergeCell」元素嗎?我也有同樣的問題。 – Samoth 2017-01-13 14:27:15

1

您需要打開流並解析它兩次。

第一次 - 提取合併的單元格。他們出現在sheet...xml文件後<sheetData>...</sheetData>標籤,就像這個例子:

... 
</sheetData> 
< mergeCells count="2" > 
    < mergeCell ref="A2:C2"/ > 
    < mergeCell ref="A3:A7"/ > 
</mergeCells > 

。提取並保留在某些列表。

然後重新打開流並像往常一樣解析它,以提取行和單元格。在完成每一行的endElement(...)方法中,檢查該行是否出現(部分或完全)在合併區域中。

1

擴大Mike的答案。您可以創建一個ContentHandler找到像合併地區:

import java.util.ArrayList; 
import java.util.List; 

import org.apache.poi.ss.util.CellRangeAddress; 

import org.xml.sax.Attributes; 
import org.xml.sax.helpers.DefaultHandler; 

public class MergedRegionLocator extends DefaultHandler { 
    private final List<CellRangeAddress> mergedRegions = new ArrayList<>(); 

    @Override 
    public void startElement (String uri, String localName, String name, Attributes attributes) { 
     if ("mergeCell".equals(name) && attributes.getValue("ref") != null) { 
      mergedRegions.add(CellRangeAddress.valueOf(attributes.getValue("ref"))); 
     } 
    } 

    public CellRangeAddress getMergedRegion (int index) { 
     return mergedRegions.get(index); 
    } 

    public List<CellRangeAddress> getMergedRegions() { 
     return mergedRegions; 
    } 
} 

一個例子使用它與基於事件的POI解析:

OPCPackage pkg = OPCPackage.open(new FileInputStream("test.xlsx")); 
XSSFReader reader = new XSSFReader(pkg); 
InputStream sheetData = reader.getSheetsData().next(); 

MergedRegionLocator mergedRegionLocator = new MergedRegionLocator(); 
XMLReader parser = XMLReaderFactory.createXMLReader(); 
parser.setContentHandler(mergedRegionLocator); 
parser.parse(new InputSource(sheetData)); 

mergedRegionLocator.getMergedRegions();