blob: faf31b3dedfdd3b38b35163bbb412713e38c3c46 [file] [log] [blame]
/*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.apache.poi.examples.xwpf.usermodel;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
/**
* Tests whether it is possible to successfully update an Excel workbook that is
* embedded into a WordprocessingML document. Note that the test has currently
* only been conducted with a binary Excel workbook and NOT yet with a
* SpreadsheetML workbook embedded into the document.<p>
*
* This code was successfully tested with the following file from the POI test collection:
* http://svn.apache.org/repos/asf/poi/trunk/test-data/document/EmbeddedDocument.docx
*/
@SuppressWarnings({"java:S106","java:S4823","java:S1192"})
public class UpdateEmbeddedDoc {
private XWPFDocument doc;
private File docFile;
private static final int SHEET_NUM = 0;
private static final int ROW_NUM = 0;
private static final int CELL_NUM = 0;
private static final double NEW_VALUE = 100.98D;
private static final String BINARY_EXTENSION = "xls";
private static final String OPENXML_EXTENSION = "xlsx";
/**
* Create a new instance of the UpdateEmbeddedDoc class using the following
* parameters;
*
* @param filename An instance of the String class that encapsulates the name
* of and path to a WordprocessingML Word document that contains an
* embedded binary Excel workbook.
* @throws java.io.FileNotFoundException Thrown if the file cannot be found
* on the underlying file system.
* @throws java.io.IOException Thrown if a problem occurs in the underlying
* file system.
*/
public UpdateEmbeddedDoc(String filename) throws FileNotFoundException, IOException {
this.docFile = new File(filename);
if (!this.docFile.exists()) {
throw new FileNotFoundException("The Word document " + filename + " does not exist.");
}
try (FileInputStream fis = new FileInputStream(this.docFile)) {
// Open the Word document file and instantiate the XWPFDocument class.
this.doc = new XWPFDocument(fis);
}
}
/**
* Called to update the embedded Excel workbook. As the format and structure
* of the workbook are known in advance, all this code attempts to do is
* write a new value into the first cell on the first row of the first
* worksheet. Prior to executing this method, that cell will contain the
* value 1.
*
* @throws org.apache.poi.openxml4j.exceptions.OpenXML4JException
* Rather
* than use the specific classes (HSSF/XSSF) to handle the embedded
* workbook this method uses those defined in the SS stream. As
* a result, it might be the case that a SpreadsheetML file is
* opened for processing, throwing this exception if that file is
* invalid.
* @throws java.io.IOException Thrown if a problem occurs in the underlying
* file system.
*/
public void updateEmbeddedDoc() throws OpenXML4JException, IOException {
List<PackagePart> embeddedDocs = this.doc.getAllEmbeddedParts();
for (PackagePart pPart : embeddedDocs) {
String ext = pPart.getPartName().getExtension();
if (BINARY_EXTENSION.equals(ext) || OPENXML_EXTENSION.equals(ext)) {
// Get an InputStream from the package part and pass that
// to the create method of the WorkbookFactory class. Update
// the resulting Workbook and then stream that out again
// using an OutputStream obtained from the same PackagePart.
try (InputStream is = pPart.getInputStream();
Workbook workbook = WorkbookFactory.create(is);
OutputStream os = pPart.getOutputStream()) {
Sheet sheet = workbook.getSheetAt(SHEET_NUM);
Row row = sheet.getRow(ROW_NUM);
Cell cell = row.getCell(CELL_NUM);
cell.setCellValue(NEW_VALUE);
workbook.write(os);
}
}
}
if (!embeddedDocs.isEmpty()) {
// Finally, write the newly modified Word document out to file.
try (FileOutputStream fos = new FileOutputStream(this.docFile)) {
this.doc.write(fos);
}
}
}
/**
* Called to test whether or not the embedded workbook was correctly
* updated. This method simply recovers the first cell from the first row
* of the first workbook and tests the value it contains.
* <p>
* Note that execution will not continue up to the assertion as the
* embedded workbook is now corrupted and causes an IllegalArgumentException
* with the following message
* <p>
* <em>java.lang.IllegalArgumentException: Your InputStream was neither an
* OLE2 stream, nor an OOXML stream</em>
* <p>
* to be thrown when the WorkbookFactory.createWorkbook(InputStream) method
* is executed.
*
* @throws org.apache.poi.openxml4j.exceptions.OpenXML4JException
* Rather
* than use the specific classes (HSSF/XSSF) to handle the embedded
* workbook this method uses those defined in the SS stream. As
* a result, it might be the case that a SpreadsheetML file is
* opened for processing, throwing this exception if that file is
* invalid.
* @throws java.io.IOException Thrown if a problem occurs in the underlying
* file system.
*/
public void checkUpdatedDoc() throws OpenXML4JException, IOException {
for (PackagePart pPart : this.doc.getAllEmbeddedParts()) {
String ext = pPart.getPartName().getExtension();
if (BINARY_EXTENSION.equals(ext) || OPENXML_EXTENSION.equals(ext)) {
try (InputStream is = pPart.getInputStream();
Workbook workbook = WorkbookFactory.create(is)) {
Sheet sheet = workbook.getSheetAt(SHEET_NUM);
Row row = sheet.getRow(ROW_NUM);
Cell cell = row.getCell(CELL_NUM);
if(cell.getNumericCellValue() != NEW_VALUE) {
throw new IllegalStateException("Failed to validate document content.");
}
}
}
}
}
/**
* Code to test updating of the embedded Excel workbook.
*/
public static void main(String[] args) throws IOException, OpenXML4JException {
UpdateEmbeddedDoc ued = new UpdateEmbeddedDoc(args[0]);
ued.updateEmbeddedDoc();
ued.checkUpdatedDoc();
}
}