Apache POI 库:如何读取 Word 文档中嵌入的 Excel sheet
Apache POI library : How to read Excel sheet embedded in Word document
我正在使用 Apache POI 库读取 Word 文档并将其转换为 HTML。我有一个包含嵌入式 Excel 作品sheet 的 Word 文档。有没有办法在读取XWPF文档时读取那个嵌入的Excelsheet?
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
中。因此可以检查每个 XWPFRun
是否包含 OLEObject
。如果是,则从 OLEObject
中获取 rId
属性。此 ID 链接到 Office Open XML
文档的文档部分。该文档部分后面的包部分的内容类型决定了嵌入的对象类型。因此,根据内容类型,您可以获得 XSSFWorkbook
、HSSFWorkbook
或其他嵌入的 OLEObject
。
以下方法演示了这种方法:
...
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
从 XWPFRun
中获取所有 OLEObject
XML
对象。它还获得 rId
属性。如果存在 such,则它调用 handleOLEObject
。此方法通过 rId
从 XWPFDocument
获取链接 POIXMLDocumentPart
。然后它根据内容类型确定嵌入了哪种 OLEObjects
并为这些对象调用不同的处理程序方法。
我正在使用 Apache POI 库读取 Word 文档并将其转换为 HTML。我有一个包含嵌入式 Excel 作品sheet 的 Word 文档。有没有办法在读取XWPF文档时读取那个嵌入的Excelsheet?
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
中。因此可以检查每个 XWPFRun
是否包含 OLEObject
。如果是,则从 OLEObject
中获取 rId
属性。此 ID 链接到 Office Open XML
文档的文档部分。该文档部分后面的包部分的内容类型决定了嵌入的对象类型。因此,根据内容类型,您可以获得 XSSFWorkbook
、HSSFWorkbook
或其他嵌入的 OLEObject
。
以下方法演示了这种方法:
...
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
从 XWPFRun
中获取所有 OLEObject
XML
对象。它还获得 rId
属性。如果存在 such,则它调用 handleOLEObject
。此方法通过 rId
从 XWPFDocument
获取链接 POIXMLDocumentPart
。然后它根据内容类型确定嵌入了哪种 OLEObjects
并为这些对象调用不同的处理程序方法。