2012-07-23 97 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(); 
相关问题