tag r1847494 as 4.0.1
git-svn-id: https://svn.apache.org/repos/asf/poi/tags/REL_4_0_1@1847495 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
commit
3ad99da86e
@ -1950,6 +1950,7 @@ under the License.
|
|||||||
<mapper>
|
<mapper>
|
||||||
<chainedmapper>
|
<chainedmapper>
|
||||||
<filtermapper>
|
<filtermapper>
|
||||||
|
<replaceregex pattern=".jar" replace="" flags="g"/>
|
||||||
<replaceregex pattern="ooxml-lite" replace="ooxml-schemas" flags="g"/>
|
<replaceregex pattern="ooxml-lite" replace="ooxml-schemas" flags="g"/>
|
||||||
<replaceregex pattern="(.java|.src)$$" replace="-sources"/>
|
<replaceregex pattern="(.java|.src)$$" replace="-sources"/>
|
||||||
<replaceregex pattern=".*(?:build|src).?(.*)?" replace="\1"/>
|
<replaceregex pattern=".*(?:build|src).?(.*)?" replace="\1"/>
|
||||||
@ -2112,6 +2113,7 @@ under the License.
|
|||||||
sonar/*/src/**,
|
sonar/*/src/**,
|
||||||
compile-lib/**,
|
compile-lib/**,
|
||||||
ooxml-lib/**,
|
ooxml-lib/**,
|
||||||
|
ooxml-testlib/**,
|
||||||
scripts/**,
|
scripts/**,
|
||||||
TEST*,
|
TEST*,
|
||||||
*.ipr,
|
*.ipr,
|
||||||
@ -2452,7 +2454,7 @@ under the License.
|
|||||||
<copy todir="${repo}">
|
<copy todir="${repo}">
|
||||||
<mappedresources>
|
<mappedresources>
|
||||||
<!-- add sha-512 when nexus rules are updated (1/2) -->
|
<!-- add sha-512 when nexus rules are updated (1/2) -->
|
||||||
<fileset dir="build/dist/maven" includes="@{artifactId}/**" excludes="**/*.sha512"/>
|
<fileset dir="build/dist/maven" includes="@{artifactId}/**" excludes="**/*.sha512,**/*.sha256"/>
|
||||||
<regexpmapper from="^([^/]+)/(.*)$$" to="org/apache/poi/\1/${version.id}/\2" handledirsep="true"/>
|
<regexpmapper from="^([^/]+)/(.*)$$" to="org/apache/poi/\1/${version.id}/\2" handledirsep="true"/>
|
||||||
</mappedresources>
|
</mappedresources>
|
||||||
</copy>
|
</copy>
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.apache.poi</groupId>
|
<groupId>org.apache.poi</groupId>
|
||||||
<artifactId>poi-parent</artifactId>
|
<artifactId>poi-parent</artifactId>
|
||||||
<version>4.0.1-SNAPSHOT</version>
|
<version>4.0.2-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>poi-examples</artifactId>
|
<artifactId>poi-examples</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.apache.poi</groupId>
|
<groupId>org.apache.poi</groupId>
|
||||||
<artifactId>poi-parent</artifactId>
|
<artifactId>poi-parent</artifactId>
|
||||||
<version>4.0.1-SNAPSHOT</version>
|
<version>4.0.2-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>poi-excelant</artifactId>
|
<artifactId>poi-excelant</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.apache.poi</groupId>
|
<groupId>org.apache.poi</groupId>
|
||||||
<artifactId>poi-parent</artifactId>
|
<artifactId>poi-parent</artifactId>
|
||||||
<version>4.0.1-SNAPSHOT</version>
|
<version>4.0.2-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>poi-main</artifactId>
|
<artifactId>poi-main</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.apache.poi</groupId>
|
<groupId>org.apache.poi</groupId>
|
||||||
<artifactId>poi-parent</artifactId>
|
<artifactId>poi-parent</artifactId>
|
||||||
<version>4.0.1-SNAPSHOT</version>
|
<version>4.0.2-SNAPSHOT</version>
|
||||||
<relativePath>..</relativePath>
|
<relativePath>..</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>poi-ooxml-schema-encryption</artifactId>
|
<artifactId>poi-ooxml-schema-encryption</artifactId>
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.apache.poi</groupId>
|
<groupId>org.apache.poi</groupId>
|
||||||
<artifactId>poi-parent</artifactId>
|
<artifactId>poi-parent</artifactId>
|
||||||
<version>4.0.1-SNAPSHOT</version>
|
<version>4.0.2-SNAPSHOT</version>
|
||||||
<relativePath>..</relativePath>
|
<relativePath>..</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>poi-ooxml-schema-security</artifactId>
|
<artifactId>poi-ooxml-schema-security</artifactId>
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.apache.poi</groupId>
|
<groupId>org.apache.poi</groupId>
|
||||||
<artifactId>poi-parent</artifactId>
|
<artifactId>poi-parent</artifactId>
|
||||||
<version>4.0.1-SNAPSHOT</version>
|
<version>4.0.2-SNAPSHOT</version>
|
||||||
<relativePath>..</relativePath>
|
<relativePath>..</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>poi-ooxml-schema</artifactId>
|
<artifactId>poi-ooxml-schema</artifactId>
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.apache.poi</groupId>
|
<groupId>org.apache.poi</groupId>
|
||||||
<artifactId>poi-parent</artifactId>
|
<artifactId>poi-parent</artifactId>
|
||||||
<version>4.0.1-SNAPSHOT</version>
|
<version>4.0.2-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>poi-ooxml</artifactId>
|
<artifactId>poi-ooxml</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
<groupId>org.apache.poi</groupId>
|
<groupId>org.apache.poi</groupId>
|
||||||
<artifactId>poi-parent</artifactId>
|
<artifactId>poi-parent</artifactId>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
<version>4.0.1-SNAPSHOT</version>
|
<version>4.0.2-SNAPSHOT</version>
|
||||||
<name>Apache POI - the Java API for Microsoft Documents</name>
|
<name>Apache POI - the Java API for Microsoft Documents</name>
|
||||||
<description>Maven build of Apache POI for Sonar checks</description>
|
<description>Maven build of Apache POI for Sonar checks</description>
|
||||||
<url>http://poi.apache.org/</url>
|
<url>http://poi.apache.org/</url>
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.apache.poi</groupId>
|
<groupId>org.apache.poi</groupId>
|
||||||
<artifactId>poi-parent</artifactId>
|
<artifactId>poi-parent</artifactId>
|
||||||
<version>4.0.1-SNAPSHOT</version>
|
<version>4.0.2-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>poi-scratchpad</artifactId>
|
<artifactId>poi-scratchpad</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
@ -289,6 +289,7 @@ public class TestAllFiles {
|
|||||||
"document/Bug50955.doc",
|
"document/Bug50955.doc",
|
||||||
"document/57843.doc",
|
"document/57843.doc",
|
||||||
"slideshow/PPT95.ppt",
|
"slideshow/PPT95.ppt",
|
||||||
|
"slideshow/pp40only.ppt",
|
||||||
"slideshow/Divino_Revelado.pptx",
|
"slideshow/Divino_Revelado.pptx",
|
||||||
"openxml4j/OPCCompliance_CoreProperties_DCTermsNamespaceLimitedUseFAIL.docx",
|
"openxml4j/OPCCompliance_CoreProperties_DCTermsNamespaceLimitedUseFAIL.docx",
|
||||||
"openxml4j/OPCCompliance_CoreProperties_DoNotUseCompatibilityMarkupFAIL.docx",
|
"openxml4j/OPCCompliance_CoreProperties_DoNotUseCompatibilityMarkupFAIL.docx",
|
||||||
|
@ -35,7 +35,6 @@ import java.util.Iterator;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.xml.parsers.ParserConfigurationException;
|
|
||||||
import javax.xml.transform.TransformerException;
|
import javax.xml.transform.TransformerException;
|
||||||
|
|
||||||
import org.apache.poi.EncryptedDocumentException;
|
import org.apache.poi.EncryptedDocumentException;
|
||||||
@ -148,7 +147,7 @@ public class XSSFFileHandler extends SpreadsheetHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void exportToXML(XSSFWorkbook wb) throws SAXException,
|
private void exportToXML(XSSFWorkbook wb) throws SAXException,
|
||||||
ParserConfigurationException, TransformerException {
|
TransformerException {
|
||||||
for (XSSFMap map : wb.getCustomXMLMappings()) {
|
for (XSSFMap map : wb.getCustomXMLMappings()) {
|
||||||
XSSFExportToXml exporter = new XSSFExportToXml(map);
|
XSSFExportToXml exporter = new XSSFExportToXml(map);
|
||||||
|
|
||||||
@ -165,7 +164,6 @@ public class XSSFFileHandler extends SpreadsheetHandler {
|
|||||||
// zip-bomb
|
// zip-bomb
|
||||||
EXPECTED_ADDITIONAL_FAILURES.add("spreadsheet/54764.xlsx");
|
EXPECTED_ADDITIONAL_FAILURES.add("spreadsheet/54764.xlsx");
|
||||||
EXPECTED_ADDITIONAL_FAILURES.add("spreadsheet/54764-2.xlsx");
|
EXPECTED_ADDITIONAL_FAILURES.add("spreadsheet/54764-2.xlsx");
|
||||||
EXPECTED_ADDITIONAL_FAILURES.add("spreadsheet/54764.xlsx");
|
|
||||||
EXPECTED_ADDITIONAL_FAILURES.add("spreadsheet/poc-xmlbomb.xlsx");
|
EXPECTED_ADDITIONAL_FAILURES.add("spreadsheet/poc-xmlbomb.xlsx");
|
||||||
EXPECTED_ADDITIONAL_FAILURES.add("spreadsheet/poc-xmlbomb-empty.xlsx");
|
EXPECTED_ADDITIONAL_FAILURES.add("spreadsheet/poc-xmlbomb-empty.xlsx");
|
||||||
// strict OOXML
|
// strict OOXML
|
||||||
@ -185,18 +183,19 @@ public class XSSFFileHandler extends SpreadsheetHandler {
|
|||||||
public void handleAdditional(File file) throws Exception {
|
public void handleAdditional(File file) throws Exception {
|
||||||
// redirect stdout as the examples often write lots of text
|
// redirect stdout as the examples often write lots of text
|
||||||
PrintStream oldOut = System.out;
|
PrintStream oldOut = System.out;
|
||||||
|
String testFile = file.getParentFile().getName() + "/" + file.getName();
|
||||||
try {
|
try {
|
||||||
System.setOut(new NullPrintStream());
|
System.setOut(new NullPrintStream());
|
||||||
FromHowTo.main(new String[]{file.getAbsolutePath()});
|
FromHowTo.main(new String[]{file.getAbsolutePath()});
|
||||||
XLSX2CSV.main(new String[]{file.getAbsolutePath()});
|
XLSX2CSV.main(new String[]{file.getAbsolutePath()});
|
||||||
|
|
||||||
assertFalse("Expected Extraction to fail for file " + file + " and handler " + this + ", but did not fail!",
|
assertFalse("Expected Extraction to fail for file " + file + " and handler " + this + ", but did not fail!",
|
||||||
EXPECTED_ADDITIONAL_FAILURES.contains(file.getParentFile().getName() + "/" + file.getName()));
|
EXPECTED_ADDITIONAL_FAILURES.contains(testFile));
|
||||||
|
|
||||||
} catch (OLE2NotOfficeXmlFileException e) {
|
} catch (OLE2NotOfficeXmlFileException e) {
|
||||||
// we have some files that are not actually OOXML and thus cannot be tested here
|
// we have some files that are not actually OOXML and thus cannot be tested here
|
||||||
} catch (IllegalArgumentException | InvalidFormatException | POIXMLException | IOException e) {
|
} catch (IllegalArgumentException | InvalidFormatException | POIXMLException | IOException e) {
|
||||||
if(!EXPECTED_ADDITIONAL_FAILURES.contains(file.getParentFile().getName() + "/" + file.getName())) {
|
if(!EXPECTED_ADDITIONAL_FAILURES.contains(testFile)) {
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -36,7 +36,7 @@ import org.apache.poi.util.POILogger;
|
|||||||
* Supports reading and writing of variant data.<p>
|
* Supports reading and writing of variant data.<p>
|
||||||
*
|
*
|
||||||
* <strong>FIXME (3):</strong> Reading and writing should be made more
|
* <strong>FIXME (3):</strong> Reading and writing should be made more
|
||||||
* uniform than it is now. The following items should be resolved:<p>
|
* uniform than it is now. The following items should be resolved:
|
||||||
*
|
*
|
||||||
* <ul>
|
* <ul>
|
||||||
*
|
*
|
||||||
|
@ -33,8 +33,11 @@ import org.apache.poi.hpsf.SummaryInformation;
|
|||||||
* The methods {@link #getSummaryInformationProperties} and {@link
|
* The methods {@link #getSummaryInformationProperties} and {@link
|
||||||
* #getDocumentSummaryInformationProperties} return singleton {@link
|
* #getDocumentSummaryInformationProperties} return singleton {@link
|
||||||
* PropertyIDMap}s. An application that wants to extend these maps
|
* PropertyIDMap}s. An application that wants to extend these maps
|
||||||
* should treat them as unmodifiable, copy them and modifiy the
|
* should treat them as unmodifiable, copy them and modify the
|
||||||
* copies.
|
* copies.
|
||||||
|
*
|
||||||
|
* Trying to modify the map directly will cause exceptions
|
||||||
|
* {@link UnsupportedOperationException} to be thrown.
|
||||||
*/
|
*/
|
||||||
public class PropertyIDMap implements Map<Long,String> {
|
public class PropertyIDMap implements Map<Long,String> {
|
||||||
|
|
||||||
@ -490,11 +493,13 @@ public class PropertyIDMap implements Map<Long,String> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String put(Long key, String value) {
|
public String put(Long key, String value) {
|
||||||
|
//noinspection ConstantConditions
|
||||||
return idMap.put(key, value);
|
return idMap.put(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String remove(Object key) {
|
public String remove(Object key) {
|
||||||
|
//noinspection ConstantConditions
|
||||||
return idMap.remove(key);
|
return idMap.remove(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2276,6 +2276,8 @@ public final class InternalWorkbook {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Only for internal calls - code based on this is not supported ...
|
* Only for internal calls - code based on this is not supported ...
|
||||||
|
*
|
||||||
|
* @return The list of records.
|
||||||
*/
|
*/
|
||||||
@Internal
|
@Internal
|
||||||
public WorkbookRecordList getWorkbookRecordList() {
|
public WorkbookRecordList getWorkbookRecordList() {
|
||||||
|
@ -33,8 +33,9 @@ import org.apache.poi.util.LittleEndianInputStream;
|
|||||||
import org.apache.poi.util.RecordFormatException;
|
import org.apache.poi.util.RecordFormatException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Title: Record Input Stream<P>
|
* Title: Record Input Stream
|
||||||
* Description: Wraps a stream and provides helper methods for the construction of records.<P>
|
*
|
||||||
|
* Description: Wraps a stream and provides helper methods for the construction of records.
|
||||||
*/
|
*/
|
||||||
public final class RecordInputStream implements LittleEndianInput {
|
public final class RecordInputStream implements LittleEndianInput {
|
||||||
|
|
||||||
@ -194,11 +195,11 @@ public final class RecordInputStream implements LittleEndianInput {
|
|||||||
private int readNextSid() {
|
private int readNextSid() {
|
||||||
int nAvailable = _bhi.available();
|
int nAvailable = _bhi.available();
|
||||||
if (nAvailable < EOFRecord.ENCODED_SIZE) {
|
if (nAvailable < EOFRecord.ENCODED_SIZE) {
|
||||||
if (nAvailable > 0) {
|
/*if (nAvailable > 0) {
|
||||||
// some scrap left over?
|
// some scrap left over?
|
||||||
// ex45582-22397.xls has one extra byte after the last record
|
// ex45582-22397.xls has one extra byte after the last record
|
||||||
// Excel reads that file OK
|
// Excel reads that file OK
|
||||||
}
|
}*/
|
||||||
return INVALID_SID_VALUE;
|
return INVALID_SID_VALUE;
|
||||||
}
|
}
|
||||||
int result = _bhi.readRecordSID();
|
int result = _bhi.readRecordSID();
|
||||||
@ -305,14 +306,13 @@ public final class RecordInputStream implements LittleEndianInput {
|
|||||||
@Override
|
@Override
|
||||||
public double readDouble() {
|
public double readDouble() {
|
||||||
long valueLongBits = readLong();
|
long valueLongBits = readLong();
|
||||||
double result = Double.longBitsToDouble(valueLongBits);
|
/*if (Double.isNaN(result)) {
|
||||||
if (Double.isNaN(result)) {
|
|
||||||
// YK: Excel doesn't write NaN but instead converts the cell type into {@link CellType#ERROR}.
|
// YK: Excel doesn't write NaN but instead converts the cell type into {@link CellType#ERROR}.
|
||||||
// HSSF prior to version 3.7 had a bug: it could write Double.NaN but could not read such a file back.
|
// HSSF prior to version 3.7 had a bug: it could write Double.NaN but could not read such a file back.
|
||||||
// This behavior was fixed in POI-3.7.
|
// This behavior was fixed in POI-3.7.
|
||||||
//throw new RuntimeException("Did not expect to read NaN"); // (Because Excel typically doesn't write NaN)
|
//throw new RuntimeException("Did not expect to read NaN"); // (Because Excel typically doesn't write NaN)
|
||||||
}
|
}*/
|
||||||
return result;
|
return Double.longBitsToDouble(valueLongBits);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void readPlain(byte[] buf, int off, int len) {
|
public void readPlain(byte[] buf, int off, int len) {
|
||||||
|
@ -161,7 +161,7 @@ public final class SSTRecord extends ContinuableRecord {
|
|||||||
* <P>
|
* <P>
|
||||||
* The data consists of sets of string data. This string data is
|
* The data consists of sets of string data. This string data is
|
||||||
* arranged as follows:
|
* arranged as follows:
|
||||||
* <P>
|
* </P><P>
|
||||||
* <pre>
|
* <pre>
|
||||||
* short string_length; // length of string data
|
* short string_length; // length of string data
|
||||||
* byte string_flag; // flag specifying special string
|
* byte string_flag; // flag specifying special string
|
||||||
@ -176,9 +176,9 @@ public final class SSTRecord extends ContinuableRecord {
|
|||||||
* byte[] extension; // optional extension (length of array
|
* byte[] extension; // optional extension (length of array
|
||||||
* // is extend_length)
|
* // is extend_length)
|
||||||
* </pre>
|
* </pre>
|
||||||
* <P>
|
* </P><P>
|
||||||
* The string_flag is bit mapped as follows:
|
* The string_flag is bit mapped as follows:
|
||||||
* <P>
|
* </P><P>
|
||||||
* <TABLE summary="string_flag mapping">
|
* <TABLE summary="string_flag mapping">
|
||||||
* <TR>
|
* <TR>
|
||||||
* <TH>Bit number</TH>
|
* <TH>Bit number</TH>
|
||||||
@ -232,7 +232,7 @@ public final class SSTRecord extends ContinuableRecord {
|
|||||||
* associated data. The UnicodeString class can handle the byte[]
|
* associated data. The UnicodeString class can handle the byte[]
|
||||||
* vs short[] nature of the actual string data
|
* vs short[] nature of the actual string data
|
||||||
*
|
*
|
||||||
* @param in the RecordInputstream to read the record from
|
* @param in the RecordInputStream to read the record from
|
||||||
*/
|
*/
|
||||||
public SSTRecord(RecordInputStream in) {
|
public SSTRecord(RecordInputStream in) {
|
||||||
// this method is ALWAYS called after construction -- using
|
// this method is ALWAYS called after construction -- using
|
||||||
|
@ -77,7 +77,7 @@ public final class SharedFormulaRecord extends SharedValueRecordBase {
|
|||||||
|
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
StringBuffer buffer = new StringBuffer();
|
StringBuilder buffer = new StringBuilder();
|
||||||
|
|
||||||
buffer.append("[SHARED FORMULA (").append(HexDump.intToHex(sid)).append("]\n");
|
buffer.append("[SHARED FORMULA (").append(HexDump.intToHex(sid)).append("]\n");
|
||||||
buffer.append(" .range = ").append(getRange()).append("\n");
|
buffer.append(" .range = ").append(getRange()).append("\n");
|
||||||
@ -99,6 +99,10 @@ public final class SharedFormulaRecord extends SharedValueRecordBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Convert formula into an array of {@link Ptg} tokens.
|
||||||
|
*
|
||||||
|
* @param formula The record to break into tokens, cannot be null
|
||||||
|
*
|
||||||
* @return the equivalent {@link Ptg} array that the formula would have, were it not shared.
|
* @return the equivalent {@link Ptg} array that the formula would have, were it not shared.
|
||||||
*/
|
*/
|
||||||
public Ptg[] getFormulaTokens(FormulaRecord formula) {
|
public Ptg[] getFormulaTokens(FormulaRecord formula) {
|
||||||
|
@ -42,6 +42,8 @@ public abstract class SharedValueRecordBase extends StandardRecord {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* reads only the range (1 {@link CellRangeAddress8Bit}) from the stream
|
* reads only the range (1 {@link CellRangeAddress8Bit}) from the stream
|
||||||
|
*
|
||||||
|
* @param in The interface for reading the record data.
|
||||||
*/
|
*/
|
||||||
public SharedValueRecordBase(LittleEndianInput in) {
|
public SharedValueRecordBase(LittleEndianInput in) {
|
||||||
_range = new CellRangeAddress8Bit(in);
|
_range = new CellRangeAddress8Bit(in);
|
||||||
@ -99,14 +101,12 @@ public abstract class SharedValueRecordBase extends StandardRecord {
|
|||||||
&& r.getLastColumn() >= colIx;
|
&& r.getLastColumn() >= colIx;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @return {@code true} if (rowIx, colIx) describes the first cell in this shared value
|
|
||||||
* object's range
|
|
||||||
*
|
|
||||||
* @param rowIx the row index
|
* @param rowIx the row index
|
||||||
* @param colIx the column index
|
* @param colIx the column index
|
||||||
*
|
*
|
||||||
* @return {@code true} if its the first cell in this shared value object range
|
* @return {@code true} if (rowIx, colIx) describes the first cell in this shared value
|
||||||
*
|
* object's range
|
||||||
|
*
|
||||||
* @see #getRange()
|
* @see #getRange()
|
||||||
*/
|
*/
|
||||||
public final boolean isFirstCell(int rowIx, int colIx) {
|
public final boolean isFirstCell(int rowIx, int colIx) {
|
||||||
|
@ -78,7 +78,7 @@ public enum FileMagic {
|
|||||||
/** PDF document */
|
/** PDF document */
|
||||||
PDF("%PDF"),
|
PDF("%PDF"),
|
||||||
/** Some different HTML documents */
|
/** Some different HTML documents */
|
||||||
HTML("<!DOCTYP".getBytes(UTF_8), "<html".getBytes(UTF_8)),
|
HTML("<!DOCTYP".getBytes(UTF_8), "<html".getBytes(UTF_8), "<HTML".getBytes(UTF_8)),
|
||||||
WORD2(new byte[]{ (byte)0xdb, (byte)0xa5, 0x2d, 0x00}),
|
WORD2(new byte[]{ (byte)0xdb, (byte)0xa5, 0x2d, 0x00}),
|
||||||
// keep UNKNOWN always as last enum!
|
// keep UNKNOWN always as last enum!
|
||||||
/** UNKNOWN magic */
|
/** UNKNOWN magic */
|
||||||
@ -101,17 +101,8 @@ public enum FileMagic {
|
|||||||
|
|
||||||
public static FileMagic valueOf(byte[] magic) {
|
public static FileMagic valueOf(byte[] magic) {
|
||||||
for (FileMagic fm : values()) {
|
for (FileMagic fm : values()) {
|
||||||
int i=0;
|
|
||||||
boolean found = true;
|
|
||||||
for (byte[] ma : fm.magic) {
|
for (byte[] ma : fm.magic) {
|
||||||
for (byte m : ma) {
|
if (findMagic(ma, magic)) {
|
||||||
byte d = magic[i++];
|
|
||||||
if (!(d == m || (m == 0x70 && (d == 0x10 || d == 0x20 || d == 0x40)))) {
|
|
||||||
found = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (found) {
|
|
||||||
return fm;
|
return fm;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -119,6 +110,17 @@ public enum FileMagic {
|
|||||||
return UNKNOWN;
|
return UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean findMagic(byte[] cmp, byte[] actual) {
|
||||||
|
int i=0;
|
||||||
|
for (byte m : cmp) {
|
||||||
|
byte d = actual[i++];
|
||||||
|
if (!(d == m || (m == 0x70 && (d == 0x10 || d == 0x20 || d == 0x40)))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the file magic of the supplied {@link File}<p>
|
* Get the file magic of the supplied {@link File}<p>
|
||||||
|
@ -29,7 +29,10 @@ import java.awt.geom.Rectangle2D;
|
|||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
import org.apache.poi.sl.usermodel.AbstractColorStyle;
|
import org.apache.poi.sl.usermodel.AbstractColorStyle;
|
||||||
import org.apache.poi.sl.usermodel.ColorStyle;
|
import org.apache.poi.sl.usermodel.ColorStyle;
|
||||||
@ -197,28 +200,17 @@ public class DrawPaint {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getShade() {
|
public int getShade() {
|
||||||
int shade = orig.getShade();
|
return scale(orig.getShade(), PaintModifier.DARKEN_LESS, PaintModifier.DARKEN);
|
||||||
switch (modifier) {
|
|
||||||
case DARKEN:
|
|
||||||
return Math.min(100000, Math.max(0,shade)+40000);
|
|
||||||
case DARKEN_LESS:
|
|
||||||
return Math.min(100000, Math.max(0,shade)+20000);
|
|
||||||
default:
|
|
||||||
return shade;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getTint() {
|
public int getTint() {
|
||||||
int tint = orig.getTint();
|
return scale(orig.getTint(), PaintModifier.LIGHTEN_LESS, PaintModifier.LIGHTEN);
|
||||||
switch (modifier) {
|
}
|
||||||
case LIGHTEN:
|
|
||||||
return Math.min(100000, Math.max(0,tint)+40000);
|
private int scale(int value, PaintModifier lessModifier, PaintModifier moreModifier) {
|
||||||
case LIGHTEN_LESS:
|
int delta = (modifier == lessModifier ? 20000 : (modifier == moreModifier ? 40000 : 0));
|
||||||
return Math.min(100000, Math.max(0,tint)+20000);
|
return Math.min(100000, Math.max(0,value)+delta);
|
||||||
default:
|
|
||||||
return tint;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -300,7 +292,7 @@ public class DrawPaint {
|
|||||||
Color result = color.getColor();
|
Color result = color.getColor();
|
||||||
|
|
||||||
double alpha = getAlpha(result, color);
|
double alpha = getAlpha(result, color);
|
||||||
double hsl[] = RGB2HSL(result); // values are in the range [0..100] (usually ...)
|
double[] hsl = RGB2HSL(result); // values are in the range [0..100] (usually ...)
|
||||||
applyHslModOff(hsl, 0, color.getHueMod(), color.getHueOff());
|
applyHslModOff(hsl, 0, color.getHueMod(), color.getHueOff());
|
||||||
applyHslModOff(hsl, 1, color.getSatMod(), color.getSatOff());
|
applyHslModOff(hsl, 1, color.getSatMod(), color.getSatOff());
|
||||||
applyHslModOff(hsl, 2, color.getLumMod(), color.getLumOff());
|
applyHslModOff(hsl, 2, color.getLumMod(), color.getLumOff());
|
||||||
@ -344,7 +336,7 @@ public class DrawPaint {
|
|||||||
* @param mod the modulation adjustment
|
* @param mod the modulation adjustment
|
||||||
* @param off the offset adjustment
|
* @param off the offset adjustment
|
||||||
*/
|
*/
|
||||||
private static void applyHslModOff(double hsl[], int hslPart, int mod, int off) {
|
private static void applyHslModOff(double[] hsl, int hslPart, int mod, int off) {
|
||||||
if (mod == -1) {
|
if (mod == -1) {
|
||||||
mod = 100000;
|
mod = 100000;
|
||||||
}
|
}
|
||||||
@ -363,7 +355,7 @@ public class DrawPaint {
|
|||||||
*
|
*
|
||||||
* For a shade, the equation is luminance * %tint.
|
* For a shade, the equation is luminance * %tint.
|
||||||
*/
|
*/
|
||||||
private static void applyShade(double hsl[], ColorStyle fc) {
|
private static void applyShade(double[] hsl, ColorStyle fc) {
|
||||||
int shade = fc.getShade();
|
int shade = fc.getShade();
|
||||||
if (shade == -1) {
|
if (shade == -1) {
|
||||||
return;
|
return;
|
||||||
@ -380,7 +372,7 @@ public class DrawPaint {
|
|||||||
* For a tint, the equation is luminance * %tint + (1-%tint).
|
* For a tint, the equation is luminance * %tint + (1-%tint).
|
||||||
* (Note that 1-%tint is equal to the lumOff value in DrawingML.)
|
* (Note that 1-%tint is equal to the lumOff value in DrawingML.)
|
||||||
*/
|
*/
|
||||||
private static void applyTint(double hsl[], ColorStyle fc) {
|
private static void applyTint(double[] hsl, ColorStyle fc) {
|
||||||
int tint = fc.getTint();
|
int tint = fc.getTint();
|
||||||
if (tint == -1) {
|
if (tint == -1) {
|
||||||
return;
|
return;
|
||||||
@ -403,70 +395,63 @@ public class DrawPaint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Rectangle2D anchor = DrawShape.getAnchor(graphics, shape);
|
Rectangle2D anchor = DrawShape.getAnchor(graphics, shape);
|
||||||
final double h = anchor.getHeight(), w = anchor.getWidth(), x = anchor.getX(), y = anchor.getY();
|
|
||||||
|
|
||||||
AffineTransform at = AffineTransform.getRotateInstance(Math.toRadians(angle), anchor.getCenterX(), anchor.getCenterY());
|
AffineTransform at = AffineTransform.getRotateInstance(Math.toRadians(angle), anchor.getCenterX(), anchor.getCenterY());
|
||||||
|
|
||||||
double diagonal = Math.sqrt(h * h + w * w);
|
double diagonal = Math.sqrt(Math.pow(anchor.getWidth(),2) + Math.pow(anchor.getHeight(),2));
|
||||||
Point2D p1 = new Point2D.Double(x + w / 2 - diagonal / 2, y + h / 2);
|
final Point2D p1 = at.transform(new Point2D.Double(anchor.getCenterX() - diagonal / 2, anchor.getCenterY()), null);
|
||||||
p1 = at.transform(p1, null);
|
final Point2D p2 = at.transform(new Point2D.Double(anchor.getMaxX(), anchor.getCenterY()), null);
|
||||||
|
|
||||||
Point2D p2 = new Point2D.Double(x + w, y + h / 2);
|
|
||||||
p2 = at.transform(p2, null);
|
|
||||||
|
|
||||||
// snapToAnchor(p1, anchor);
|
// snapToAnchor(p1, anchor);
|
||||||
// snapToAnchor(p2, anchor);
|
// snapToAnchor(p2, anchor);
|
||||||
|
|
||||||
if (p1.equals(p2)) {
|
// gradient paint on the same point throws an exception ... and doesn't make sense
|
||||||
// gradient paint on the same point throws an exception ... and doesn't make sense
|
return (p1.equals(p2)) ? null : safeFractions((f,c)->new LinearGradientPaint(p1,p2,f,c), fill);
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
float[] fractions = fill.getGradientFractions();
|
|
||||||
Color[] colors = new Color[fractions.length];
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
for (ColorStyle fc : fill.getGradientColors()) {
|
|
||||||
// if fc is null, use transparent color to get color of background
|
|
||||||
colors[i++] = (fc == null) ? TRANSPARENT : applyColorTransform(fc);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new LinearGradientPaint(p1, p2, fractions, colors);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@SuppressWarnings("WeakerAccess")
|
@SuppressWarnings("WeakerAccess")
|
||||||
protected Paint createRadialGradientPaint(GradientPaint fill, Graphics2D graphics) {
|
protected Paint createRadialGradientPaint(GradientPaint fill, Graphics2D graphics) {
|
||||||
Rectangle2D anchor = DrawShape.getAnchor(graphics, shape);
|
Rectangle2D anchor = DrawShape.getAnchor(graphics, shape);
|
||||||
|
|
||||||
Point2D pCenter = new Point2D.Double(anchor.getX() + anchor.getWidth()/2,
|
final Point2D pCenter = new Point2D.Double(anchor.getCenterX(), anchor.getCenterY());
|
||||||
anchor.getY() + anchor.getHeight()/2);
|
|
||||||
|
|
||||||
float radius = (float)Math.max(anchor.getWidth(), anchor.getHeight());
|
final float radius = (float)Math.max(anchor.getWidth(), anchor.getHeight());
|
||||||
|
|
||||||
float[] fractions = fill.getGradientFractions();
|
return safeFractions((f,c)->new RadialGradientPaint(pCenter,radius,f,c), fill);
|
||||||
Color[] colors = new Color[fractions.length];
|
|
||||||
|
|
||||||
int i=0;
|
|
||||||
for (ColorStyle fc : fill.getGradientColors()) {
|
|
||||||
colors[i++] = applyColorTransform(fc);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new RadialGradientPaint(pCenter, radius, fractions, colors);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings({"WeakerAccess", "unused"})
|
@SuppressWarnings({"WeakerAccess", "unused"})
|
||||||
protected Paint createPathGradientPaint(GradientPaint fill, Graphics2D graphics) {
|
protected Paint createPathGradientPaint(GradientPaint fill, Graphics2D graphics) {
|
||||||
// currently we ignore an eventually center setting
|
// currently we ignore an eventually center setting
|
||||||
|
|
||||||
float[] fractions = fill.getGradientFractions();
|
return safeFractions(PathGradientPaint::new, fill);
|
||||||
Color[] colors = new Color[fractions.length];
|
}
|
||||||
|
|
||||||
int i=0;
|
private Paint safeFractions(BiFunction<float[],Color[],Paint> init, GradientPaint fill) {
|
||||||
for (ColorStyle fc : fill.getGradientColors()) {
|
float[] fractions = fill.getGradientFractions();
|
||||||
colors[i++] = applyColorTransform(fc);
|
final ColorStyle[] styles = fill.getGradientColors();
|
||||||
|
|
||||||
|
// need to remap the fractions, because Java doesn't like repeating fraction values
|
||||||
|
Map<Float,Color> m = new TreeMap<>();
|
||||||
|
for (int i = 0; i<fractions.length; i++) {
|
||||||
|
// if fc is null, use transparent color to get color of background
|
||||||
|
m.put(fractions[i], (styles[i] == null ? TRANSPARENT : applyColorTransform(styles[i])));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new PathGradientPaint(colors, fractions);
|
final Color[] colors = new Color[m.size()];
|
||||||
|
if (fractions.length != m.size()) {
|
||||||
|
fractions = new float[m.size()];
|
||||||
|
}
|
||||||
|
|
||||||
|
int i=0;
|
||||||
|
for (Map.Entry<Float,Color> me : m.entrySet()) {
|
||||||
|
fractions[i] = me.getKey();
|
||||||
|
colors[i] = me.getValue();
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return init.apply(fractions, colors);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -23,21 +23,24 @@ import java.awt.MultipleGradientPaint.CycleMethod;
|
|||||||
import java.awt.geom.*;
|
import java.awt.geom.*;
|
||||||
import java.awt.image.*;
|
import java.awt.image.*;
|
||||||
|
|
||||||
|
import org.apache.poi.util.Internal;
|
||||||
|
|
||||||
|
@Internal
|
||||||
class PathGradientPaint implements Paint {
|
class PathGradientPaint implements Paint {
|
||||||
|
|
||||||
// http://asserttrue.blogspot.de/2010/01/how-to-iimplement-custom-paint-in-50.html
|
// http://asserttrue.blogspot.de/2010/01/how-to-iimplement-custom-paint-in-50.html
|
||||||
protected final Color colors[];
|
private final Color[] colors;
|
||||||
protected final float fractions[];
|
private final float[] fractions;
|
||||||
protected final int capStyle;
|
private final int capStyle;
|
||||||
protected final int joinStyle;
|
private final int joinStyle;
|
||||||
protected final int transparency;
|
private final int transparency;
|
||||||
|
|
||||||
|
|
||||||
public PathGradientPaint(Color colors[], float fractions[]) {
|
PathGradientPaint(float[] fractions, Color[] colors) {
|
||||||
this(colors,fractions,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND);
|
this(fractions,colors,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PathGradientPaint(Color colors[], float fractions[], int capStyle, int joinStyle) {
|
private PathGradientPaint(float[] fractions, Color[] colors, int capStyle, int joinStyle) {
|
||||||
this.colors = colors.clone();
|
this.colors = colors.clone();
|
||||||
this.fractions = fractions.clone();
|
this.fractions = fractions.clone();
|
||||||
this.capStyle = capStyle;
|
this.capStyle = capStyle;
|
||||||
@ -66,26 +69,26 @@ class PathGradientPaint implements Paint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class PathGradientContext implements PaintContext {
|
class PathGradientContext implements PaintContext {
|
||||||
protected final Rectangle deviceBounds;
|
final Rectangle deviceBounds;
|
||||||
protected final Rectangle2D userBounds;
|
final Rectangle2D userBounds;
|
||||||
protected final AffineTransform xform;
|
protected final AffineTransform xform;
|
||||||
protected final RenderingHints hints;
|
final RenderingHints hints;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* for POI: the shape will be only known when the subclasses determines the concrete implementation
|
* for POI: the shape will be only known when the subclasses determines the concrete implementation
|
||||||
* in the draw/-content method, so we need to postpone the setting/creation as long as possible
|
* in the draw/-content method, so we need to postpone the setting/creation as long as possible
|
||||||
**/
|
**/
|
||||||
protected final Shape shape;
|
protected final Shape shape;
|
||||||
protected final PaintContext pCtx;
|
final PaintContext pCtx;
|
||||||
protected final int gradientSteps;
|
final int gradientSteps;
|
||||||
WritableRaster raster;
|
WritableRaster raster;
|
||||||
|
|
||||||
public PathGradientContext(
|
PathGradientContext(
|
||||||
ColorModel cm
|
ColorModel cm
|
||||||
, Rectangle deviceBounds
|
, Rectangle deviceBounds
|
||||||
, Rectangle2D userBounds
|
, Rectangle2D userBounds
|
||||||
, AffineTransform xform
|
, AffineTransform xform
|
||||||
, RenderingHints hints
|
, RenderingHints hints
|
||||||
) {
|
) {
|
||||||
shape = (Shape)hints.get(Drawable.GRADIENT_SHAPE);
|
shape = (Shape)hints.get(Drawable.GRADIENT_SHAPE);
|
||||||
if (shape == null) {
|
if (shape == null) {
|
||||||
@ -139,7 +142,7 @@ class PathGradientPaint implements Paint {
|
|||||||
return childRaster;
|
return childRaster;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int getGradientSteps(Shape gradientShape) {
|
int getGradientSteps(Shape gradientShape) {
|
||||||
Rectangle rect = gradientShape.getBounds();
|
Rectangle rect = gradientShape.getBounds();
|
||||||
int lower = 1;
|
int lower = 1;
|
||||||
int upper = (int)(Math.max(rect.getWidth(),rect.getHeight())/2.0);
|
int upper = (int)(Math.max(rect.getWidth(),rect.getHeight())/2.0);
|
||||||
@ -158,7 +161,7 @@ class PathGradientPaint implements Paint {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
protected void createRaster() {
|
void createRaster() {
|
||||||
ColorModel cm = getColorModel();
|
ColorModel cm = getColorModel();
|
||||||
raster = cm.createCompatibleWritableRaster((int)deviceBounds.getWidth(), (int)deviceBounds.getHeight());
|
raster = cm.createCompatibleWritableRaster((int)deviceBounds.getWidth(), (int)deviceBounds.getHeight());
|
||||||
BufferedImage img = new BufferedImage(cm, raster, false, null);
|
BufferedImage img = new BufferedImage(cm, raster, false, null);
|
||||||
@ -168,7 +171,7 @@ class PathGradientPaint implements Paint {
|
|||||||
graphics.transform(xform);
|
graphics.transform(xform);
|
||||||
|
|
||||||
Raster img2 = pCtx.getRaster(0, 0, gradientSteps, 1);
|
Raster img2 = pCtx.getRaster(0, 0, gradientSteps, 1);
|
||||||
int rgb[] = new int[cm.getNumComponents()];
|
int[] rgb = new int[cm.getNumComponents()];
|
||||||
|
|
||||||
for (int i = gradientSteps-1; i>=0; i--) {
|
for (int i = gradientSteps-1; i>=0; i--) {
|
||||||
img2.getPixel(i, 0, rgb);
|
img2.getPixel(i, 0, rgb);
|
||||||
|
@ -59,6 +59,7 @@ public final class SheetNameFormatter {
|
|||||||
* @param rawSheetName - sheet name
|
* @param rawSheetName - sheet name
|
||||||
* @deprecated use <code>appendFormat(StringBuilder out, String rawSheetName)</code> instead
|
* @deprecated use <code>appendFormat(StringBuilder out, String rawSheetName)</code> instead
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public static void appendFormat(StringBuffer out, String rawSheetName) {
|
public static void appendFormat(StringBuffer out, String rawSheetName) {
|
||||||
boolean needsQuotes = needsDelimiting(rawSheetName);
|
boolean needsQuotes = needsDelimiting(rawSheetName);
|
||||||
if(needsQuotes) {
|
if(needsQuotes) {
|
||||||
@ -73,6 +74,7 @@ public final class SheetNameFormatter {
|
|||||||
/**
|
/**
|
||||||
* @deprecated use <code>appendFormat(StringBuilder out, String workbookName, String rawSheetName)</code> instead
|
* @deprecated use <code>appendFormat(StringBuilder out, String workbookName, String rawSheetName)</code> instead
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public static void appendFormat(StringBuffer out, String workbookName, String rawSheetName) {
|
public static void appendFormat(StringBuffer out, String workbookName, String rawSheetName) {
|
||||||
boolean needsQuotes = needsDelimiting(workbookName) || needsDelimiting(rawSheetName);
|
boolean needsQuotes = needsDelimiting(workbookName) || needsDelimiting(rawSheetName);
|
||||||
if(needsQuotes) {
|
if(needsQuotes) {
|
||||||
@ -123,7 +125,7 @@ public final class SheetNameFormatter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void appendAndEscape(Appendable sb, String rawSheetName) {
|
static void appendAndEscape(Appendable sb, String rawSheetName) {
|
||||||
int len = rawSheetName.length();
|
int len = rawSheetName.length();
|
||||||
for(int i=0; i<len; i++) {
|
for(int i=0; i<len; i++) {
|
||||||
char ch = rawSheetName.charAt(i);
|
char ch = rawSheetName.charAt(i);
|
||||||
@ -139,7 +141,12 @@ public final class SheetNameFormatter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean needsDelimiting(String rawSheetName) {
|
/**
|
||||||
|
* Tell if the given raw sheet name needs screening/delimiting.
|
||||||
|
* @param rawSheetName the sheet name.
|
||||||
|
* @return true if the given raw sheet name needs screening/delimiting, false otherwise.
|
||||||
|
*/
|
||||||
|
static boolean needsDelimiting(String rawSheetName) {
|
||||||
int len = rawSheetName.length();
|
int len = rawSheetName.length();
|
||||||
if(len < 1) {
|
if(len < 1) {
|
||||||
throw new RuntimeException("Zero length string is an invalid sheet name");
|
throw new RuntimeException("Zero length string is an invalid sheet name");
|
||||||
|
@ -0,0 +1,73 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
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.ss.formula;
|
||||||
|
|
||||||
|
public class SheetRangeAndWorkbookIndexFormatter {
|
||||||
|
private SheetRangeAndWorkbookIndexFormatter() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String format(StringBuilder sb, int workbookIndex, String firstSheetName, String lastSheetName) {
|
||||||
|
if (anySheetNameNeedsEscaping(firstSheetName, lastSheetName)) {
|
||||||
|
return formatWithDelimiting(sb, workbookIndex, firstSheetName, lastSheetName);
|
||||||
|
} else {
|
||||||
|
return formatWithoutDelimiting(sb, workbookIndex, firstSheetName, lastSheetName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String formatWithDelimiting(StringBuilder sb, int workbookIndex, String firstSheetName, String lastSheetName) {
|
||||||
|
sb.append('\'');
|
||||||
|
if (workbookIndex >= 0) {
|
||||||
|
sb.append('[');
|
||||||
|
sb.append(workbookIndex);
|
||||||
|
sb.append(']');
|
||||||
|
}
|
||||||
|
|
||||||
|
SheetNameFormatter.appendAndEscape(sb, firstSheetName);
|
||||||
|
|
||||||
|
if (lastSheetName != null) {
|
||||||
|
sb.append(':');
|
||||||
|
SheetNameFormatter.appendAndEscape(sb, lastSheetName);
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.append('\'');
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String formatWithoutDelimiting(StringBuilder sb, int workbookIndex, String firstSheetName, String lastSheetName) {
|
||||||
|
if (workbookIndex >= 0) {
|
||||||
|
sb.append('[');
|
||||||
|
sb.append(workbookIndex);
|
||||||
|
sb.append(']');
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.append(firstSheetName);
|
||||||
|
|
||||||
|
if (lastSheetName != null) {
|
||||||
|
sb.append(':');
|
||||||
|
sb.append(lastSheetName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean anySheetNameNeedsEscaping(String firstSheetName, String lastSheetName) {
|
||||||
|
boolean anySheetNameNeedsDelimiting = firstSheetName != null && SheetNameFormatter.needsDelimiting(firstSheetName);
|
||||||
|
anySheetNameNeedsDelimiting |= lastSheetName != null && SheetNameFormatter.needsDelimiting(lastSheetName);
|
||||||
|
return anySheetNameNeedsDelimiting;
|
||||||
|
}
|
||||||
|
}
|
@ -20,6 +20,7 @@ package org.apache.poi.ss.formula.ptg;
|
|||||||
import org.apache.poi.ss.SpreadsheetVersion;
|
import org.apache.poi.ss.SpreadsheetVersion;
|
||||||
import org.apache.poi.ss.formula.SheetIdentifier;
|
import org.apache.poi.ss.formula.SheetIdentifier;
|
||||||
import org.apache.poi.ss.formula.SheetNameFormatter;
|
import org.apache.poi.ss.formula.SheetNameFormatter;
|
||||||
|
import org.apache.poi.ss.formula.SheetRangeAndWorkbookIndexFormatter;
|
||||||
import org.apache.poi.ss.formula.SheetRangeIdentifier;
|
import org.apache.poi.ss.formula.SheetRangeIdentifier;
|
||||||
import org.apache.poi.ss.util.AreaReference;
|
import org.apache.poi.ss.util.AreaReference;
|
||||||
import org.apache.poi.util.LittleEndianOutput;
|
import org.apache.poi.util.LittleEndianOutput;
|
||||||
@ -102,16 +103,8 @@ public final class Area3DPxg extends AreaPtgBase implements Pxg3D {
|
|||||||
|
|
||||||
public String toFormulaString() {
|
public String toFormulaString() {
|
||||||
StringBuilder sb = new StringBuilder(64);
|
StringBuilder sb = new StringBuilder(64);
|
||||||
if (externalWorkbookNumber >= 0) {
|
|
||||||
sb.append('[');
|
SheetRangeAndWorkbookIndexFormatter.format(sb, externalWorkbookNumber, firstSheetName, lastSheetName);
|
||||||
sb.append(externalWorkbookNumber);
|
|
||||||
sb.append(']');
|
|
||||||
}
|
|
||||||
SheetNameFormatter.appendFormat(sb, firstSheetName);
|
|
||||||
if (lastSheetName != null) {
|
|
||||||
sb.append(':');
|
|
||||||
SheetNameFormatter.appendFormat(sb, lastSheetName);
|
|
||||||
}
|
|
||||||
sb.append('!');
|
sb.append('!');
|
||||||
sb.append(formatReferenceAsString());
|
sb.append(formatReferenceAsString());
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
package org.apache.poi.ss.formula.ptg;
|
package org.apache.poi.ss.formula.ptg;
|
||||||
|
|
||||||
import org.apache.poi.ss.formula.SheetIdentifier;
|
import org.apache.poi.ss.formula.SheetIdentifier;
|
||||||
import org.apache.poi.ss.formula.SheetNameFormatter;
|
import org.apache.poi.ss.formula.SheetRangeAndWorkbookIndexFormatter;
|
||||||
import org.apache.poi.ss.formula.SheetRangeIdentifier;
|
import org.apache.poi.ss.formula.SheetRangeIdentifier;
|
||||||
import org.apache.poi.ss.util.CellReference;
|
import org.apache.poi.ss.util.CellReference;
|
||||||
import org.apache.poi.util.LittleEndianOutput;
|
import org.apache.poi.util.LittleEndianOutput;
|
||||||
@ -101,18 +101,8 @@ public final class Ref3DPxg extends RefPtgBase implements Pxg3D {
|
|||||||
|
|
||||||
public String toFormulaString() {
|
public String toFormulaString() {
|
||||||
StringBuilder sb = new StringBuilder(64);
|
StringBuilder sb = new StringBuilder(64);
|
||||||
if (externalWorkbookNumber >= 0) {
|
|
||||||
sb.append('[');
|
SheetRangeAndWorkbookIndexFormatter.format(sb, externalWorkbookNumber, firstSheetName, lastSheetName);
|
||||||
sb.append(externalWorkbookNumber);
|
|
||||||
sb.append(']');
|
|
||||||
}
|
|
||||||
if (firstSheetName != null) {
|
|
||||||
SheetNameFormatter.appendFormat(sb, firstSheetName);
|
|
||||||
}
|
|
||||||
if (lastSheetName != null) {
|
|
||||||
sb.append(':');
|
|
||||||
SheetNameFormatter.appendFormat(sb, lastSheetName);
|
|
||||||
}
|
|
||||||
sb.append('!');
|
sb.append('!');
|
||||||
sb.append(formatReferenceAsString());
|
sb.append(formatReferenceAsString());
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
|
@ -45,8 +45,8 @@ public class RecordFormatException
|
|||||||
* be thrown. If assertTrue is <code>false</code>, this will throw this
|
* be thrown. If assertTrue is <code>false</code>, this will throw this
|
||||||
* exception with the message.
|
* exception with the message.
|
||||||
*
|
*
|
||||||
* @param assertTrue
|
* @param assertTrue If false, the exception is thrown, if true, no action is performed
|
||||||
* @param message
|
* @param message The message to include in the thrown exception
|
||||||
*/
|
*/
|
||||||
public static void check(boolean assertTrue, String message) {
|
public static void check(boolean assertTrue, String message) {
|
||||||
if (! assertTrue) {
|
if (! assertTrue) {
|
||||||
|
@ -615,7 +615,7 @@ public class POIXMLDocumentPart {
|
|||||||
protected void read(POIXMLFactory factory, Map<PackagePart, POIXMLDocumentPart> context) throws OpenXML4JException {
|
protected void read(POIXMLFactory factory, Map<PackagePart, POIXMLDocumentPart> context) throws OpenXML4JException {
|
||||||
PackagePart pp = getPackagePart();
|
PackagePart pp = getPackagePart();
|
||||||
|
|
||||||
if (pp.getContentType().equals(XWPFRelation.TEMPLATE.getContentType())) {
|
if (pp.getContentType().equals(XWPFRelation.GLOSSARY_DOCUMENT.getContentType())) {
|
||||||
logger.log(POILogger.WARN,
|
logger.log(POILogger.WARN,
|
||||||
"POI does not currently support template.main+xml (glossary) parts. " +
|
"POI does not currently support template.main+xml (glossary) parts. " +
|
||||||
"Skipping this part for now.");
|
"Skipping this part for now.");
|
||||||
|
@ -22,41 +22,37 @@ import org.apache.poi.extractor.POITextExtractor;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* A command line wrapper around {@link ExtractorFactory}, useful
|
* A command line wrapper around {@link ExtractorFactory}, useful
|
||||||
* for when debugging.
|
* for when debugging.
|
||||||
*/
|
*/
|
||||||
public class CommandLineTextExtractor {
|
public class CommandLineTextExtractor {
|
||||||
public static final String DIVIDER = "=======================";
|
public static final String DIVIDER = "=======================";
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
|
||||||
if(args.length < 1) {
|
|
||||||
System.err.println("Use:");
|
|
||||||
System.err.println(" CommandLineTextExtractor <filename> [filename] [filename]");
|
|
||||||
System.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (String arg : args) {
|
public static void main(String[] args) throws Exception {
|
||||||
System.out.println(DIVIDER);
|
if (args.length < 1) {
|
||||||
|
System.err.println("Use:");
|
||||||
|
System.err.println(" CommandLineTextExtractor <filename> [filename] [filename]");
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
File f = new File(arg);
|
for (String arg : args) {
|
||||||
System.out.println(f);
|
System.out.println(DIVIDER);
|
||||||
|
|
||||||
POITextExtractor extractor =
|
File f = new File(arg);
|
||||||
ExtractorFactory.createExtractor(f);
|
System.out.println(f);
|
||||||
try {
|
|
||||||
POITextExtractor metadataExtractor =
|
|
||||||
extractor.getMetadataTextExtractor();
|
|
||||||
|
|
||||||
System.out.println(" " + DIVIDER);
|
try (POITextExtractor extractor = ExtractorFactory.createExtractor(f)) {
|
||||||
String metaData = metadataExtractor.getText();
|
POITextExtractor metadataExtractor =
|
||||||
System.out.println(metaData);
|
extractor.getMetadataTextExtractor();
|
||||||
System.out.println(" " + DIVIDER);
|
|
||||||
String text = extractor.getText();
|
System.out.println(" " + DIVIDER);
|
||||||
System.out.println(text);
|
String metaData = metadataExtractor.getText();
|
||||||
System.out.println(DIVIDER);
|
System.out.println(metaData);
|
||||||
System.out.println("Had " + metaData.length() + " characters of metadata and " + text.length() + " characters of text");
|
System.out.println(" " + DIVIDER);
|
||||||
} finally {
|
String text = extractor.getText();
|
||||||
extractor.close();
|
System.out.println(text);
|
||||||
}
|
System.out.println(DIVIDER);
|
||||||
}
|
System.out.println("Had " + metaData.length() + " characters of metadata and " + text.length() + " characters of text");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -154,8 +154,6 @@ public final class ZipHelper {
|
|||||||
"The supplied data appears to be a raw XML file. " +
|
"The supplied data appears to be a raw XML file. " +
|
||||||
"Formats such as Office 2003 XML are not supported");
|
"Formats such as Office 2003 XML are not supported");
|
||||||
default:
|
default:
|
||||||
case OOXML:
|
|
||||||
case UNKNOWN:
|
|
||||||
// Don't check for a Zip header, as to maintain backwards
|
// Don't check for a Zip header, as to maintain backwards
|
||||||
// compatibility we need to let them seek over junk at the
|
// compatibility we need to let them seek over junk at the
|
||||||
// start before beginning processing.
|
// start before beginning processing.
|
||||||
|
@ -38,7 +38,7 @@ public class ZipInputStreamZipEntrySource implements ZipEntrySource {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads all the entries from the ZipInputStream
|
* Reads all the entries from the ZipInputStream
|
||||||
* into memory, and closes the source stream.
|
* into memory, and don't close (since POI 4.0.1) the source stream.
|
||||||
* We'll then eat lots of memory, but be able to
|
* We'll then eat lots of memory, but be able to
|
||||||
* work with the entries at-will.
|
* work with the entries at-will.
|
||||||
*/
|
*/
|
||||||
@ -50,7 +50,6 @@ public class ZipInputStreamZipEntrySource implements ZipEntrySource {
|
|||||||
}
|
}
|
||||||
zipEntries.put(zipEntry.getName(), new ZipArchiveFakeEntry(zipEntry, inp));
|
zipEntries.put(zipEntry.getName(), new ZipArchiveFakeEntry(zipEntry, inp));
|
||||||
}
|
}
|
||||||
inp.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -170,16 +170,24 @@ public class XSLFPictureShape extends XSLFSimpleShape
|
|||||||
|
|
||||||
@SuppressWarnings("WeakerAccess")
|
@SuppressWarnings("WeakerAccess")
|
||||||
protected String getBlipLink(){
|
protected String getBlipLink(){
|
||||||
String link = getBlip().getLink();
|
CTBlip blip = getBlip();
|
||||||
if (link.isEmpty()) return null;
|
if (blip != null) {
|
||||||
return link;
|
String link = blip.getLink();
|
||||||
|
return (link.isEmpty()) ? null : link;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("WeakerAccess")
|
@SuppressWarnings("WeakerAccess")
|
||||||
protected String getBlipId(){
|
protected String getBlipId(){
|
||||||
String id = getBlip().getEmbed();
|
CTBlip blip = getBlip();
|
||||||
if (id.isEmpty()) return null;
|
if (blip != null) {
|
||||||
return id;
|
String id = blip.getEmbed();
|
||||||
|
return (id.isEmpty()) ? null : id;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -19,6 +19,7 @@ package org.apache.poi.ooxml;
|
|||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertNotSame;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
@ -89,7 +90,7 @@ public final class TestPOIXMLProperties {
|
|||||||
XSSFWorkbook newWorkbook =
|
XSSFWorkbook newWorkbook =
|
||||||
XSSFTestDataSamples.writeOutAndReadBack(workbook);
|
XSSFTestDataSamples.writeOutAndReadBack(workbook);
|
||||||
workbook.close();
|
workbook.close();
|
||||||
assertTrue(workbook != newWorkbook);
|
assertNotSame(workbook, newWorkbook);
|
||||||
|
|
||||||
|
|
||||||
POIXMLProperties newProps = newWorkbook.getProperties();
|
POIXMLProperties newProps = newWorkbook.getProperties();
|
||||||
@ -158,7 +159,7 @@ public final class TestPOIXMLProperties {
|
|||||||
p = ctProps.getPropertyArray(3);
|
p = ctProps.getPropertyArray(3);
|
||||||
assertEquals("{D5CDD505-2E9C-101B-9397-08002B2CF9AE}", p.getFmtid());
|
assertEquals("{D5CDD505-2E9C-101B-9397-08002B2CF9AE}", p.getFmtid());
|
||||||
assertEquals("test-4", p.getName());
|
assertEquals("test-4", p.getName());
|
||||||
assertEquals(true, p.getBool());
|
assertTrue(p.getBool());
|
||||||
assertEquals(5, p.getPid());
|
assertEquals(5, p.getPid());
|
||||||
|
|
||||||
wb2.close();
|
wb2.close();
|
||||||
|
@ -87,6 +87,10 @@ public class TestNecessaryOOXMLClasses {
|
|||||||
Assert.assertNotNull(ctLblAlgn);
|
Assert.assertNotNull(ctLblAlgn);
|
||||||
CTDashStopList ctDashStopList = CTDashStopList.Factory.newInstance();
|
CTDashStopList ctDashStopList = CTDashStopList.Factory.newInstance();
|
||||||
Assert.assertNotNull(ctDashStopList);
|
Assert.assertNotNull(ctDashStopList);
|
||||||
|
STDispBlanksAs stDashBlanksAs = STDispBlanksAs.Factory.newInstance();
|
||||||
|
Assert.assertNotNull(stDashBlanksAs);
|
||||||
|
CTDispBlanksAs ctDashBlanksAs = CTDispBlanksAs.Factory.newInstance();
|
||||||
|
Assert.assertNotNull(ctDashBlanksAs);
|
||||||
|
|
||||||
STLblAlgn.Enum e1 = STLblAlgn.Enum.forString("ctr");
|
STLblAlgn.Enum e1 = STLblAlgn.Enum.forString("ctr");
|
||||||
Assert.assertNotNull(e1);
|
Assert.assertNotNull(e1);
|
||||||
@ -100,6 +104,8 @@ public class TestNecessaryOOXMLClasses {
|
|||||||
Assert.assertNotNull(e5);
|
Assert.assertNotNull(e5);
|
||||||
STMarkerStyle.Enum e6 = STMarkerStyle.Enum.forString("circle");
|
STMarkerStyle.Enum e6 = STMarkerStyle.Enum.forString("circle");
|
||||||
Assert.assertNotNull(e6);
|
Assert.assertNotNull(e6);
|
||||||
|
STDispBlanksAs.Enum e7 = STDispBlanksAs.Enum.forString("span");
|
||||||
|
Assert.assertNotNull(e7);
|
||||||
|
|
||||||
CTTextBulletTypefaceFollowText ctTextBulletTypefaceFollowText = CTTextBulletTypefaceFollowText.Factory.newInstance();
|
CTTextBulletTypefaceFollowText ctTextBulletTypefaceFollowText = CTTextBulletTypefaceFollowText.Factory.newInstance();
|
||||||
Assert.assertNotNull(ctTextBulletTypefaceFollowText);
|
Assert.assertNotNull(ctTextBulletTypefaceFollowText);
|
||||||
|
@ -42,7 +42,7 @@ public class TestXDGFVisioExtractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void closeResoures() throws IOException {
|
public void closeResources() throws IOException {
|
||||||
if(xml != null) {
|
if(xml != null) {
|
||||||
xml.close();
|
xml.close();
|
||||||
}
|
}
|
||||||
|
@ -17,12 +17,7 @@
|
|||||||
package org.apache.poi.xslf;
|
package org.apache.poi.xslf;
|
||||||
|
|
||||||
import static org.apache.poi.POITestCase.assertContains;
|
import static org.apache.poi.POITestCase.assertContains;
|
||||||
import static org.junit.Assert.assertArrayEquals;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
|
||||||
import static org.junit.Assert.assertNull;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
import static org.junit.Assert.fail;
|
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
@ -93,6 +88,25 @@ import org.openxmlformats.schemas.presentationml.x2006.main.CTShape;
|
|||||||
public class TestXSLFBugs {
|
public class TestXSLFBugs {
|
||||||
private static final POIDataSamples slTests = POIDataSamples.getSlideShowInstance();
|
private static final POIDataSamples slTests = POIDataSamples.getSlideShowInstance();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void bug62929() throws Exception {
|
||||||
|
try(XMLSlideShow ss1 = XSLFTestDataSamples.openSampleDocument("missing-blip-fill.pptx")) {
|
||||||
|
assertEquals(1, ss1.getSlides().size());
|
||||||
|
|
||||||
|
XSLFSlide slide = ss1.getSlides().get(0);
|
||||||
|
|
||||||
|
assertEquals(slide.getShapes().size(), 1);
|
||||||
|
|
||||||
|
XSLFPictureShape picture = (XSLFPictureShape)slide.getShapes().get(0);
|
||||||
|
|
||||||
|
assertEquals(picture.getShapeId(), 662);
|
||||||
|
assertFalse(picture.isExternalLinkedPicture());
|
||||||
|
assertNull(picture.getPictureData());
|
||||||
|
assertNull(picture.getPictureLink());
|
||||||
|
assertNull(picture.getClipping());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void bug62736() throws Exception {
|
public void bug62736() throws Exception {
|
||||||
XMLSlideShow ss1 = XSLFTestDataSamples.openSampleDocument("bug62736.pptx");
|
XMLSlideShow ss1 = XSLFTestDataSamples.openSampleDocument("bug62736.pptx");
|
||||||
|
@ -47,7 +47,7 @@ public class TestPPTX2PNG {
|
|||||||
private static final POIDataSamples samples = POIDataSamples.getSlideShowInstance();
|
private static final POIDataSamples samples = POIDataSamples.getSlideShowInstance();
|
||||||
private static final File basedir = null;
|
private static final File basedir = null;
|
||||||
private static final String files =
|
private static final String files =
|
||||||
"53446.ppt, alterman_security.ppt, alterman_security.pptx, KEY02.pptx, themes.pptx, backgrounds.pptx, layouts.pptx, sample.pptx, shapes.pptx, 54880_chinese.ppt";
|
"53446.ppt, alterman_security.ppt, alterman_security.pptx, KEY02.pptx, themes.pptx, backgrounds.pptx, layouts.pptx, sample.pptx, shapes.pptx, 54880_chinese.ppt, keyframes.pptx";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ public class XSSFTestDataSamples {
|
|||||||
* @param wb the workbook to write
|
* @param wb the workbook to write
|
||||||
* @param testName a fragment of the filename
|
* @param testName a fragment of the filename
|
||||||
* @return the location where the workbook was saved
|
* @return the location where the workbook was saved
|
||||||
* @throws IOException
|
* @throws IOException If writing the file fails
|
||||||
*/
|
*/
|
||||||
public static <R extends Workbook> File writeOut(R wb, String testName) throws IOException {
|
public static <R extends Workbook> File writeOut(R wb, String testName) throws IOException {
|
||||||
final File file = getOutputFile(testName);
|
final File file = getOutputFile(testName);
|
||||||
@ -104,7 +104,9 @@ public class XSSFTestDataSamples {
|
|||||||
file = TempFile.createTempFile(testName, ".xlsx");
|
file = TempFile.createTempFile(testName, ".xlsx");
|
||||||
}
|
}
|
||||||
if (file.exists()) {
|
if (file.exists()) {
|
||||||
file.delete();
|
if(!file.delete()) {
|
||||||
|
throw new IOException("Could not delete file " + file);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
@ -114,7 +116,7 @@ public class XSSFTestDataSamples {
|
|||||||
*
|
*
|
||||||
* @param wb the workbook to write
|
* @param wb the workbook to write
|
||||||
* @return the memory buffer
|
* @return the memory buffer
|
||||||
* @throws IOException
|
* @throws IOException If writing the file fails
|
||||||
*/
|
*/
|
||||||
public static <R extends Workbook> ByteArrayOutputStream writeOut(R wb) throws IOException {
|
public static <R extends Workbook> ByteArrayOutputStream writeOut(R wb) throws IOException {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream(8192);
|
ByteArrayOutputStream out = new ByteArrayOutputStream(8192);
|
||||||
@ -137,7 +139,7 @@ public class XSSFTestDataSamples {
|
|||||||
* to avoid creating a temporary file. However, this may complicate the calling
|
* to avoid creating a temporary file. However, this may complicate the calling
|
||||||
* code to avoid having the workbook, BAOS, and BAIS open at the same time.
|
* code to avoid having the workbook, BAOS, and BAIS open at the same time.
|
||||||
*
|
*
|
||||||
* @param wb
|
* @param wb The workbook to write out, it is closed after the call.
|
||||||
* @param testName file name to be used to write to a file. This file will be cleaned up by a call to readBack(String)
|
* @param testName file name to be used to write to a file. This file will be cleaned up by a call to readBack(String)
|
||||||
* @return workbook location
|
* @return workbook location
|
||||||
* @throws RuntimeException if {@link #TEST_OUTPUT_DIR} System property is not set
|
* @throws RuntimeException if {@link #TEST_OUTPUT_DIR} System property is not set
|
||||||
@ -161,18 +163,13 @@ public class XSSFTestDataSamples {
|
|||||||
*
|
*
|
||||||
* @param wb the workbook to write
|
* @param wb the workbook to write
|
||||||
* @return the memory buffer
|
* @return the memory buffer
|
||||||
* @throws IOException
|
* @throws RuntimeException If writing the file fails
|
||||||
*/
|
*/
|
||||||
public static <R extends Workbook> ByteArrayOutputStream writeOutAndClose(R wb) {
|
public static <R extends Workbook> ByteArrayOutputStream writeOutAndClose(R wb) throws IOException {
|
||||||
try {
|
ByteArrayOutputStream out = writeOut(wb);
|
||||||
ByteArrayOutputStream out = writeOut(wb);
|
// Do not close the workbook if there was a problem writing the workbook
|
||||||
// Do not close the workbook if there was a problem writing the workbook
|
wb.close();
|
||||||
wb.close();
|
return out;
|
||||||
return out;
|
|
||||||
}
|
|
||||||
catch (final IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -183,12 +180,14 @@ public class XSSFTestDataSamples {
|
|||||||
*
|
*
|
||||||
* @param file the workbook file to read and delete
|
* @param file the workbook file to read and delete
|
||||||
* @return the read back workbook
|
* @return the read back workbook
|
||||||
* @throws IOException
|
* @throws IOException If reading or deleting the file fails
|
||||||
*/
|
*/
|
||||||
public static XSSFWorkbook readBackAndDelete(File file) throws IOException {
|
public static XSSFWorkbook readBackAndDelete(File file) throws IOException {
|
||||||
XSSFWorkbook wb = readBack(file);
|
XSSFWorkbook wb = readBack(file);
|
||||||
// do not delete the file if there's an error--might be helpful for debugging
|
// do not delete the file if there's an error--might be helpful for debugging
|
||||||
file.delete();
|
if(!file.delete()) {
|
||||||
|
throw new IOException("Could not delete file " + file + " after reading");
|
||||||
|
}
|
||||||
return wb;
|
return wb;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,16 +197,12 @@ public class XSSFTestDataSamples {
|
|||||||
*
|
*
|
||||||
* @param file the workbook file to read
|
* @param file the workbook file to read
|
||||||
* @return the read back workbook
|
* @return the read back workbook
|
||||||
* @throws IOException
|
* @throws IOException If reading the file fails
|
||||||
*/
|
*/
|
||||||
public static XSSFWorkbook readBack(File file) throws IOException {
|
public static XSSFWorkbook readBack(File file) throws IOException {
|
||||||
InputStream in = new FileInputStream(file);
|
try (InputStream in = new FileInputStream(file)) {
|
||||||
try {
|
|
||||||
return new XSSFWorkbook(in);
|
return new XSSFWorkbook(in);
|
||||||
}
|
}
|
||||||
finally {
|
|
||||||
in.close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -216,17 +211,13 @@ public class XSSFTestDataSamples {
|
|||||||
*
|
*
|
||||||
* @param out the output stream to read back from
|
* @param out the output stream to read back from
|
||||||
* @return the read back workbook
|
* @return the read back workbook
|
||||||
* @throws IOException
|
* @throws IOException If reading the file fails
|
||||||
*/
|
*/
|
||||||
public static XSSFWorkbook readBack(ByteArrayOutputStream out) throws IOException {
|
public static XSSFWorkbook readBack(ByteArrayOutputStream out) throws IOException {
|
||||||
InputStream is = new ByteArrayInputStream(out.toByteArray());
|
try (InputStream is = new ByteArrayInputStream(out.toByteArray())) {
|
||||||
out.close();
|
out.close();
|
||||||
try {
|
|
||||||
return new XSSFWorkbook(is);
|
return new XSSFWorkbook(is);
|
||||||
}
|
}
|
||||||
finally {
|
|
||||||
is.close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -452,4 +452,12 @@ public class TestXWPFWordExtractor extends TestCase {
|
|||||||
//once we add processing for this, we can change this to contains
|
//once we add processing for this, we can change this to contains
|
||||||
assertNotContained(txt, "table rows");
|
assertNotContained(txt, "table rows");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testPartsInTemplate() throws IOException {
|
||||||
|
XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("60316b.dotx");
|
||||||
|
XWPFWordExtractor extractor = new XWPFWordExtractor(doc);
|
||||||
|
String txt = extractor.getText();
|
||||||
|
assertContains(txt, "header 2");
|
||||||
|
assertContains(txt, "footer 1");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
|
|
||||||
package org.apache.poi.hslf.record;
|
package org.apache.poi.hslf.record;
|
||||||
|
|
||||||
|
import static org.apache.poi.hslf.usermodel.HSLFSlideShow.PP95_DOCUMENT;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -143,7 +145,7 @@ public class CurrentUserAtom
|
|||||||
// See how long it is. If it's under 28 bytes long, we can't
|
// See how long it is. If it's under 28 bytes long, we can't
|
||||||
// read it
|
// read it
|
||||||
if(_contents.length < 28) {
|
if(_contents.length < 28) {
|
||||||
boolean isPP95 = dir.hasEntry("PP40");
|
boolean isPP95 = dir.hasEntry(PP95_DOCUMENT);
|
||||||
// PPT95 has 4 byte size, then data
|
// PPT95 has 4 byte size, then data
|
||||||
if (!isPP95 && _contents.length >= 4) {
|
if (!isPP95 && _contents.length >= 4) {
|
||||||
int size = LittleEndian.getInt(_contents);
|
int size = LittleEndian.getInt(_contents);
|
||||||
|
@ -71,6 +71,7 @@ public final class HSLFSlideShow implements SlideShow<HSLFShape,HSLFTextParagrap
|
|||||||
|
|
||||||
/** Powerpoint document entry/stream name */
|
/** Powerpoint document entry/stream name */
|
||||||
public static final String POWERPOINT_DOCUMENT = "PowerPoint Document";
|
public static final String POWERPOINT_DOCUMENT = "PowerPoint Document";
|
||||||
|
public static final String PP95_DOCUMENT = "PP40";
|
||||||
|
|
||||||
enum LoadSavePhase {
|
enum LoadSavePhase {
|
||||||
INIT, LOADED
|
INIT, LOADED
|
||||||
|
@ -17,6 +17,9 @@
|
|||||||
|
|
||||||
package org.apache.poi.hslf.usermodel;
|
package org.apache.poi.hslf.usermodel;
|
||||||
|
|
||||||
|
import static org.apache.poi.hslf.usermodel.HSLFSlideShow.POWERPOINT_DOCUMENT;
|
||||||
|
import static org.apache.poi.hslf.usermodel.HSLFSlideShow.PP95_DOCUMENT;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
@ -35,6 +38,7 @@ import java.util.TreeMap;
|
|||||||
import org.apache.poi.POIDocument;
|
import org.apache.poi.POIDocument;
|
||||||
import org.apache.poi.hslf.exceptions.CorruptPowerPointFileException;
|
import org.apache.poi.hslf.exceptions.CorruptPowerPointFileException;
|
||||||
import org.apache.poi.hslf.exceptions.HSLFException;
|
import org.apache.poi.hslf.exceptions.HSLFException;
|
||||||
|
import org.apache.poi.hslf.exceptions.OldPowerPointFormatException;
|
||||||
import org.apache.poi.hslf.record.CurrentUserAtom;
|
import org.apache.poi.hslf.record.CurrentUserAtom;
|
||||||
import org.apache.poi.hslf.record.DocumentEncryptionAtom;
|
import org.apache.poi.hslf.record.DocumentEncryptionAtom;
|
||||||
import org.apache.poi.hslf.record.ExOleObjStg;
|
import org.apache.poi.hslf.record.ExOleObjStg;
|
||||||
@ -183,13 +187,18 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable {
|
|||||||
* @throws IOException when the powerpoint can't be read
|
* @throws IOException when the powerpoint can't be read
|
||||||
*/
|
*/
|
||||||
private void readPowerPointStream() throws IOException {
|
private void readPowerPointStream() throws IOException {
|
||||||
|
final DirectoryNode dir = getDirectory();
|
||||||
|
|
||||||
|
if (!dir.hasEntry(POWERPOINT_DOCUMENT) && dir.hasEntry(PP95_DOCUMENT)) {
|
||||||
|
throw new OldPowerPointFormatException("You seem to have supplied a PowerPoint95 file, which isn't supported");
|
||||||
|
}
|
||||||
|
|
||||||
// Get the main document stream
|
// Get the main document stream
|
||||||
DocumentEntry docProps =
|
DocumentEntry docProps = (DocumentEntry)dir.getEntry(POWERPOINT_DOCUMENT);
|
||||||
(DocumentEntry) getDirectory().getEntry(HSLFSlideShow.POWERPOINT_DOCUMENT);
|
|
||||||
|
|
||||||
// Grab the document stream
|
// Grab the document stream
|
||||||
int len = docProps.getSize();
|
int len = docProps.getSize();
|
||||||
try (InputStream is = getDirectory().createDocumentInputStream(HSLFSlideShow.POWERPOINT_DOCUMENT)) {
|
try (InputStream is = dir.createDocumentInputStream(docProps)) {
|
||||||
_docstream = IOUtils.toByteArray(is, len);
|
_docstream = IOUtils.toByteArray(is, len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -665,8 +674,8 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable {
|
|||||||
|
|
||||||
// Write the PPT stream into the POIFS layer
|
// Write the PPT stream into the POIFS layer
|
||||||
ByteArrayInputStream bais = new ByteArrayInputStream(_docstream);
|
ByteArrayInputStream bais = new ByteArrayInputStream(_docstream);
|
||||||
outFS.createOrUpdateDocument(bais, HSLFSlideShow.POWERPOINT_DOCUMENT);
|
outFS.createOrUpdateDocument(bais, POWERPOINT_DOCUMENT);
|
||||||
writtenEntries.add(HSLFSlideShow.POWERPOINT_DOCUMENT);
|
writtenEntries.add(POWERPOINT_DOCUMENT);
|
||||||
|
|
||||||
currentUser.setEncrypted(encryptedSS.getDocumentEncryptionAtom() != null);
|
currentUser.setEncrypted(encryptedSS.getDocumentEncryptionAtom() != null);
|
||||||
currentUser.writeToFS(outFS);
|
currentUser.writeToFS(outFS);
|
||||||
|
@ -0,0 +1,81 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
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.poifs.filesystem;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.Charsets;
|
||||||
|
import org.apache.poi.POIDataSamples;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
public class TestFileMagic {
|
||||||
|
@Test
|
||||||
|
public void testFileMagic() {
|
||||||
|
assertEquals(FileMagic.XML, FileMagic.valueOf("XML"));
|
||||||
|
assertEquals(FileMagic.XML, FileMagic.valueOf("<?xml".getBytes(Charsets.UTF_8)));
|
||||||
|
|
||||||
|
assertEquals(FileMagic.HTML, FileMagic.valueOf("HTML"));
|
||||||
|
assertEquals(FileMagic.HTML, FileMagic.valueOf("<!DOCTYP".getBytes(Charsets.UTF_8)));
|
||||||
|
assertEquals(FileMagic.HTML, FileMagic.valueOf("<!DOCTYPE".getBytes(Charsets.UTF_8)));
|
||||||
|
assertEquals(FileMagic.HTML, FileMagic.valueOf("<html".getBytes(Charsets.UTF_8)));
|
||||||
|
|
||||||
|
try {
|
||||||
|
FileMagic.valueOf("some string");
|
||||||
|
fail("Should catch exception here");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// expected here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFileMagicFile() throws IOException {
|
||||||
|
assertEquals(FileMagic.OLE2, FileMagic.valueOf(POIDataSamples.getSpreadSheetInstance().getFile("SampleSS.xls")));
|
||||||
|
assertEquals(FileMagic.OOXML, FileMagic.valueOf(POIDataSamples.getSpreadSheetInstance().getFile("SampleSS.xlsx")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFileMagicStream() throws IOException {
|
||||||
|
try (InputStream stream = new BufferedInputStream(new FileInputStream(POIDataSamples.getSpreadSheetInstance().getFile("SampleSS.xls")))) {
|
||||||
|
assertEquals(FileMagic.OLE2, FileMagic.valueOf(stream));
|
||||||
|
}
|
||||||
|
try (InputStream stream = new BufferedInputStream(new FileInputStream(POIDataSamples.getSpreadSheetInstance().getFile("SampleSS.xlsx")))) {
|
||||||
|
assertEquals(FileMagic.OOXML, FileMagic.valueOf(stream));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPrepare() throws IOException {
|
||||||
|
try (InputStream stream = new BufferedInputStream(new FileInputStream(POIDataSamples.getSpreadSheetInstance().getFile("SampleSS.xlsx")))) {
|
||||||
|
assertSame(stream, FileMagic.prepareToCheckMagic(stream));
|
||||||
|
}
|
||||||
|
|
||||||
|
try (InputStream stream = new InputStream() {
|
||||||
|
@Override
|
||||||
|
public int read() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
assertNotSame(stream, FileMagic.prepareToCheckMagic(stream));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
package org.apache.poi.poifs.filesystem;
|
package org.apache.poi.poifs.filesystem;
|
||||||
|
|
||||||
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
@ -278,4 +279,18 @@ public final class TestPOIFSFileSystem {
|
|||||||
private static InputStream openSampleStream(String sampleFileName) {
|
private static InputStream openSampleStream(String sampleFileName) {
|
||||||
return HSSFTestDataSamples.openSampleFileStream(sampleFileName);
|
return HSSFTestDataSamples.openSampleFileStream(sampleFileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void fileMagics() {
|
||||||
|
for (FileMagic fm : FileMagic.values()) {
|
||||||
|
if (fm == FileMagic.UNKNOWN) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (byte[] b : fm.magic) {
|
||||||
|
assertEquals(fm, FileMagic.valueOf(b));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(FileMagic.UNKNOWN, FileMagic.valueOf("foobaa".getBytes(UTF_8)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,66 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
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.ss.formula;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
public class SheetRangeAndWorkbookIndexFormatterTest {
|
||||||
|
@Test
|
||||||
|
public void noDelimiting_ifASingleSheetNameDoesntNeedDelimiting() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
String result = SheetRangeAndWorkbookIndexFormatter.format(sb, 0, "noDelimiting", null);
|
||||||
|
assertEquals("[0]noDelimiting", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void everythingIsScreened_ifASingleSheetNameNeedsDelimiting() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
String result = SheetRangeAndWorkbookIndexFormatter.format(sb, 0, "1delimiting", null);
|
||||||
|
assertEquals("'[0]1delimiting'", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void noDelimiting_ifBothSheetNamesDontNeedDelimiting() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
String result = SheetRangeAndWorkbookIndexFormatter.format(sb, 0, "noDelimiting1", "noDelimiting2");
|
||||||
|
assertEquals("[0]noDelimiting1:noDelimiting2", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void everythingIsScreened_ifFirstSheetNamesNeedsDelimiting() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
String result = SheetRangeAndWorkbookIndexFormatter.format(sb, 0, "1delimiting", "noDelimiting");
|
||||||
|
assertEquals("'[0]1delimiting:noDelimiting'", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void everythingIsScreened_ifLastSheetNamesNeedsDelimiting() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
String result = SheetRangeAndWorkbookIndexFormatter.format(sb, 0, "noDelimiting", "1delimiting");
|
||||||
|
assertEquals("'[0]noDelimiting:1delimiting'", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void everythingIsScreened_ifBothSheetNamesNeedDelimiting() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
String result = SheetRangeAndWorkbookIndexFormatter.format(sb, 0, "1delimiting", "2delimiting");
|
||||||
|
assertEquals("'[0]1delimiting:2delimiting'", result);
|
||||||
|
}
|
||||||
|
}
|
BIN
test-data/document/60316.docx
Normal file
BIN
test-data/document/60316.docx
Normal file
Binary file not shown.
BIN
test-data/document/60316b.dotx
Normal file
BIN
test-data/document/60316b.dotx
Normal file
Binary file not shown.
BIN
test-data/slideshow/keyframes.pptx
Normal file
BIN
test-data/slideshow/keyframes.pptx
Normal file
Binary file not shown.
BIN
test-data/slideshow/missing-blip-fill.pptx
Normal file
BIN
test-data/slideshow/missing-blip-fill.pptx
Normal file
Binary file not shown.
BIN
test-data/slideshow/pp40only.ppt
Normal file
BIN
test-data/slideshow/pp40only.ppt
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user