我正在使用Apache POI库来读取一个Word文档并将其转换为HTML。我有一个Word文档,其中包含一个嵌入式Excel工作表。有什么方法可以在读取XWPF文档时读取那个嵌入的Excel表格吗?
OOXML包含以下代码。
<w:object w:dxaOrig="6942" w:dyaOrig="3234" w14:anchorId="071813E3">
<v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f">
<v:stroke joinstyle="miter"/>
<v:formulas>
<v:f eqn="if lineDrawn pixelLineWidth 0"/>
<v:f eqn="sum @0 1 0"/>
<v:f eqn="sum 0 0 @1"/>
<v:f eqn="prod @2 1 2"/>
<v:f eqn="prod @3 21600 pixelWidth"/>
<v:f eqn="prod @3 21600 pixelHeight"/>
<v:f eqn="sum @0 0 1"/>
<v:f eqn="prod @6 1 2"/>
<v:f eqn="prod @7 21600 pixelWidth"/>
<v:f eqn="sum @8 21600 0"/>
<v:f eqn="prod @7 21600 pixelHeight"/>
<v:f eqn="sum @10 21600 0"/>
</v:formulas>
<v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"/>
<o:lock v:ext="edit" aspectratio="t"/>
</v:shapetype>
<v:shape id="_x0000_i1037" type="#_x0000_t75" style="width:347.4pt;height:162pt" o:ole="">
<v:imagedata r:id="rId7" o:title=""/>
</v:shape>
<o:OLEObject Type="Embed" ProgID="Excel.Sheet.12" ShapeID="_x0000_i1037" DrawAspect="Content" ObjectID="_1653752874" r:id="rId8"/>
</w:object>
我看到里面嵌入了OLEObject. 但不知道如何读取其内容。任何帮助都是非常感激的。
该 OLEObject
中包含了 XWPFRun
s. 所以可以检查每个 XWPFRun
是否包含 OLEObject
s. 如果是这样,那么得到的 rId
的属性 OLEObject
. 这个ID链接到一个文件的一部分。Office Open XML
文档。该文档部分后面的包部分的内容类型决定了嵌入的对象是什么类型。因此,根据内容类型的不同,我们可以得到的是 XSSFWorkbook
, HSSFWorkbook
或其他嵌入式 OLEObject
s则。
下面的方法展示了这种方法。
...
import org.apache.poi.ooxml.*;
import org.apache.poi.openxml4j.opc.*;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.hssf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import org.apache.xmlbeans.XmlObject;
...
void handleOLEObjects(XWPFRun run) {
CTR ctr = run.getCTR();
String declareNameSpaces = "declare namespace o='urn:schemas-microsoft-com:office:office'";
XmlObject[] oleObjects = ctr.selectPath(declareNameSpaces + ".//o:OLEObject");
for (XmlObject oleObject : oleObjects) {
XmlObject rIdAttribute = oleObject.selectAttribute("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "id");
if (rIdAttribute != null) {
String rId = rIdAttribute.newCursor().getTextValue();
handleOLEObject(run.getDocument(), rId);
}
}
}
void handleOLEObject(XWPFDocument document, String rId) {
POIXMLDocumentPart documentPart = document.getRelationById(rId);
if ("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet".equals(documentPart.getPackagePart().getContentType())) {
handleXSSFWorkbook(documentPart.getPackagePart());
} else if ("application/vnd.ms-excel".equals(documentPart.getPackagePart().getContentType())) {
handleHSSFWorkbook(documentPart.getPackagePart());
} //else if ...
}
void handleXSSFWorkbook(PackagePart part) {
try {
XSSFWorkbook workbook = new XSSFWorkbook(part);
for (Sheet sheet : workbook) {
for (Row row : sheet) {
for (Cell cell : row) {
System.out.print(cell + "\t");
}
System.out.println();
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
void handleHSSFWorkbook(PackagePart part) {
try {
HSSFWorkbook workbook = new HSSFWorkbook(part.getInputStream());
for (Sheet sheet : workbook) {
for (Row row : sheet) {
for (Cell cell : row) {
System.out.print(cell + "\t");
}
System.out.println();
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
该方法 handleOLEObjects
用途 XPath
以获得所有 OLEObject
XML
脱离 XWPFRun
. 它还得到了 rId
属性。如果存在这样的属性,那么它就会调用 handleOLEObject
. 本方法获取链接的 POIXMLDocumentPart
从 XWPFDocument
被 rId
. 然后,它通过内容类型来决定哪些种类的内容。OLEObjects
并为这些对象调用不同的处理方法。