mirror of
https://github.com/apache/poi.git
synced 2025-02-10 12:04:44 +00:00
Sonar fixes
- Math operands should be cast before assignment - Suppress - Make sure that command line arguments are used safely here - Suppress - Replace this use of System.out or System.err by a logger. git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1876737 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
c41dee931f
commit
661c0b66bc
@ -25,6 +25,7 @@ import java.nio.file.Paths;
|
|||||||
import java.security.GeneralSecurityException;
|
import java.security.GeneralSecurityException;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import org.apache.poi.poifs.crypt.Decryptor;
|
import org.apache.poi.poifs.crypt.Decryptor;
|
||||||
import org.apache.poi.poifs.crypt.EncryptionInfo;
|
import org.apache.poi.poifs.crypt.EncryptionInfo;
|
||||||
@ -50,7 +51,8 @@ public final class OOXMLPasswordsTry {
|
|||||||
System.err.println(" OOXMLPasswordsTry <file.ooxml> <wordlist>");
|
System.err.println(" OOXMLPasswordsTry <file.ooxml> <wordlist>");
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
String ooxml = args[0], words = args[1];
|
String ooxml = args[0];
|
||||||
|
String words = args[1];
|
||||||
|
|
||||||
System.out.println("Trying passwords from " + words + " against " + ooxml);
|
System.out.println("Trying passwords from " + words + " against " + ooxml);
|
||||||
System.out.println();
|
System.out.println();
|
||||||
@ -61,7 +63,7 @@ public final class OOXMLPasswordsTry {
|
|||||||
|
|
||||||
final long start = System.currentTimeMillis();
|
final long start = System.currentTimeMillis();
|
||||||
final int[] count = { 0 };
|
final int[] count = { 0 };
|
||||||
Predicate<String> counter = (s) -> {
|
Predicate<String> counter = s -> {
|
||||||
if (++count[0] % 1000 == 0) {
|
if (++count[0] % 1000 == 0) {
|
||||||
int secs = (int) ((System.currentTimeMillis() - start) / 1000);
|
int secs = (int) ((System.currentTimeMillis() - start) / 1000);
|
||||||
System.out.println("Done " + count[0] + " passwords, " + secs + " seconds, last password " + s);
|
System.out.println("Done " + count[0] + " passwords, " + secs + " seconds, last password " + s);
|
||||||
@ -70,9 +72,10 @@ public final class OOXMLPasswordsTry {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Try each password in turn, reporting progress
|
// Try each password in turn, reporting progress
|
||||||
Optional<String> found = Files.lines(Paths.get(words)).filter(counter).filter(w -> isValid(d, w)).findFirst();
|
try (Stream<String> lines = Files.lines(Paths.get(words))) {
|
||||||
|
Optional<String> found = lines.filter(counter).filter(w -> isValid(d, w)).findFirst();
|
||||||
System.out.println(found.map(s -> "Password found: " + s).orElse("Error - No password matched"));
|
System.out.println(found.map(s -> "Password found: " + s).orElse("Error - No password matched"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,33 +17,27 @@
|
|||||||
|
|
||||||
package org.apache.poi.hpsf.examples;
|
package org.apache.poi.hpsf.examples;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.apache.poi.hpsf.DocumentSummaryInformation;
|
import org.apache.poi.hpsf.DocumentSummaryInformation;
|
||||||
|
import org.apache.poi.hpsf.HPSFException;
|
||||||
import org.apache.poi.hpsf.HPSFRuntimeException;
|
import org.apache.poi.hpsf.HPSFRuntimeException;
|
||||||
import org.apache.poi.hpsf.MarkUnsupportedException;
|
|
||||||
import org.apache.poi.hpsf.NoPropertySetStreamException;
|
|
||||||
import org.apache.poi.hpsf.PropertySet;
|
import org.apache.poi.hpsf.PropertySet;
|
||||||
import org.apache.poi.hpsf.PropertySetFactory;
|
import org.apache.poi.hpsf.PropertySetFactory;
|
||||||
import org.apache.poi.hpsf.SummaryInformation;
|
import org.apache.poi.hpsf.SummaryInformation;
|
||||||
import org.apache.poi.hpsf.UnexpectedPropertySetTypeException;
|
|
||||||
import org.apache.poi.hpsf.WritingNotSupportedException;
|
import org.apache.poi.hpsf.WritingNotSupportedException;
|
||||||
import org.apache.poi.poifs.eventfilesystem.POIFSReader;
|
import org.apache.poi.poifs.eventfilesystem.POIFSReader;
|
||||||
import org.apache.poi.poifs.eventfilesystem.POIFSReaderEvent;
|
import org.apache.poi.poifs.eventfilesystem.POIFSReaderEvent;
|
||||||
import org.apache.poi.poifs.eventfilesystem.POIFSReaderListener;
|
|
||||||
import org.apache.poi.poifs.filesystem.DirectoryEntry;
|
import org.apache.poi.poifs.filesystem.DirectoryEntry;
|
||||||
import org.apache.poi.poifs.filesystem.DocumentInputStream;
|
import org.apache.poi.poifs.filesystem.DocumentInputStream;
|
||||||
import org.apache.poi.poifs.filesystem.EntryUtils;
|
import org.apache.poi.poifs.filesystem.EntryUtils;
|
||||||
import org.apache.poi.poifs.filesystem.POIFSDocumentPath;
|
import org.apache.poi.poifs.filesystem.POIFSDocumentPath;
|
||||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||||
import org.apache.poi.util.IOUtils;
|
|
||||||
import org.apache.poi.util.TempFile;
|
import org.apache.poi.util.TempFile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -89,7 +83,7 @@ public final class CopyCompare {
|
|||||||
String originalFileName = null;
|
String originalFileName = null;
|
||||||
String copyFileName = null;
|
String copyFileName = null;
|
||||||
|
|
||||||
/* Check the command-line arguments. */
|
// Check the command-line arguments.
|
||||||
if (args.length == 1) {
|
if (args.length == 1) {
|
||||||
originalFileName = args[0];
|
originalFileName = args[0];
|
||||||
File f = TempFile.createTempFile("CopyOfPOIFileSystem-", ".ole2");
|
File f = TempFile.createTempFile("CopyOfPOIFileSystem-", ".ole2");
|
||||||
@ -99,25 +93,26 @@ public final class CopyCompare {
|
|||||||
originalFileName = args[0];
|
originalFileName = args[0];
|
||||||
copyFileName = args[1];
|
copyFileName = args[1];
|
||||||
} else {
|
} else {
|
||||||
System.err.println("Usage: " + CopyCompare.class.getName() +
|
System.err.println("Usage: CopyCompare originPOIFS [copyPOIFS]");
|
||||||
"originPOIFS [copyPOIFS]");
|
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read the origin POIFS using the eventing API. The real work is done
|
|
||||||
* in the class CopyFile which is registered here as a POIFSReader. */
|
// Read the origin POIFS using the eventing API.
|
||||||
final POIFSReader r = new POIFSReader();
|
final POIFSReader r = new POIFSReader();
|
||||||
final CopyFile cf = new CopyFile(copyFileName);
|
try (final POIFSFileSystem poiFs = new POIFSFileSystem();
|
||||||
r.registerListener(cf);
|
OutputStream fos = new FileOutputStream(copyFileName)) {
|
||||||
r.setNotifyEmptyDirectories(true);
|
r.registerListener(e -> handleEvent(poiFs, e));
|
||||||
|
r.setNotifyEmptyDirectories(true);
|
||||||
|
|
||||||
r.read(new File(originalFileName));
|
r.read(new File(originalFileName));
|
||||||
|
|
||||||
/* Write the new POIFS to disk. */
|
// Write the new POIFS to disk.
|
||||||
cf.close();
|
poiFs.writeFilesystem(fos);
|
||||||
|
}
|
||||||
|
|
||||||
/* Read all documents from the original POI file system and compare them
|
// Read all documents from the original POI file system and compare them with
|
||||||
* with the equivalent document from the copy. */
|
// the equivalent document from the copy.
|
||||||
try (POIFSFileSystem opfs = new POIFSFileSystem(new File(originalFileName));
|
try (POIFSFileSystem opfs = new POIFSFileSystem(new File(originalFileName));
|
||||||
POIFSFileSystem cpfs = new POIFSFileSystem(new File(copyFileName))) {
|
POIFSFileSystem cpfs = new POIFSFileSystem(new File(copyFileName))) {
|
||||||
final DirectoryEntry oRoot = opfs.getRoot();
|
final DirectoryEntry oRoot = opfs.getRoot();
|
||||||
@ -126,94 +121,28 @@ public final class CopyCompare {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private interface InputStreamSupplier {
|
||||||
|
InputStream get() throws IOException, WritingNotSupportedException;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>This class does all the work. Its method {@link
|
* The method is called by POI's eventing API for each file in the origin POIFS.
|
||||||
* #processPOIFSReaderEvent(POIFSReaderEvent)} is called for each file in
|
|
||||||
* the original POI file system. Except for property set streams it copies
|
|
||||||
* everything unmodified to the destination POI filesystem. Property set
|
|
||||||
* streams are copied by creating a new {@link PropertySet} from the
|
|
||||||
* original property set by using the {@link
|
|
||||||
* PropertySet#PropertySet(PropertySet)} constructor.</p>
|
|
||||||
*/
|
*/
|
||||||
static class CopyFile implements POIFSReaderListener {
|
public static void handleEvent(final POIFSFileSystem poiFs, final POIFSReaderEvent event) {
|
||||||
private final String dstName;
|
// The following declarations are shortcuts for accessing the "event" object.
|
||||||
private final POIFSFileSystem poiFs;
|
final DocumentInputStream stream = event.getStream();
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
/**
|
// Find out whether the current document is a property set stream or not.
|
||||||
* <p>The constructor of a {@link CopyFile} instance creates the target
|
InputStreamSupplier su;
|
||||||
* POIFS. It also stores the name of the file the POIFS will be written
|
if (stream != null && PropertySet.isPropertySetStream(stream)) {
|
||||||
* to once it is complete.</p>
|
// Yes, the current document is a property set stream. Let's create
|
||||||
*
|
// a PropertySet instance from it.
|
||||||
* @param dstName The name of the disk file the destination POIFS is to
|
PropertySet ps = PropertySetFactory.create(stream);
|
||||||
* be written to.
|
|
||||||
*/
|
|
||||||
CopyFile(final String dstName) {
|
|
||||||
this.dstName = dstName;
|
|
||||||
poiFs = new POIFSFileSystem();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Copy the property set to the destination POI file system.
|
||||||
/**
|
final PropertySet mps;
|
||||||
* <p>The method is called by POI's eventing API for each file in the
|
|
||||||
* origin POIFS.</p>
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void processPOIFSReaderEvent(final POIFSReaderEvent event) {
|
|
||||||
/* The following declarations are shortcuts for accessing the
|
|
||||||
* "event" object. */
|
|
||||||
final POIFSDocumentPath path = event.getPath();
|
|
||||||
final String name = event.getName();
|
|
||||||
|
|
||||||
Throwable t = null;
|
|
||||||
|
|
||||||
try (final DocumentInputStream stream = event.getStream()) {
|
|
||||||
/* Find out whether the current document is a property set
|
|
||||||
* stream or not. */
|
|
||||||
if (stream != null && PropertySet.isPropertySetStream(stream)) {
|
|
||||||
/* Yes, the current document is a property set stream.
|
|
||||||
* Let's create a PropertySet instance from it. */
|
|
||||||
PropertySet ps = PropertySetFactory.create(stream);
|
|
||||||
|
|
||||||
/* Copy the property set to the destination POI file
|
|
||||||
* system. */
|
|
||||||
copy(poiFs, path, name, ps);
|
|
||||||
} else {
|
|
||||||
/* No, the current document is not a property set stream. We
|
|
||||||
* copy it unmodified to the destination POIFS. */
|
|
||||||
copy(poiFs, path, name, stream);
|
|
||||||
}
|
|
||||||
} catch (MarkUnsupportedException | WritingNotSupportedException | IOException | NoPropertySetStreamException ex) {
|
|
||||||
t = ex;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* According to the definition of the processPOIFSReaderEvent method
|
|
||||||
* we cannot pass checked exceptions to the caller. The following
|
|
||||||
* lines check whether a checked exception occurred and throws an
|
|
||||||
* unchecked exception. The message of that exception is that of
|
|
||||||
* the underlying checked exception. */
|
|
||||||
if (t != null) {
|
|
||||||
throw new HPSFRuntimeException("Could not read file \"" + path + "/" + name, t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes a {@link PropertySet} to a POI filesystem.
|
|
||||||
*
|
|
||||||
* @param poiFs The POI filesystem to write to.
|
|
||||||
* @param path The file's path in the POI filesystem.
|
|
||||||
* @param name The file's name in the POI filesystem.
|
|
||||||
* @param ps The property set to write.
|
|
||||||
*/
|
|
||||||
public void copy(final POIFSFileSystem poiFs,
|
|
||||||
final POIFSDocumentPath path,
|
|
||||||
final String name,
|
|
||||||
final PropertySet ps)
|
|
||||||
throws WritingNotSupportedException, IOException {
|
|
||||||
final DirectoryEntry de = getPath(poiFs, path);
|
|
||||||
final PropertySet mps;
|
|
||||||
try {
|
|
||||||
if (ps instanceof DocumentSummaryInformation) {
|
if (ps instanceof DocumentSummaryInformation) {
|
||||||
mps = new DocumentSummaryInformation(ps);
|
mps = new DocumentSummaryInformation(ps);
|
||||||
} else if (ps instanceof SummaryInformation) {
|
} else if (ps instanceof SummaryInformation) {
|
||||||
@ -221,112 +150,32 @@ public final class CopyCompare {
|
|||||||
} else {
|
} else {
|
||||||
mps = new PropertySet(ps);
|
mps = new PropertySet(ps);
|
||||||
}
|
}
|
||||||
} catch (UnexpectedPropertySetTypeException e) {
|
su = mps::toInputStream;
|
||||||
throw new IOException(e);
|
} else {
|
||||||
|
// No, the current document is not a property set stream.
|
||||||
|
// We copy it unmodified to the destination POIFS.
|
||||||
|
su = event::getStream;
|
||||||
}
|
}
|
||||||
de.createDocument(name, mps.toInputStream());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
try (InputStream is = su.get()) {
|
||||||
|
final POIFSDocumentPath path = event.getPath();
|
||||||
|
|
||||||
/**
|
// Ensures that the directory hierarchy for a document in a POI fileystem is in place.
|
||||||
* Copies the bytes from a {@link DocumentInputStream} to a new
|
// Get the root directory. It does not have to be created since it always exists in a POIFS.
|
||||||
* stream in a POI filesystem.
|
DirectoryEntry de = poiFs.getRoot();
|
||||||
*
|
|
||||||
* @param poiFs The POI filesystem to write to.
|
|
||||||
* @param path The source document's path.
|
|
||||||
* @param name The source document's name.
|
|
||||||
* @param stream The stream containing the source document.
|
|
||||||
*/
|
|
||||||
public void copy(final POIFSFileSystem poiFs,
|
|
||||||
final POIFSDocumentPath path,
|
|
||||||
final String name,
|
|
||||||
final DocumentInputStream stream)
|
|
||||||
throws IOException {
|
|
||||||
// create the directories to the document
|
|
||||||
final DirectoryEntry de = getPath(poiFs, path);
|
|
||||||
// check the parameters after the directories have been created
|
|
||||||
if (stream != null && name != null) {
|
|
||||||
byte[] data = IOUtils.toByteArray(stream);
|
|
||||||
de.createDocument(name, new ByteArrayInputStream(data));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
for (int i=0; i<path.length(); i++) {
|
||||||
/**
|
String subDir = path.getComponent(i);
|
||||||
* Writes the POI file system to a disk file.
|
de = (de.hasEntry(subDir)) ? (DirectoryEntry)de.getEntry(subDir) : de.createDirectory(subDir);
|
||||||
*/
|
|
||||||
public void close() throws IOException {
|
|
||||||
try (OutputStream fos = new FileOutputStream(dstName)) {
|
|
||||||
poiFs.writeFilesystem(fos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Contains the directory paths that have already been created in the
|
|
||||||
* output POI filesystem and maps them to their corresponding
|
|
||||||
* {@link org.apache.poi.poifs.filesystem.DirectoryNode}s.
|
|
||||||
*/
|
|
||||||
private final Map<String, DirectoryEntry> paths = new HashMap<>();
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Ensures that the directory hierarchy for a document in a POI
|
|
||||||
* fileystem is in place. When a document is to be created somewhere in
|
|
||||||
* a POI filesystem its directory must be created first. This method
|
|
||||||
* creates all directories between the POI filesystem root and the
|
|
||||||
* directory the document should belong to which do not yet exist.</p>
|
|
||||||
* <p>
|
|
||||||
* <p>Unfortunately POI does not offer a simple method to interrogate
|
|
||||||
* the POIFS whether a certain child node (file or directory) exists in
|
|
||||||
* a directory. However, since we always start with an empty POIFS which
|
|
||||||
* contains the root directory only and since each directory in the
|
|
||||||
* POIFS is created by this method we can maintain the POIFS's directory
|
|
||||||
* hierarchy ourselves: The {@link DirectoryEntry} of each directory
|
|
||||||
* created is stored in a {@link Map}. The directories' path names map
|
|
||||||
* to the corresponding {@link DirectoryEntry} instances.</p>
|
|
||||||
*
|
|
||||||
* @param poiFs The POI filesystem the directory hierarchy is created
|
|
||||||
* in, if needed.
|
|
||||||
* @param path The document's path. This method creates those directory
|
|
||||||
* components of this hierarchy which do not yet exist.
|
|
||||||
* @return The directory entry of the document path's parent. The caller
|
|
||||||
* should use this {@link DirectoryEntry} to create documents in it.
|
|
||||||
*/
|
|
||||||
public DirectoryEntry getPath(final POIFSFileSystem poiFs,
|
|
||||||
final POIFSDocumentPath path) {
|
|
||||||
try {
|
|
||||||
/* Check whether this directory has already been created. */
|
|
||||||
final String s = path.toString();
|
|
||||||
DirectoryEntry de = paths.get(s);
|
|
||||||
if (de != null) {
|
|
||||||
/* Yes: return the corresponding DirectoryEntry. */
|
|
||||||
return de;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* No: We have to create the directory - or return the root's
|
de.createDocument(event.getName(), is);
|
||||||
* DirectoryEntry. */
|
|
||||||
int l = path.length();
|
|
||||||
if (l == 0) {
|
|
||||||
/* Get the root directory. It does not have to be created
|
|
||||||
* since it always exists in a POIFS. */
|
|
||||||
de = poiFs.getRoot();
|
|
||||||
} else {
|
|
||||||
/* Create a subordinate directory. The first step is to
|
|
||||||
* ensure that the parent directory exists: */
|
|
||||||
de = getPath(poiFs, path.getParent());
|
|
||||||
/* Now create the target directory: */
|
|
||||||
de = de.createDirectory(path.getComponent(path.length() - 1));
|
|
||||||
}
|
|
||||||
paths.put(s, de);
|
|
||||||
return de;
|
|
||||||
} catch (IOException ex) {
|
|
||||||
/* This exception will be thrown if the directory already
|
|
||||||
* exists. However, since we have full control about directory
|
|
||||||
* creation we can ensure that this will never happen. */
|
|
||||||
throw new RuntimeException(ex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} catch (HPSFException | IOException ex) {
|
||||||
|
// According to the definition of the processPOIFSReaderEvent method we cannot pass checked
|
||||||
|
// exceptions to the caller.
|
||||||
|
throw new HPSFRuntimeException("Could not read file " + event.getPath() + "/" + event.getName(), ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ import java.io.File;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.poi.hpsf.HPSFRuntimeException;
|
||||||
import org.apache.poi.hpsf.NoPropertySetStreamException;
|
import org.apache.poi.hpsf.NoPropertySetStreamException;
|
||||||
import org.apache.poi.hpsf.Property;
|
import org.apache.poi.hpsf.Property;
|
||||||
import org.apache.poi.hpsf.PropertySet;
|
import org.apache.poi.hpsf.PropertySet;
|
||||||
@ -65,7 +66,7 @@ public final class ReadCustomPropertySets {
|
|||||||
out("No property set stream: \"" + streamName + "\"");
|
out("No property set stream: \"" + streamName + "\"");
|
||||||
return;
|
return;
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
throw new RuntimeException("Property set stream \"" + streamName + "\": " + ex);
|
throw new HPSFRuntimeException("Property set stream \"" + streamName + "\": " + ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Print the name of the property set stream: */
|
/* Print the name of the property set stream: */
|
||||||
|
@ -93,7 +93,8 @@ public final class WriteAuthorAndTitle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Read the names of the origin and destination POI filesystems. */
|
/* Read the names of the origin and destination POI filesystems. */
|
||||||
final String srcName = args[0], dstName = args[1];
|
final String srcName = args[0];
|
||||||
|
final String dstName = args[1];
|
||||||
|
|
||||||
/* Read the origin POIFS using the eventing API. The real work is done
|
/* Read the origin POIFS using the eventing API. The real work is done
|
||||||
* in the class ModifySICopyTheRest which is registered here as a
|
* in the class ModifySICopyTheRest which is registered here as a
|
||||||
@ -101,7 +102,7 @@ public final class WriteAuthorAndTitle {
|
|||||||
try (POIFSFileSystem poifs = new POIFSFileSystem();
|
try (POIFSFileSystem poifs = new POIFSFileSystem();
|
||||||
OutputStream out = new FileOutputStream(dstName)) {
|
OutputStream out = new FileOutputStream(dstName)) {
|
||||||
final POIFSReader r = new POIFSReader();
|
final POIFSReader r = new POIFSReader();
|
||||||
r.registerListener((e) -> handleEvent(poifs, e));
|
r.registerListener(e -> handleEvent(poifs, e));
|
||||||
r.read(new File(srcName));
|
r.read(new File(srcName));
|
||||||
|
|
||||||
/* Write the new POIFS to disk. */
|
/* Write the new POIFS to disk. */
|
||||||
|
@ -392,7 +392,8 @@ public final class ApacheconEU08 {
|
|||||||
Graphics2D graphics = new SLGraphics(group);
|
Graphics2D graphics = new SLGraphics(group);
|
||||||
|
|
||||||
//draw a simple bar graph
|
//draw a simple bar graph
|
||||||
int x = bounds.x + 50, y = bounds.y + 50;
|
int x = bounds.x + 50;
|
||||||
|
int y = bounds.y + 50;
|
||||||
graphics.setFont(new Font("Arial", Font.BOLD, 10));
|
graphics.setFont(new Font("Arial", Font.BOLD, 10));
|
||||||
for (int i = 0, idx = 1; i < def.length; i+=2, idx++) {
|
for (int i = 0, idx = 1; i < def.length; i+=2, idx++) {
|
||||||
graphics.setColor(Color.black);
|
graphics.setColor(Color.black);
|
||||||
|
@ -60,42 +60,40 @@ public final class DataExtraction {
|
|||||||
handleSound(aSound);
|
handleSound(aSound);
|
||||||
}
|
}
|
||||||
|
|
||||||
int oleIdx = -1, picIdx = -1;
|
int oleIdx = -1;
|
||||||
|
int picIdx = -1;
|
||||||
for (HSLFSlide slide : ppt.getSlides()) {
|
for (HSLFSlide slide : ppt.getSlides()) {
|
||||||
//extract embedded OLE documents
|
//extract embedded OLE documents
|
||||||
for (HSLFShape shape : slide.getShapes()) {
|
for (HSLFShape shape : slide.getShapes()) {
|
||||||
if (shape instanceof HSLFObjectShape) {
|
if (shape instanceof HSLFObjectShape) {
|
||||||
oleIdx++;
|
handleShape((HSLFObjectShape) shape, ++oleIdx);
|
||||||
HSLFObjectShape ole = (HSLFObjectShape) shape;
|
} else if (shape instanceof HSLFPictureShape) {
|
||||||
HSLFObjectData data = ole.getObjectData();
|
handlePicture((HSLFPictureShape) shape, ++picIdx);
|
||||||
String name = ole.getInstanceName();
|
|
||||||
switch (name == null ? "" : name) {
|
|
||||||
case "Worksheet":
|
|
||||||
//read xls
|
|
||||||
handleWorkbook(data, name, oleIdx);
|
|
||||||
break;
|
|
||||||
case "Document":
|
|
||||||
//read the word document
|
|
||||||
handleDocument(data, name, oleIdx);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
handleUnknown(data, ole.getProgId(), oleIdx);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Pictures
|
|
||||||
else if (shape instanceof HSLFPictureShape) {
|
|
||||||
picIdx++;
|
|
||||||
HSLFPictureShape p = (HSLFPictureShape) shape;
|
|
||||||
HSLFPictureData data = p.getPictureData();
|
|
||||||
handlePicture(data, picIdx);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void handleShape(HSLFObjectShape ole, int oleIdx) throws IOException {
|
||||||
|
HSLFObjectData data = ole.getObjectData();
|
||||||
|
String name = ole.getInstanceName();
|
||||||
|
switch (name == null ? "" : name) {
|
||||||
|
case "Worksheet":
|
||||||
|
//read xls
|
||||||
|
handleWorkbook(data, name, oleIdx);
|
||||||
|
break;
|
||||||
|
case "Document":
|
||||||
|
//read the word document
|
||||||
|
handleDocument(data, name, oleIdx);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
handleUnknown(data, ole.getProgId(), oleIdx);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private static void handleWorkbook(HSLFObjectData data, String name, int oleIdx) throws IOException {
|
private static void handleWorkbook(HSLFObjectData data, String name, int oleIdx) throws IOException {
|
||||||
try (InputStream is = data.getInputStream();
|
try (InputStream is = data.getInputStream();
|
||||||
HSSFWorkbook wb = new HSSFWorkbook(is);
|
HSSFWorkbook wb = new HSSFWorkbook(is);
|
||||||
@ -126,7 +124,8 @@ public final class DataExtraction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void handlePicture(HSLFPictureData data, int picIdx) throws IOException {
|
private static void handlePicture(HSLFPictureShape p, int picIdx) throws IOException {
|
||||||
|
HSLFPictureData data = p.getPictureData();
|
||||||
String ext = data.getType().extension;
|
String ext = data.getType().extension;
|
||||||
try (FileOutputStream out = new FileOutputStream("pict-" + picIdx + ext)) {
|
try (FileOutputStream out = new FileOutputStream("pict-" + picIdx + ext)) {
|
||||||
out.write(data.getData());
|
out.write(data.getData());
|
||||||
|
@ -42,7 +42,7 @@ public final class Graphics2DDemo {
|
|||||||
try (HSLFSlideShow ppt = new HSLFSlideShow();
|
try (HSLFSlideShow ppt = new HSLFSlideShow();
|
||||||
FileOutputStream out = new FileOutputStream("hslf-graphics.ppt")) {
|
FileOutputStream out = new FileOutputStream("hslf-graphics.ppt")) {
|
||||||
//bar chart data. The first value is the bar color, the second is the width
|
//bar chart data. The first value is the bar color, the second is the width
|
||||||
Object[] def = new Object[]{
|
Object[] def = {
|
||||||
Color.yellow, 40,
|
Color.yellow, 40,
|
||||||
Color.green, 60,
|
Color.green, 60,
|
||||||
Color.gray, 30,
|
Color.gray, 30,
|
||||||
|
@ -31,22 +31,21 @@ import org.apache.poi.hsmf.exceptions.ChunkNotFoundException;
|
|||||||
* Reads one or several Outlook MSG files and for each of them creates
|
* Reads one or several Outlook MSG files and for each of them creates
|
||||||
* a text file from available chunks and a directory that contains
|
* a text file from available chunks and a directory that contains
|
||||||
* attachments.
|
* attachments.
|
||||||
*
|
|
||||||
* @author Bruno Girin
|
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings({"java:S106","java:S4823"})
|
||||||
public class Msg2txt {
|
public class Msg2txt {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The stem used to create file names for the text file and the directory
|
* The stem used to create file names for the text file and the directory
|
||||||
* that contains the attachments.
|
* that contains the attachments.
|
||||||
*/
|
*/
|
||||||
private String fileNameStem;
|
private String fileNameStem;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Outlook MSG file being processed.
|
* The Outlook MSG file being processed.
|
||||||
*/
|
*/
|
||||||
private MAPIMessage msg;
|
private MAPIMessage msg;
|
||||||
|
|
||||||
public Msg2txt(String fileName) throws IOException {
|
public Msg2txt(String fileName) throws IOException {
|
||||||
fileNameStem = fileName;
|
fileNameStem = fileName;
|
||||||
if(fileNameStem.endsWith(".msg") || fileNameStem.endsWith(".MSG")) {
|
if(fileNameStem.endsWith(".msg") || fileNameStem.endsWith(".MSG")) {
|
||||||
@ -54,10 +53,10 @@ public class Msg2txt {
|
|||||||
}
|
}
|
||||||
msg = new MAPIMessage(fileName);
|
msg = new MAPIMessage(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Processes the message.
|
* Processes the message.
|
||||||
*
|
*
|
||||||
* @throws IOException if an exception occurs while writing the message out
|
* @throws IOException if an exception occurs while writing the message out
|
||||||
*/
|
*/
|
||||||
public void processMessage() throws IOException {
|
public void processMessage() throws IOException {
|
||||||
@ -114,7 +113,7 @@ public class Msg2txt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Processes a single attachment: reads it from the Outlook MSG file and
|
* Processes a single attachment: reads it from the Outlook MSG file and
|
||||||
* writes it to disk as an individual file.
|
* writes it to disk as an individual file.
|
||||||
@ -123,22 +122,22 @@ public class Msg2txt {
|
|||||||
* @param dir the directory in which to write the attachment file
|
* @param dir the directory in which to write the attachment file
|
||||||
* @throws IOException when any of the file operations fails
|
* @throws IOException when any of the file operations fails
|
||||||
*/
|
*/
|
||||||
public void processAttachment(AttachmentChunks attachment,
|
public void processAttachment(AttachmentChunks attachment,
|
||||||
File dir) throws IOException {
|
File dir) throws IOException {
|
||||||
String fileName = attachment.getAttachFileName().toString();
|
String fileName = attachment.getAttachFileName().toString();
|
||||||
if(attachment.getAttachLongFileName() != null) {
|
if(attachment.getAttachLongFileName() != null) {
|
||||||
fileName = attachment.getAttachLongFileName().toString();
|
fileName = attachment.getAttachLongFileName().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
File f = new File(dir, fileName);
|
File f = new File(dir, fileName);
|
||||||
try (OutputStream fileOut = new FileOutputStream(f)) {
|
try (OutputStream fileOut = new FileOutputStream(f)) {
|
||||||
fileOut.write(attachment.getAttachData().getValue());
|
fileOut.write(attachment.getAttachData().getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Processes the list of arguments as a list of names of Outlook MSG files.
|
* Processes the list of arguments as a list of names of Outlook MSG files.
|
||||||
*
|
*
|
||||||
* @param args the list of MSG files to process
|
* @param args the list of MSG files to process
|
||||||
*/
|
*/
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
@ -43,7 +43,6 @@ import org.apache.poi.hssf.record.LabelSSTRecord;
|
|||||||
import org.apache.poi.hssf.record.NoteRecord;
|
import org.apache.poi.hssf.record.NoteRecord;
|
||||||
import org.apache.poi.hssf.record.NumberRecord;
|
import org.apache.poi.hssf.record.NumberRecord;
|
||||||
import org.apache.poi.hssf.record.RKRecord;
|
import org.apache.poi.hssf.record.RKRecord;
|
||||||
import org.apache.poi.hssf.record.Record;
|
|
||||||
import org.apache.poi.hssf.record.SSTRecord;
|
import org.apache.poi.hssf.record.SSTRecord;
|
||||||
import org.apache.poi.hssf.record.StringRecord;
|
import org.apache.poi.hssf.record.StringRecord;
|
||||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||||
@ -54,6 +53,7 @@ import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
|||||||
* EventModel code to ensure it outputs all columns and rows.
|
* EventModel code to ensure it outputs all columns and rows.
|
||||||
* @author Nick Burch
|
* @author Nick Burch
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings({"java:S106","java:S4823"})
|
||||||
public class XLS2CSVmra implements HSSFListener {
|
public class XLS2CSVmra implements HSSFListener {
|
||||||
private int minColumns;
|
private int minColumns;
|
||||||
private POIFSFileSystem fs;
|
private POIFSFileSystem fs;
|
||||||
@ -72,7 +72,7 @@ public class XLS2CSVmra implements HSSFListener {
|
|||||||
// Records we pick up as we process
|
// Records we pick up as we process
|
||||||
private SSTRecord sstRecord;
|
private SSTRecord sstRecord;
|
||||||
private FormatTrackingHSSFListener formatListener;
|
private FormatTrackingHSSFListener formatListener;
|
||||||
|
|
||||||
/** So we known which sheet we're on */
|
/** So we known which sheet we're on */
|
||||||
private int sheetIndex = -1;
|
private int sheetIndex = -1;
|
||||||
private BoundSheetRecord[] orderedBSRs;
|
private BoundSheetRecord[] orderedBSRs;
|
||||||
@ -149,7 +149,7 @@ public class XLS2CSVmra implements HSSFListener {
|
|||||||
if(workbookBuildingListener != null && stubWorkbook == null) {
|
if(workbookBuildingListener != null && stubWorkbook == null) {
|
||||||
stubWorkbook = workbookBuildingListener.getStubHSSFWorkbook();
|
stubWorkbook = workbookBuildingListener.getStubHSSFWorkbook();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Output the worksheet name
|
// Output the worksheet name
|
||||||
// Works by ordering the BSRs by the location of
|
// Works by ordering the BSRs by the location of
|
||||||
// their BOFRecords, and then knowing that we
|
// their BOFRecords, and then knowing that we
|
||||||
@ -159,7 +159,7 @@ public class XLS2CSVmra implements HSSFListener {
|
|||||||
orderedBSRs = BoundSheetRecord.orderByBofPosition(boundSheetRecords);
|
orderedBSRs = BoundSheetRecord.orderByBofPosition(boundSheetRecords);
|
||||||
}
|
}
|
||||||
output.println();
|
output.println();
|
||||||
output.println(
|
output.println(
|
||||||
orderedBSRs[sheetIndex].getSheetname() +
|
orderedBSRs[sheetIndex].getSheetname() +
|
||||||
" [" + (sheetIndex+1) + "]:"
|
" [" + (sheetIndex+1) + "]:"
|
||||||
);
|
);
|
||||||
|
@ -18,873 +18,6 @@
|
|||||||
|
|
||||||
package org.apache.poi.hssf.usermodel.examples;
|
package org.apache.poi.hssf.usermodel.examples;
|
||||||
|
|
||||||
import java.io.File;
|
/* Placeholder - this is now handled in the Common SS example **/
|
||||||
import java.io.FileInputStream;
|
public class AddDimensionedImage extends org.apache.poi.ss.examples.AddDimensionedImage {
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
|
|
||||||
import org.apache.poi.hssf.usermodel.HSSFPatriarch;
|
|
||||||
import org.apache.poi.hssf.usermodel.HSSFRow;
|
|
||||||
import org.apache.poi.hssf.usermodel.HSSFSheet;
|
|
||||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
|
||||||
import org.apache.poi.ss.usermodel.ClientAnchor.AnchorType;
|
|
||||||
import org.apache.poi.ss.usermodel.Workbook;
|
|
||||||
import org.apache.poi.ss.util.CellReference;
|
|
||||||
import org.apache.poi.util.IOUtils;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Demonstrates how to add an image to a worksheet and set that image's size
|
|
||||||
* to a specific number of milimetres irrespective of the width of the columns
|
|
||||||
* or height of the rows. Overridden methods are provided so that the location
|
|
||||||
* of the image - the cells row and column co-ordinates that define the top
|
|
||||||
* left hand corners of the image - can be identified either in the familiar
|
|
||||||
* Excel manner - A1 for instance - or using POI's methodolody of a column and
|
|
||||||
* row index where 0, 0 would indicate cell A1.
|
|
||||||
*
|
|
||||||
* The best way to make use of these techniques is to delay adding the image to
|
|
||||||
* the sheet until all other work has been completed. That way, the sizes of
|
|
||||||
* all rows and columns will have been adjusted - assuming that step was
|
|
||||||
* necessary. Even though the anchors type is set to prevent the image moving
|
|
||||||
* or re-sizing, this setting does not have any effect until the sheet is being
|
|
||||||
* viewed using the Excel application.
|
|
||||||
*
|
|
||||||
* The key to the process is the HSSFClientAnchor class. It accepts eight
|
|
||||||
* parameters that define, in order;
|
|
||||||
*
|
|
||||||
* * How far - in terms of co-ordinate position - the image should be inset
|
|
||||||
* from the left hand border of a cell.
|
|
||||||
* * How far - in terms of co-ordinate positions - the image should be inset
|
|
||||||
* from the from the top of the cell.
|
|
||||||
* * How far - in terms of co-ordinate positions - the right hand edge of
|
|
||||||
* the image should protrude into a cell (measured from the cell's left hand
|
|
||||||
* edge to the image's right hand edge).
|
|
||||||
* * How far - in terms of co-ordinate positions - the bottm edge of the
|
|
||||||
* image should protrude into a row (measured from the cell's top edge to
|
|
||||||
* the image's bottom edge).
|
|
||||||
* * The index of the column that contains the cell whose top left hand
|
|
||||||
* corner should be aligned with the top left hand corner of the image.
|
|
||||||
* * The index of the row that contains the cell whose top left hand corner
|
|
||||||
* should be aligned with the image's top left hand corner.
|
|
||||||
* * The index of the column that contains the cell whose top left hand
|
|
||||||
* corner should be aligned with the image's bottom right hand corner
|
|
||||||
* * The index number of the row that contains the cell whose top left
|
|
||||||
* hand corner should be aligned with the images bottom right hand corner.
|
|
||||||
*
|
|
||||||
* It can be used to add an image into cell A1, for example, in the following
|
|
||||||
* manner;
|
|
||||||
*
|
|
||||||
* HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0, 0, 0,
|
|
||||||
* (short)0, 0, (short)1, 1);
|
|
||||||
*
|
|
||||||
* The final four parameters determine that the top left hand corner should be
|
|
||||||
* aligned with the top left hand corner of cell A1 and it's bottom right
|
|
||||||
* hand corner with the top left hand corner of cell B2. Think of the image as
|
|
||||||
* being stretched so that it's top left hand corner is aligned with the top
|
|
||||||
* left hand corner of cell A1 and it's bottom right hand corner is aligned with
|
|
||||||
* the top left hand corner of cell B1. Interestingly, this would also produce
|
|
||||||
* the same results;
|
|
||||||
*
|
|
||||||
* anchor = new HSSFClientAnchor(0, 0, 1023, 255,
|
|
||||||
* (short)0, 0, (short)0, 0);
|
|
||||||
*
|
|
||||||
* Note that the final four parameters all contain the same value and seem to
|
|
||||||
* indicate that the images top left hand corner is aligned with the top left
|
|
||||||
* hand corner of cell A1 and that it's bottom right hand corner is also
|
|
||||||
* aligned with the top left hand corner of cell A1. Yet, running this code
|
|
||||||
* would see the image fully occupying cell A1. That is the result of the
|
|
||||||
* values passed to parameters three and four; these I have referred to as
|
|
||||||
* determing the images co-ordinates within the cell. They indicate that the
|
|
||||||
* image should occupy - in order - the full width of the column and the full
|
|
||||||
* height of the row.
|
|
||||||
*
|
|
||||||
* The co-ordinate values shown are the maxima; and they are independent of
|
|
||||||
* row height/column width and of the font used. Passing 255 will always result
|
|
||||||
* in the image occupying the full height of the row and passing 1023 will
|
|
||||||
* always result in the image occupying the full width of the column. They help
|
|
||||||
* in situations where an image is larger than a column/row and must overlap
|
|
||||||
* into the next column/row. Using them does mean, however, that it is often
|
|
||||||
* necessary to perform conversions between Excel's characters units, points,
|
|
||||||
* pixels and millimetres in order to establish how many rows/columns an image
|
|
||||||
* should occupy and just what the varous insets ought to be.
|
|
||||||
*
|
|
||||||
* Note that the first two parameters of the HSSFClientAchor classes constructor
|
|
||||||
* are not made use of in the code that follows. It would be fairly trivial
|
|
||||||
* however to extend these example further and provide methods that would centre
|
|
||||||
* an image within a cell or allow the user to specify that a plain border a
|
|
||||||
* fixed number of millimetres wide should wrap around the image. Those first
|
|
||||||
* two parameters would make this sort of functionality perfectly possible.
|
|
||||||
*
|
|
||||||
* Owing to the various conversions used, the actual size of the image may vary
|
|
||||||
* from that required; testing has so far found this to be in the region of
|
|
||||||
* plus or minus two millimetres. Most likely by modifying the way the
|
|
||||||
* calculations are performed - possibly using double(s) throughout and
|
|
||||||
* rounding the values at the correct point - it is likely that these errors
|
|
||||||
* could be reduced or removed.
|
|
||||||
*
|
|
||||||
* A note concerning Excels' image resizing behaviour. The HSSFClientAnchor
|
|
||||||
* class contains a method called setAnchorType(int) which can be used to
|
|
||||||
* determine how Excel will resize an image in reponse to the user increasing
|
|
||||||
* or decreasing the dimensions of the cell containing the image. There are
|
|
||||||
* three values that can be passed to this method; 0 = To move and size the
|
|
||||||
* image with the cell, 2 = To move but don't size the image with the cell,
|
|
||||||
* 3 = To prevent the image from moving or being resized along with the cell. If
|
|
||||||
* an image is inserted using this class and placed into a single cell then if
|
|
||||||
* the setAnchorType(int) method is called and a value of either 0 or 2 passed
|
|
||||||
* to it, the resultant resizing behaviour may be a surprise. The image will not
|
|
||||||
* grow in size of the column is made wider or the row higher but it will shrink
|
|
||||||
* if the columns width or rows height are reduced.
|
|
||||||
*
|
|
||||||
* @author Mark Beardsley [msb at apache.org]
|
|
||||||
* @version 1.00 5th August 2009.
|
|
||||||
*/
|
|
||||||
public class AddDimensionedImage {
|
|
||||||
|
|
||||||
// Four constants that determine how - and indeed whether - the rows
|
|
||||||
// and columns an image may overlie should be expanded to accommodate that
|
|
||||||
// image.
|
|
||||||
// Passing EXPAND_ROW will result in the height of a row being increased
|
|
||||||
// to accommodate the image if it is not already larger. The image will
|
|
||||||
// be layed across one or more columns.
|
|
||||||
// Passing EXPAND_COLUMN will result in the width of the column being
|
|
||||||
// increased to accommodate the image if it is not already larger. The image
|
|
||||||
// will be layed across one or many rows.
|
|
||||||
// Passing EXPAND_ROW_AND_COLUMN will result in the height of the row
|
|
||||||
// bing increased along with the width of the column to accomdate the
|
|
||||||
// image if either is not already larger.
|
|
||||||
// Passing OVERLAY_ROW_AND_COLUMN will result in the image being layed
|
|
||||||
// over one or more rows and columns. No row or column will be resized,
|
|
||||||
// instead, code will determine how many rows and columns the image should
|
|
||||||
// overlie.
|
|
||||||
public static final int EXPAND_ROW = 1;
|
|
||||||
public static final int EXPAND_COLUMN = 2;
|
|
||||||
public static final int EXPAND_ROW_AND_COLUMN = 3;
|
|
||||||
public static final int OVERLAY_ROW_AND_COLUMN = 7;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add an image to a worksheet.
|
|
||||||
*
|
|
||||||
* @param cellNumber A String that contains the location of the cell whose
|
|
||||||
* top left hand corner should be aligned with the top
|
|
||||||
* left hand corner of the image; for example "A1", "A2"
|
|
||||||
* etc. This is to support the familiar Excel syntax.
|
|
||||||
* Whilst images are are not actually inserted into cells
|
|
||||||
* this provides a convenient method of indicating where
|
|
||||||
* the image should be positioned on the sheet.
|
|
||||||
* @param sheet A reference to the sheet that contains the cell referenced
|
|
||||||
* above.
|
|
||||||
* @param imageFile A String that encapsulates the name of and path to
|
|
||||||
* the image that is to be 'inserted into' the sheet.
|
|
||||||
* @param reqImageWidthMM A primitive double that contains the required
|
|
||||||
* width of the image in millimetres.
|
|
||||||
* @param reqImageHeightMM A primitive double that contains the required
|
|
||||||
* height of the image in millimetres.
|
|
||||||
* @param resizeBehaviour A primitive int whose value will determine how
|
|
||||||
* the code should react if the image is larger than
|
|
||||||
* the cell referenced by the cellNumber parameter.
|
|
||||||
* Four constants are provided to determine what
|
|
||||||
* should happen;
|
|
||||||
* AddDimensionedImage.EXPAND_ROW
|
|
||||||
* AddDimensionedImage.EXPAND_COLUMN
|
|
||||||
* AddDimensionedImage.EXPAND_ROW_AND_COLUMN
|
|
||||||
* AddDimensionedImage.OVERLAY_ROW_AND_COLUMN
|
|
||||||
* @throws java.io.FileNotFoundException If the file containing the image
|
|
||||||
* cannot be located.
|
|
||||||
* @throws java.io.IOException If a problem occurs whilst reading the file
|
|
||||||
* of image data.
|
|
||||||
* @throws java.lang.IllegalArgumentException If an invalid value is passed
|
|
||||||
* to the resizeBehaviour
|
|
||||||
* parameter.
|
|
||||||
*/
|
|
||||||
public void addImageToSheet(String cellNumber, HSSFSheet sheet,
|
|
||||||
String imageFile, double reqImageWidthMM, double reqImageHeightMM,
|
|
||||||
int resizeBehaviour) throws IOException, IllegalArgumentException {
|
|
||||||
// Convert the String into column and row indices then chain the
|
|
||||||
// call to the overridden addImageToSheet() method.
|
|
||||||
CellReference cellRef = new CellReference(cellNumber);
|
|
||||||
this.addImageToSheet(cellRef.getCol(), cellRef.getRow(), sheet,
|
|
||||||
imageFile, reqImageWidthMM, reqImageHeightMM,resizeBehaviour);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add an image to a worksheet.
|
|
||||||
*
|
|
||||||
* @param colNumber A primitive int that contains the index number of a
|
|
||||||
* column on the worksheet; POI column indices are zero
|
|
||||||
* based. Together with the rowNumber parameter's value,
|
|
||||||
* this parameter identifies a cell on the worksheet. The
|
|
||||||
* image's top left hand corner will be aligned with the
|
|
||||||
* top left hand corner of this cell.
|
|
||||||
* @param rowNumber A primtive int that contains the index number of a row
|
|
||||||
* on the worksheet; POI row indices are zero based.
|
|
||||||
* Together with the rowNumber parameter's value, this
|
|
||||||
* parameter identifies a cell on the worksheet. The
|
|
||||||
* image's top left hand corner will be aligned with the
|
|
||||||
* top left hand corner of this cell.
|
|
||||||
* @param sheet A reference to the sheet that contains the cell identified
|
|
||||||
* by the two parameters above.
|
|
||||||
* @param imageFile A String that encapsulates the name of and path to
|
|
||||||
* the image that is to be 'inserted into' the sheet.
|
|
||||||
* @param reqImageWidthMM A primitive double that contains the required
|
|
||||||
* width of the image in millimetres.
|
|
||||||
* @param reqImageHeightMM A primitive double that contains the required
|
|
||||||
* height of the image in millimetres.
|
|
||||||
* @param resizeBehaviour A primitive int whose value will determine how
|
|
||||||
* the code should react if the image is larger than
|
|
||||||
* the cell referenced by the colNumber and
|
|
||||||
* rowNumber parameters. Four constants are provided
|
|
||||||
* to determine what should happen;
|
|
||||||
* AddDimensionedImage.EXPAND_ROW
|
|
||||||
* AddDimensionedImage.EXPAND_COLUMN
|
|
||||||
* AddDimensionedImage.EXPAND_ROW_AND_COLUMN
|
|
||||||
* AddDimensionedImage.OVERLAY_ROW_AND_COLUMN
|
|
||||||
* @throws java.io.FileNotFoundException If the file containing the image
|
|
||||||
* cannot be located.
|
|
||||||
* @throws java.io.IOException If a problem occurs whilst reading the file
|
|
||||||
* of image data.
|
|
||||||
* @throws java.lang.IllegalArgumentException If an invalid value is passed
|
|
||||||
* to the resizeBehaviour
|
|
||||||
* parameter.
|
|
||||||
*/
|
|
||||||
private void addImageToSheet(int colNumber, int rowNumber, HSSFSheet sheet,
|
|
||||||
String imageFile, double reqImageWidthMM, double reqImageHeightMM,
|
|
||||||
int resizeBehaviour) throws FileNotFoundException, IOException,
|
|
||||||
IllegalArgumentException {
|
|
||||||
HSSFClientAnchor anchor;
|
|
||||||
HSSFPatriarch patriarch;
|
|
||||||
ClientAnchorDetail rowClientAnchorDetail;
|
|
||||||
ClientAnchorDetail colClientAnchorDetail;
|
|
||||||
|
|
||||||
// Validate the resizeBehaviour parameter.
|
|
||||||
if((resizeBehaviour != AddDimensionedImage.EXPAND_COLUMN) &&
|
|
||||||
(resizeBehaviour != AddDimensionedImage.EXPAND_ROW) &&
|
|
||||||
(resizeBehaviour != AddDimensionedImage.EXPAND_ROW_AND_COLUMN) &&
|
|
||||||
(resizeBehaviour != AddDimensionedImage.OVERLAY_ROW_AND_COLUMN)) {
|
|
||||||
throw new IllegalArgumentException("Invalid value passed to the " +
|
|
||||||
"resizeBehaviour parameter of AddDimensionedImage.addImageToSheet()");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call methods to calculate how the image and sheet should be
|
|
||||||
// manipulated to accommodate the image; columns and then rows.
|
|
||||||
colClientAnchorDetail = this.fitImageToColumns(sheet, colNumber,
|
|
||||||
reqImageWidthMM, resizeBehaviour);
|
|
||||||
rowClientAnchorDetail = this.fitImageToRows(sheet, rowNumber,
|
|
||||||
reqImageHeightMM, resizeBehaviour);
|
|
||||||
|
|
||||||
// Having determined if and how to resize the rows, columns and/or the
|
|
||||||
// image, create the HSSFClientAnchor object to position the image on
|
|
||||||
// the worksheet. Note how the two ClientAnchorDetail records are
|
|
||||||
// interrogated to recover the row/column co-ordinates and any insets.
|
|
||||||
// The first two parameters are not used currently but could be if the
|
|
||||||
// need arose to extend the functionality of this code by adding the
|
|
||||||
// ability to specify that a clear 'border' be placed around the image.
|
|
||||||
int dx1 = 0, dy1 = 0, dx2 = 0, dy2 = 0;
|
|
||||||
short col1 = 0, col2 = 0, row1 = 0, row2 = 0;
|
|
||||||
if (colClientAnchorDetail != null) {
|
|
||||||
dx2 = colClientAnchorDetail.getInset();
|
|
||||||
col1 = (short)colClientAnchorDetail.getFromIndex();
|
|
||||||
col2 = (short)colClientAnchorDetail.getToIndex();
|
|
||||||
}
|
|
||||||
if (rowClientAnchorDetail != null) {
|
|
||||||
dy2 = rowClientAnchorDetail.getInset();
|
|
||||||
row1 = (short)rowClientAnchorDetail.getFromIndex();
|
|
||||||
row2 = (short)rowClientAnchorDetail.getToIndex();
|
|
||||||
}
|
|
||||||
anchor = new HSSFClientAnchor(dx1, dy1, dx2, dy2, col1, row1, col2, row2);
|
|
||||||
|
|
||||||
// For now, set the anchor type to do not move or resize the
|
|
||||||
// image as the size of the row/column is adjusted. This could easilly
|
|
||||||
// become another parameter passed to the method.
|
|
||||||
//anchor.setAnchorType(HSSFClientAnchor.DONT_MOVE_AND_RESIZE);
|
|
||||||
anchor.setAnchorType(AnchorType.MOVE_AND_RESIZE);
|
|
||||||
|
|
||||||
// Now, add the picture to the workbook. Note that the type is assumed
|
|
||||||
// to be a JPEG/JPG, this could easily (and should) be parameterised
|
|
||||||
// however.
|
|
||||||
//int index = sheet.getWorkbook().addPicture(this.imageToBytes(imageFile),
|
|
||||||
// HSSFWorkbook.PICTURE_TYPE_JPEG);
|
|
||||||
int index = sheet.getWorkbook().addPicture(this.imageToBytes(imageFile), Workbook.PICTURE_TYPE_PNG);
|
|
||||||
|
|
||||||
// Get the drawing patriarch and create the picture.
|
|
||||||
patriarch = sheet.createDrawingPatriarch();
|
|
||||||
patriarch.createPicture(anchor, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines whether the sheets columns should be re-sized to accommodate
|
|
||||||
* the image, adjusts the columns width if necessary and creates then
|
|
||||||
* returns a ClientAnchorDetail object that facilitates construction of
|
|
||||||
* an HSSFClientAnchor that will fix the image on the sheet and establish
|
|
||||||
* it's size.
|
|
||||||
*
|
|
||||||
* @param sheet A reference to the sheet that will 'contain' the image.
|
|
||||||
* @param colNumber A primtive int that contains the index number of a
|
|
||||||
* column on the sheet.
|
|
||||||
* @param reqImageWidthMM A primtive double that contains the required
|
|
||||||
* width of the image in millimetres
|
|
||||||
* @param resizeBehaviour A primitve int whose value will indicate how the
|
|
||||||
* width of the column should be adjusted if the
|
|
||||||
* required width of the image is greater than the
|
|
||||||
* width of the column.
|
|
||||||
* @return An instance of the ClientAnchorDetail class that will contain
|
|
||||||
* the index number of the column containing the cell whose top
|
|
||||||
* left hand corner also defines the top left hand corner of the
|
|
||||||
* image, the index number column containing the cell whose top
|
|
||||||
* left hand corner also defines the bottom right hand corner of
|
|
||||||
* the image and an inset that determines how far the right hand
|
|
||||||
* edge of the image can protrude into the next column - expressed
|
|
||||||
* as a specific number of co-ordinate positions.
|
|
||||||
*/
|
|
||||||
private ClientAnchorDetail fitImageToColumns(HSSFSheet sheet, int colNumber,
|
|
||||||
double reqImageWidthMM, int resizeBehaviour) {
|
|
||||||
|
|
||||||
double colWidthMM;
|
|
||||||
double colCoordinatesPerMM;
|
|
||||||
int pictureWidthCoordinates;
|
|
||||||
ClientAnchorDetail colClientAnchorDetail = null;
|
|
||||||
|
|
||||||
// Get the colum's width in millimetres
|
|
||||||
colWidthMM = ConvertImageUnits.widthUnits2Millimetres(
|
|
||||||
(short)sheet.getColumnWidth(colNumber));
|
|
||||||
|
|
||||||
// Check that the column's width will accommodate the image at the
|
|
||||||
// required dimension. If the width of the column is LESS than the
|
|
||||||
// required width of the image, decide how the application should
|
|
||||||
// respond - resize the column or overlay the image across one or more
|
|
||||||
// columns.
|
|
||||||
if(colWidthMM < reqImageWidthMM) {
|
|
||||||
|
|
||||||
// Should the column's width simply be expanded?
|
|
||||||
if((resizeBehaviour == AddDimensionedImage.EXPAND_COLUMN) ||
|
|
||||||
(resizeBehaviour == AddDimensionedImage.EXPAND_ROW_AND_COLUMN)) {
|
|
||||||
// Set the width of the column by converting the required image
|
|
||||||
// width from millimetres into Excel's column width units.
|
|
||||||
sheet.setColumnWidth(colNumber,
|
|
||||||
ConvertImageUnits.millimetres2WidthUnits(reqImageWidthMM));
|
|
||||||
// To make the image occupy the full width of the column, convert
|
|
||||||
// the required width of the image into co-ordinates. This value
|
|
||||||
// will become the inset for the ClientAnchorDetail class that
|
|
||||||
// is then instantiated.
|
|
||||||
colWidthMM = reqImageWidthMM;
|
|
||||||
colCoordinatesPerMM = ConvertImageUnits.TOTAL_COLUMN_COORDINATE_POSITIONS /
|
|
||||||
colWidthMM;
|
|
||||||
pictureWidthCoordinates = (int)(reqImageWidthMM * colCoordinatesPerMM);
|
|
||||||
colClientAnchorDetail = new ClientAnchorDetail(colNumber,
|
|
||||||
colNumber, pictureWidthCoordinates);
|
|
||||||
}
|
|
||||||
// If the user has chosen to overlay both rows and columns or just
|
|
||||||
// to expand ONLY the size of the rows, then calculate how to lay
|
|
||||||
// the image out across one or more columns.
|
|
||||||
else if ((resizeBehaviour == AddDimensionedImage.OVERLAY_ROW_AND_COLUMN) ||
|
|
||||||
(resizeBehaviour == AddDimensionedImage.EXPAND_ROW)) {
|
|
||||||
colClientAnchorDetail = this.calculateColumnLocation(sheet,
|
|
||||||
colNumber, reqImageWidthMM);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// If the column is wider than the image.
|
|
||||||
else {
|
|
||||||
// Mow many co-ordinate positions are there per millimetre?
|
|
||||||
colCoordinatesPerMM = ConvertImageUnits.TOTAL_COLUMN_COORDINATE_POSITIONS /
|
|
||||||
colWidthMM;
|
|
||||||
// Given the width of the image, what should be it's co-ordinate?
|
|
||||||
pictureWidthCoordinates = (int)(reqImageWidthMM * colCoordinatesPerMM);
|
|
||||||
colClientAnchorDetail = new ClientAnchorDetail(colNumber,
|
|
||||||
colNumber, pictureWidthCoordinates);
|
|
||||||
}
|
|
||||||
return(colClientAnchorDetail);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines whether the sheet's row should be re-sized to accommodate
|
|
||||||
* the image, adjusts the rows height if necessary and creates then
|
|
||||||
* returns a ClientAnchorDetail object that facilitates construction of
|
|
||||||
* an HSSFClientAnchor that will fix the image on the sheet and establish
|
|
||||||
* it's size.
|
|
||||||
*
|
|
||||||
* @param sheet A reference to the sheet that will 'contain' the image.
|
|
||||||
* @param rowNumber A primtive int that contains the index number of a
|
|
||||||
* row on the sheet.
|
|
||||||
* @param reqImageHeightMM A primtive double that contains the required
|
|
||||||
* height of the image in millimetres
|
|
||||||
* @param resizeBehaviour A primitve int whose value will indicate how the
|
|
||||||
* height of the row should be adjusted if the
|
|
||||||
* required height of the image is greater than the
|
|
||||||
* height of the row.
|
|
||||||
* @return An instance of the ClientAnchorDetail class that will contain
|
|
||||||
* the index number of the row containing the cell whose top
|
|
||||||
* left hand corner also defines the top left hand corner of the
|
|
||||||
* image, the index number of the row containing the cell whose
|
|
||||||
* top left hand corner also defines the bottom right hand
|
|
||||||
* corner of the image and an inset that determines how far the
|
|
||||||
* bottom edge of the image can protrude into the next (lower)
|
|
||||||
* row - expressed as a specific number of co-ordinate positions.
|
|
||||||
*/
|
|
||||||
private ClientAnchorDetail fitImageToRows(HSSFSheet sheet, int rowNumber,
|
|
||||||
double reqImageHeightMM, int resizeBehaviour) {
|
|
||||||
double rowCoordinatesPerMM;
|
|
||||||
int pictureHeightCoordinates;
|
|
||||||
ClientAnchorDetail rowClientAnchorDetail = null;
|
|
||||||
|
|
||||||
// Get the row and it's height
|
|
||||||
HSSFRow row = sheet.getRow(rowNumber);
|
|
||||||
if(row == null) {
|
|
||||||
// Create row if it does not exist.
|
|
||||||
row = sheet.createRow(rowNumber);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the row's height in millimetres
|
|
||||||
double rowHeightMM = row.getHeightInPoints() / ConvertImageUnits.POINTS_PER_MILLIMETRE;
|
|
||||||
|
|
||||||
// Check that the row's height will accommodate the image at the required
|
|
||||||
// dimensions. If the height of the row is LESS than the required height
|
|
||||||
// of the image, decide how the application should respond - resize the
|
|
||||||
// row or overlay the image across a series of rows.
|
|
||||||
if(rowHeightMM < reqImageHeightMM) {
|
|
||||||
if((resizeBehaviour == AddDimensionedImage.EXPAND_ROW) ||
|
|
||||||
(resizeBehaviour == AddDimensionedImage.EXPAND_ROW_AND_COLUMN)) {
|
|
||||||
row.setHeightInPoints((float)(reqImageHeightMM *
|
|
||||||
ConvertImageUnits.POINTS_PER_MILLIMETRE));
|
|
||||||
rowHeightMM = reqImageHeightMM;
|
|
||||||
rowCoordinatesPerMM = ConvertImageUnits.TOTAL_ROW_COORDINATE_POSITIONS /
|
|
||||||
rowHeightMM;
|
|
||||||
pictureHeightCoordinates = (int)(reqImageHeightMM * rowCoordinatesPerMM);
|
|
||||||
rowClientAnchorDetail = new ClientAnchorDetail(rowNumber,
|
|
||||||
rowNumber, pictureHeightCoordinates);
|
|
||||||
}
|
|
||||||
// If the user has chosen to overlay both rows and columns or just
|
|
||||||
// to expand ONLY the size of the columns, then calculate how to lay
|
|
||||||
// the image out ver one or more rows.
|
|
||||||
else if((resizeBehaviour == AddDimensionedImage.OVERLAY_ROW_AND_COLUMN) ||
|
|
||||||
(resizeBehaviour == AddDimensionedImage.EXPAND_COLUMN)) {
|
|
||||||
rowClientAnchorDetail = this.calculateRowLocation(sheet,
|
|
||||||
rowNumber, reqImageHeightMM);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Else, if the image is smaller than the space available
|
|
||||||
else {
|
|
||||||
rowCoordinatesPerMM = ConvertImageUnits.TOTAL_ROW_COORDINATE_POSITIONS /
|
|
||||||
rowHeightMM;
|
|
||||||
pictureHeightCoordinates = (int)(reqImageHeightMM * rowCoordinatesPerMM);
|
|
||||||
rowClientAnchorDetail = new ClientAnchorDetail(rowNumber,
|
|
||||||
rowNumber, pictureHeightCoordinates);
|
|
||||||
}
|
|
||||||
return(rowClientAnchorDetail);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If the image is to overlie more than one column, calculations need to be
|
|
||||||
* performed to determine how many columns and whether the image will
|
|
||||||
* overlie just a part of one column in order to be presented at the
|
|
||||||
* required size.
|
|
||||||
*
|
|
||||||
* @param sheet The sheet that will 'contain' the image.
|
|
||||||
* @param startingColumn A primitive int whose value is the index of the
|
|
||||||
* column that contains the cell whose top left hand
|
|
||||||
* corner should be aligned with the top left hand
|
|
||||||
* corner of the image.
|
|
||||||
* @param reqImageWidthMM A primitive double whose value will indicate the
|
|
||||||
* required width of the image in millimetres.
|
|
||||||
* @return An instance of the ClientAnchorDetail class that will contain
|
|
||||||
* the index number of the column containing the cell whose top
|
|
||||||
* left hand corner also defines the top left hand corner of the
|
|
||||||
* image, the index number column containing the cell whose top
|
|
||||||
* left hand corner also defines the bottom right hand corner of
|
|
||||||
* the image and an inset that determines how far the right hand
|
|
||||||
* edge of the image can protrude into the next column - expressed
|
|
||||||
* as a specific number of co-ordinate positions.
|
|
||||||
*/
|
|
||||||
private ClientAnchorDetail calculateColumnLocation(HSSFSheet sheet,
|
|
||||||
int startingColumn,
|
|
||||||
double reqImageWidthMM) {
|
|
||||||
ClientAnchorDetail anchorDetail;
|
|
||||||
double totalWidthMM = 0.0D;
|
|
||||||
double colWidthMM = 0.0D;
|
|
||||||
double overlapMM;
|
|
||||||
double coordinatePositionsPerMM;
|
|
||||||
int toColumn = startingColumn;
|
|
||||||
int inset;
|
|
||||||
|
|
||||||
// Calculate how many columns the image will have to
|
|
||||||
// span in order to be presented at the required size.
|
|
||||||
while(totalWidthMM < reqImageWidthMM) {
|
|
||||||
colWidthMM = ConvertImageUnits.widthUnits2Millimetres(
|
|
||||||
(short)(sheet.getColumnWidth(toColumn)));
|
|
||||||
// Note use of the cell border width constant. Testing with an image
|
|
||||||
// declared to fit exactly into one column demonstrated that it's
|
|
||||||
// width was greater than the width of the column the POI returned.
|
|
||||||
// Further, this difference was a constant value that I am assuming
|
|
||||||
// related to the cell's borders. Either way, that difference needs
|
|
||||||
// to be allowed for in this calculation.
|
|
||||||
totalWidthMM += (colWidthMM + ConvertImageUnits.CELL_BORDER_WIDTH_MILLIMETRES);
|
|
||||||
toColumn++;
|
|
||||||
}
|
|
||||||
// De-crement by one the last column value.
|
|
||||||
toColumn--;
|
|
||||||
// Highly unlikely that this will be true but, if the width of a series
|
|
||||||
// of columns is exactly equal to the required width of the image, then
|
|
||||||
// simply build a ClientAnchorDetail object with an inset equal to the
|
|
||||||
// total number of co-ordinate positions available in a column, a
|
|
||||||
// from column co-ordinate (top left hand corner) equal to the value
|
|
||||||
// of the startingColumn parameter and a to column co-ordinate equal
|
|
||||||
// to the toColumn variable.
|
|
||||||
//
|
|
||||||
// Convert both values to ints to perform the test.
|
|
||||||
if((int)totalWidthMM == (int)reqImageWidthMM) {
|
|
||||||
// A problem could occur if the image is sized to fit into one or
|
|
||||||
// more columns. If that occurs, the value in the toColumn variable
|
|
||||||
// will be in error. To overcome this, there are two options, to
|
|
||||||
// ibcrement the toColumn variable's value by one or to pass the
|
|
||||||
// total number of co-ordinate positions to the third paramater
|
|
||||||
// of the ClientAnchorDetail constructor. For no sepcific reason,
|
|
||||||
// the latter option is used below.
|
|
||||||
anchorDetail = new ClientAnchorDetail(startingColumn,
|
|
||||||
toColumn, ConvertImageUnits.TOTAL_COLUMN_COORDINATE_POSITIONS);
|
|
||||||
}
|
|
||||||
// In this case, the image will overlap part of another column and it is
|
|
||||||
// necessary to calculate just how much - this will become the inset
|
|
||||||
// for the ClientAnchorDetail object.
|
|
||||||
else {
|
|
||||||
// Firstly, claculate how much of the image should overlap into
|
|
||||||
// the next column.
|
|
||||||
overlapMM = reqImageWidthMM - (totalWidthMM - colWidthMM);
|
|
||||||
|
|
||||||
// When the required size is very close indded to the column size,
|
|
||||||
// the calcaulation above can produce a negative value. To prevent
|
|
||||||
// problems occuring in later caculations, this is simply removed
|
|
||||||
// be setting the overlapMM value to zero.
|
|
||||||
if(overlapMM < 0) {
|
|
||||||
overlapMM = 0.0D;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next, from the columns width, calculate how many co-ordinate
|
|
||||||
// positons there are per millimetre
|
|
||||||
coordinatePositionsPerMM = colWidthMM == 0 ? 0
|
|
||||||
: ConvertImageUnits.TOTAL_COLUMN_COORDINATE_POSITIONS / colWidthMM;
|
|
||||||
// From this figure, determine how many co-ordinat positions to
|
|
||||||
// inset the left hand or bottom edge of the image.
|
|
||||||
inset = (int)(coordinatePositionsPerMM * overlapMM);
|
|
||||||
|
|
||||||
// Now create the ClientAnchorDetail object, setting the from and to
|
|
||||||
// columns and the inset.
|
|
||||||
anchorDetail = new ClientAnchorDetail(startingColumn, toColumn, inset);
|
|
||||||
}
|
|
||||||
return(anchorDetail);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If the image is to overlie more than one rows, calculations need to be
|
|
||||||
* performed to determine how many rows and whether the image will
|
|
||||||
* overlie just a part of one row in order to be presented at the
|
|
||||||
* required size.
|
|
||||||
*
|
|
||||||
* @param sheet The sheet that will 'contain' the image.
|
|
||||||
* @param startingRow A primitive int whose value is the index of the row
|
|
||||||
* that contains the cell whose top left hand corner
|
|
||||||
* should be aligned with the top left hand corner of
|
|
||||||
* the image.
|
|
||||||
* @param reqImageHeightMM A primitive double whose value will indicate the
|
|
||||||
* required height of the image in millimetres.
|
|
||||||
* @return An instance of the ClientAnchorDetail class that will contain
|
|
||||||
* the index number of the row containing the cell whose top
|
|
||||||
* left hand corner also defines the top left hand corner of the
|
|
||||||
* image, the index number of the row containing the cell whose top
|
|
||||||
* left hand corner also defines the bottom right hand corner of
|
|
||||||
* the image and an inset that determines how far the bottom edge
|
|
||||||
* can protrude into the next (lower) row - expressed as a specific
|
|
||||||
* number of co-ordinate positions.
|
|
||||||
*/
|
|
||||||
private ClientAnchorDetail calculateRowLocation(HSSFSheet sheet,
|
|
||||||
int startingRow, double reqImageHeightMM) {
|
|
||||||
ClientAnchorDetail clientAnchorDetail;
|
|
||||||
HSSFRow row;
|
|
||||||
double rowHeightMM = 0.0D;
|
|
||||||
double totalRowHeightMM = 0.0D;
|
|
||||||
double overlapMM;
|
|
||||||
double rowCoordinatesPerMM;
|
|
||||||
int toRow = startingRow;
|
|
||||||
int inset;
|
|
||||||
|
|
||||||
// Step through the rows in the sheet and accumulate a total of their
|
|
||||||
// heights.
|
|
||||||
while(totalRowHeightMM < reqImageHeightMM) {
|
|
||||||
row = sheet.getRow(toRow);
|
|
||||||
// Note, if the row does not already exist on the sheet then create
|
|
||||||
// it here.
|
|
||||||
if(row == null) {
|
|
||||||
row = sheet.createRow(toRow);
|
|
||||||
}
|
|
||||||
// Get the row's height in millimetres and add to the running total.
|
|
||||||
rowHeightMM = row.getHeightInPoints() / ConvertImageUnits.POINTS_PER_MILLIMETRE;
|
|
||||||
totalRowHeightMM += rowHeightMM;
|
|
||||||
toRow++;
|
|
||||||
}
|
|
||||||
// Owing to the way the loop above works, the rowNumber will have been
|
|
||||||
// incremented one row too far. Undo that here.
|
|
||||||
toRow--;
|
|
||||||
// Check to see whether the image should occupy an exact number of
|
|
||||||
// rows. If so, build the ClientAnchorDetail record to point
|
|
||||||
// to those rows and with an inset of the total number of co-ordinate
|
|
||||||
// position in the row.
|
|
||||||
//
|
|
||||||
// To overcome problems that can occur with comparing double values for
|
|
||||||
// equality, cast both to int(s) to truncate the value; VERY crude and
|
|
||||||
// I do not really like it!!
|
|
||||||
if((int)totalRowHeightMM == (int)reqImageHeightMM) {
|
|
||||||
clientAnchorDetail = new ClientAnchorDetail(startingRow, toRow,
|
|
||||||
ConvertImageUnits.TOTAL_ROW_COORDINATE_POSITIONS);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Calculate how far the image will project into the next row. Note
|
|
||||||
// that the height of the last row assessed is subtracted from the
|
|
||||||
// total height of all rows assessed so far.
|
|
||||||
overlapMM = reqImageHeightMM - (totalRowHeightMM - rowHeightMM);
|
|
||||||
|
|
||||||
// To prevent an exception being thrown when the required width of
|
|
||||||
// the image is very close indeed to the column size.
|
|
||||||
if(overlapMM < 0) {
|
|
||||||
overlapMM = 0.0D;
|
|
||||||
}
|
|
||||||
|
|
||||||
rowCoordinatesPerMM = rowHeightMM == 0 ? 0
|
|
||||||
: ConvertImageUnits.TOTAL_ROW_COORDINATE_POSITIONS / rowHeightMM;
|
|
||||||
inset = (int)(overlapMM * rowCoordinatesPerMM);
|
|
||||||
clientAnchorDetail = new ClientAnchorDetail(startingRow, toRow, inset);
|
|
||||||
}
|
|
||||||
return(clientAnchorDetail);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads - reads in and converts into an array of byte(s) - an image from
|
|
||||||
* a named file.
|
|
||||||
*
|
|
||||||
* Note: this method should be modified so that the type of the image may
|
|
||||||
* also be passed to it. Currently, it assumes that all images are
|
|
||||||
* JPG/JPEG(s).
|
|
||||||
*
|
|
||||||
* @param imageFilename A String that encapsulates the path to and name
|
|
||||||
* of the file that contains the image which is to be
|
|
||||||
* 'loaded'.
|
|
||||||
* @return An array of type byte that contains the raw data of the named
|
|
||||||
* image.
|
|
||||||
* @throws java.io.FileNotFoundException Thrown if it was not possible to
|
|
||||||
* open the specified file.
|
|
||||||
* @throws java.io.IOException Thrown if reading the file failed or was
|
|
||||||
* interrupted.
|
|
||||||
*/
|
|
||||||
private byte[] imageToBytes(String imageFilename) throws IOException {
|
|
||||||
File imageFile = new File(imageFilename);
|
|
||||||
try (FileInputStream fis = new FileInputStream(imageFile)) {
|
|
||||||
return IOUtils.toByteArray(fis);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The main entry point to the program. It contains code that demonstrates
|
|
||||||
* one way to use the program.
|
|
||||||
*
|
|
||||||
* Note, the code is not restricted to use on new workbooks only. If an
|
|
||||||
* image is to be inserted into an existing workbook. just open that
|
|
||||||
* workbook, gat a reference to a sheet and pass that;
|
|
||||||
*
|
|
||||||
* AddDimensionedImage addImage = new AddDimensionedImage();
|
|
||||||
*
|
|
||||||
* File file = new File("....... Existing Workbook .......");
|
|
||||||
* FileInputStream fis = new FileInputStream(file);
|
|
||||||
* HSSFWorkbook workbook = new HSSFWorkbook(fis);
|
|
||||||
* HSSFSheet sheet = workbook.getSheetAt(0);
|
|
||||||
* addImage.addImageToSheet("C3", sheet, "image.jpg", 30, 20,
|
|
||||||
* AddDimensionedImage.EXPAND.ROW);
|
|
||||||
*
|
|
||||||
* @param args the command line arguments
|
|
||||||
*/
|
|
||||||
public static void main(String[] args) throws IOException {
|
|
||||||
if(args.length < 2){
|
|
||||||
System.err.println("Usage: AddDimensionedImage imageFile outputFile");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String imageFile = args[0];
|
|
||||||
String outputFile = args[1];
|
|
||||||
|
|
||||||
try (HSSFWorkbook workbook = new HSSFWorkbook()) {
|
|
||||||
HSSFSheet sheet = workbook.createSheet("Picture Test");
|
|
||||||
new AddDimensionedImage().addImageToSheet("A1", sheet,
|
|
||||||
imageFile, 125, 125,
|
|
||||||
AddDimensionedImage.EXPAND_ROW_AND_COLUMN);
|
|
||||||
try (FileOutputStream fos = new FileOutputStream(outputFile)) {
|
|
||||||
workbook.write(fos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The HSSFClientAnchor class accepts eight parameters. In order, these are;
|
|
||||||
*
|
|
||||||
* * How far the left hand edge of the image is inset from the left hand
|
|
||||||
* edge of the cell
|
|
||||||
* * How far the top edge of the image is inset from the top of the cell
|
|
||||||
* * How far the right hand edge of the image is inset from the left
|
|
||||||
* hand edge of the cell
|
|
||||||
* * How far the bottom edge of the image is inset from the top of the
|
|
||||||
* cell.
|
|
||||||
* * Together, parameters five and six determine the column and row
|
|
||||||
* co-ordinates of the cell whose top left hand corner will be aligned
|
|
||||||
* with the image's top left hand corner.
|
|
||||||
* * Together, parameter seven and eight determine the column and row
|
|
||||||
* co-ordinates of the cell whose top left hand corner will be aligned
|
|
||||||
* with the images bottom right hand corner.
|
|
||||||
*
|
|
||||||
* An instance of the ClientAnchorDetail class provides three of the eight
|
|
||||||
* parameters, one of the co-ordinates for the images top left hand corner,
|
|
||||||
* one of the co-ordinates for the images bottom right hand corner and
|
|
||||||
* either how far the image should be inset from the top or the left hand
|
|
||||||
* edge of the cell.
|
|
||||||
*
|
|
||||||
* @author Mark Beardsley [mas at apache.org]
|
|
||||||
* @version 1.00 5th August 2009.
|
|
||||||
*/
|
|
||||||
public static class ClientAnchorDetail {
|
|
||||||
|
|
||||||
private int fromIndex;
|
|
||||||
private int toIndex;
|
|
||||||
private int inset;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new instance of the ClientAnchorDetail class using the
|
|
||||||
* following parameters.
|
|
||||||
*
|
|
||||||
* @param fromIndex A primitive int that contains one of the
|
|
||||||
* co-ordinates (row or column index) for the top left
|
|
||||||
* hand corner of the image.
|
|
||||||
* @param toIndex A primitive int that contains one of the
|
|
||||||
* co-ordinates (row or column index) for the bottom
|
|
||||||
* right hand corner of the image.
|
|
||||||
* @param inset A primitive int that contains a value which indicates
|
|
||||||
* how far the image should be inset from the top or the
|
|
||||||
* left hand edge of a cell.
|
|
||||||
*/
|
|
||||||
public ClientAnchorDetail(int fromIndex, int toIndex, int inset) {
|
|
||||||
this.fromIndex = fromIndex;
|
|
||||||
this.toIndex = toIndex;
|
|
||||||
this.inset = inset;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get one of the number of the column or row that contains the cell
|
|
||||||
* whose top left hand corner will be aligned with the top left hand
|
|
||||||
* corner of the image.
|
|
||||||
*
|
|
||||||
* @return The value - row or column index - for one of the co-ordinates
|
|
||||||
* of the top left hand corner of the image.
|
|
||||||
*/
|
|
||||||
public int getFromIndex() {
|
|
||||||
return(this.fromIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get one of the number of the column or row that contains the cell
|
|
||||||
* whose top left hand corner will be aligned with the bottom righ hand
|
|
||||||
* corner of the image.
|
|
||||||
*
|
|
||||||
* @return The value - row or column index - for one of the co-ordinates
|
|
||||||
* of the bottom right hand corner of the image.
|
|
||||||
*/
|
|
||||||
public int getToIndex() {
|
|
||||||
return(this.toIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the image's offset from the edge of a cell.
|
|
||||||
*
|
|
||||||
* @return How far either the right hand or bottom edge of the image is
|
|
||||||
* inset from the left hand or top edge of a cell.
|
|
||||||
*/
|
|
||||||
public int getInset() {
|
|
||||||
return(this.inset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility methods used to convert Excel's character based column and row
|
|
||||||
* size measurements into pixels and/or millimetres. The class also contains
|
|
||||||
* various constants that are required in other calculations.
|
|
||||||
*
|
|
||||||
* @author xio[darjino@hotmail.com]
|
|
||||||
* @version 1.01 30th July 2009.
|
|
||||||
* Added by Mark Beardsley [msb at apache.org].
|
|
||||||
* Additional constants.
|
|
||||||
* widthUnits2Millimetres() and millimetres2Units() methods.
|
|
||||||
*/
|
|
||||||
private static final class ConvertImageUnits {
|
|
||||||
|
|
||||||
// Each cell conatins a fixed number of co-ordinate points; this number
|
|
||||||
// does not vary with row height or column width or with font. These two
|
|
||||||
// constants are defined below.
|
|
||||||
public static final int TOTAL_COLUMN_COORDINATE_POSITIONS = 1023; // MB
|
|
||||||
public static final int TOTAL_ROW_COORDINATE_POSITIONS = 255; // MB
|
|
||||||
// Cnstants that defines how many pixels and points there are in a
|
|
||||||
// millimetre. These values are required for the conversion algorithm.
|
|
||||||
public static final double PIXELS_PER_MILLIMETRES = 3.78; // MB
|
|
||||||
public static final double POINTS_PER_MILLIMETRE = 2.83; // MB
|
|
||||||
// The column width returned by HSSF and the width of a picture when
|
|
||||||
// positioned to exactly cover one cell are different by almost exactly
|
|
||||||
// 2mm - give or take rounding errors. This constant allows that
|
|
||||||
// additional amount to be accounted for when calculating how many
|
|
||||||
// celles the image ought to overlie.
|
|
||||||
public static final double CELL_BORDER_WIDTH_MILLIMETRES = 2.0D; // MB
|
|
||||||
public static final short EXCEL_COLUMN_WIDTH_FACTOR = 256;
|
|
||||||
public static final int UNIT_OFFSET_LENGTH = 7;
|
|
||||||
private static final int[] UNIT_OFFSET_MAP = new int[]
|
|
||||||
{ 0, 36, 73, 109, 146, 182, 219 };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* pixel units to excel width units(units of 1/256th of a character width)
|
|
||||||
*/
|
|
||||||
public static short pixel2WidthUnits(int pxs) {
|
|
||||||
short widthUnits = (short) (EXCEL_COLUMN_WIDTH_FACTOR *
|
|
||||||
(pxs / UNIT_OFFSET_LENGTH));
|
|
||||||
widthUnits += UNIT_OFFSET_MAP[(pxs % UNIT_OFFSET_LENGTH)];
|
|
||||||
return widthUnits;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* excel width units(units of 1/256th of a character width) to pixel
|
|
||||||
* units.
|
|
||||||
*/
|
|
||||||
public static int widthUnits2Pixel(short widthUnits) {
|
|
||||||
int pixels = (widthUnits / EXCEL_COLUMN_WIDTH_FACTOR)
|
|
||||||
* UNIT_OFFSET_LENGTH;
|
|
||||||
int offsetWidthUnits = widthUnits % EXCEL_COLUMN_WIDTH_FACTOR;
|
|
||||||
pixels += Math.round(offsetWidthUnits /
|
|
||||||
((float) EXCEL_COLUMN_WIDTH_FACTOR / UNIT_OFFSET_LENGTH));
|
|
||||||
return pixels;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert Excel's width units into millimetres.
|
|
||||||
*
|
|
||||||
* @param widthUnits The width of the column or the height of the
|
|
||||||
* row in Excel's units.
|
|
||||||
* @return A primitive double that contains the columns width or rows
|
|
||||||
* height in millimetres.
|
|
||||||
*/
|
|
||||||
public static double widthUnits2Millimetres(short widthUnits) {
|
|
||||||
return(ConvertImageUnits.widthUnits2Pixel(widthUnits) /
|
|
||||||
ConvertImageUnits.PIXELS_PER_MILLIMETRES);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert into millimetres Excel's width units..
|
|
||||||
*
|
|
||||||
* @param millimetres A primitive double that contains the columns
|
|
||||||
* width or rows height in millimetres.
|
|
||||||
* @return A primitive int that contains the columns width or rows
|
|
||||||
* height in Excel's units.
|
|
||||||
*/
|
|
||||||
public static int millimetres2WidthUnits(double millimetres) {
|
|
||||||
return(ConvertImageUnits.pixel2WidthUnits((int)(millimetres *
|
|
||||||
ConvertImageUnits.PIXELS_PER_MILLIMETRES)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -96,7 +96,6 @@ public class BigExample {
|
|||||||
r.setHeight((short) 0x249);
|
r.setHeight((short) 0x249);
|
||||||
}
|
}
|
||||||
|
|
||||||
//r.setRowNum(( short ) rownum);
|
|
||||||
// create 50 cells (0-49) (the += 2 becomes apparent later
|
// create 50 cells (0-49) (the += 2 becomes apparent later
|
||||||
for (int cellnum = 0; cellnum < 50; cellnum += 2) {
|
for (int cellnum = 0; cellnum < 50; cellnum += 2) {
|
||||||
// create a numeric cell
|
// create a numeric cell
|
||||||
|
@ -30,7 +30,10 @@ import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
|||||||
/**
|
/**
|
||||||
* Demonstrates how you can extract embedded data from a .xls file
|
* Demonstrates how you can extract embedded data from a .xls file
|
||||||
*/
|
*/
|
||||||
public class EmbeddedObjects {
|
@SuppressWarnings({"java:S106","java:S4823"})
|
||||||
|
public final class EmbeddedObjects {
|
||||||
|
private EmbeddedObjects() {}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
try (
|
try (
|
||||||
@ -43,23 +46,28 @@ public class EmbeddedObjects {
|
|||||||
String oleName = obj.getOLE2ClassName();
|
String oleName = obj.getOLE2ClassName();
|
||||||
DirectoryNode dn = (obj.hasDirectoryEntry()) ? (DirectoryNode) obj.getDirectory() : null;
|
DirectoryNode dn = (obj.hasDirectoryEntry()) ? (DirectoryNode) obj.getDirectory() : null;
|
||||||
Closeable document = null;
|
Closeable document = null;
|
||||||
if (oleName.equals("Worksheet")) {
|
switch (oleName) {
|
||||||
document = new HSSFWorkbook(dn, fs, false);
|
case "Worksheet":
|
||||||
} else if (oleName.equals("Document")) {
|
document = new HSSFWorkbook(dn, fs, false);
|
||||||
document = new HWPFDocument(dn);
|
break;
|
||||||
} else if (oleName.equals("Presentation")) {
|
case "Document":
|
||||||
document = new HSLFSlideShow(dn);
|
document = new HWPFDocument(dn);
|
||||||
} else {
|
break;
|
||||||
if (dn != null) {
|
case "Presentation":
|
||||||
// The DirectoryEntry is a DocumentNode. Examine its entries to find out what it is
|
document = new HSLFSlideShow(dn);
|
||||||
for (Entry entry : dn) {
|
break;
|
||||||
String name = entry.getName();
|
default:
|
||||||
|
if (dn != null) {
|
||||||
|
// The DirectoryEntry is a DocumentNode. Examine its entries to find out what it is
|
||||||
|
for (Entry entry : dn) {
|
||||||
|
String name = entry.getName();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// There is no DirectoryEntry
|
||||||
|
// Recover the object's data from the HSSFObjectData instance.
|
||||||
|
byte[] objectData = obj.getObjectData();
|
||||||
}
|
}
|
||||||
} else {
|
break;
|
||||||
// There is no DirectoryEntry
|
|
||||||
// Recover the object's data from the HSSFObjectData instance.
|
|
||||||
byte[] objectData = obj.getObjectData();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (document != null) {
|
if (document != null) {
|
||||||
document.close();
|
document.close();
|
||||||
|
@ -15,22 +15,28 @@
|
|||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
==================================================================== */
|
==================================================================== */
|
||||||
|
|
||||||
package org.apache.poi.hssf.usermodel.examples;
|
|
||||||
|
|
||||||
import org.apache.poi.hssf.eventusermodel.HSSFEventFactory;
|
package org.apache.poi.hssf.usermodel.examples;
|
||||||
import org.apache.poi.hssf.eventusermodel.HSSFListener;
|
|
||||||
import org.apache.poi.hssf.eventusermodel.HSSFRequest;
|
|
||||||
import org.apache.poi.hssf.record.*;
|
|
||||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
|
||||||
|
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import org.apache.poi.hssf.eventusermodel.HSSFEventFactory;
|
||||||
|
import org.apache.poi.hssf.eventusermodel.HSSFListener;
|
||||||
|
import org.apache.poi.hssf.eventusermodel.HSSFRequest;
|
||||||
|
import org.apache.poi.hssf.record.BOFRecord;
|
||||||
|
import org.apache.poi.hssf.record.BoundSheetRecord;
|
||||||
|
import org.apache.poi.hssf.record.LabelSSTRecord;
|
||||||
|
import org.apache.poi.hssf.record.NumberRecord;
|
||||||
|
import org.apache.poi.hssf.record.RowRecord;
|
||||||
|
import org.apache.poi.hssf.record.SSTRecord;
|
||||||
|
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This example shows how to use the event API for reading a file.
|
* This example shows how to use the event API for reading a file.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings({"java:S106","java:S4823"})
|
||||||
public class EventExample implements HSSFListener {
|
public class EventExample implements HSSFListener {
|
||||||
private SSTRecord sstrec;
|
private SSTRecord sstrec;
|
||||||
|
|
||||||
|
@ -40,8 +40,11 @@ import org.apache.poi.ss.util.CellRangeAddress;
|
|||||||
* It does contain sample API usage that may be educational to regular API
|
* It does contain sample API usage that may be educational to regular API
|
||||||
* users.
|
* users.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings({"java:S106","java:S4823"})
|
||||||
public final class HSSFReadWrite {
|
public final class HSSFReadWrite {
|
||||||
|
|
||||||
|
private HSSFReadWrite() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* creates an {@link HSSFWorkbook} with the specified OS filename.
|
* creates an {@link HSSFWorkbook} with the specified OS filename.
|
||||||
*/
|
*/
|
||||||
|
@ -42,11 +42,11 @@ public class Hyperlinks {
|
|||||||
|
|
||||||
//cell style for hyperlinks
|
//cell style for hyperlinks
|
||||||
//by default hyperlinks are blue and underlined
|
//by default hyperlinks are blue and underlined
|
||||||
HSSFCellStyle hlink_style = wb.createCellStyle();
|
HSSFCellStyle hlinkStyle = wb.createCellStyle();
|
||||||
HSSFFont hlink_font = wb.createFont();
|
HSSFFont hlinkFont = wb.createFont();
|
||||||
hlink_font.setUnderline(Font.U_SINGLE);
|
hlinkFont.setUnderline(Font.U_SINGLE);
|
||||||
hlink_font.setColor(HSSFColorPredefined.BLUE.getIndex());
|
hlinkFont.setColor(HSSFColorPredefined.BLUE.getIndex());
|
||||||
hlink_style.setFont(hlink_font);
|
hlinkStyle.setFont(hlinkFont);
|
||||||
|
|
||||||
HSSFCell cell;
|
HSSFCell cell;
|
||||||
HSSFSheet sheet = wb.createSheet("Hyperlinks");
|
HSSFSheet sheet = wb.createSheet("Hyperlinks");
|
||||||
@ -57,7 +57,7 @@ public class Hyperlinks {
|
|||||||
HSSFHyperlink link = helper.createHyperlink(HyperlinkType.URL);
|
HSSFHyperlink link = helper.createHyperlink(HyperlinkType.URL);
|
||||||
link.setAddress("https://poi.apache.org/");
|
link.setAddress("https://poi.apache.org/");
|
||||||
cell.setHyperlink(link);
|
cell.setHyperlink(link);
|
||||||
cell.setCellStyle(hlink_style);
|
cell.setCellStyle(hlinkStyle);
|
||||||
|
|
||||||
//link to a file in the current directory
|
//link to a file in the current directory
|
||||||
cell = sheet.createRow(1).createCell(0);
|
cell = sheet.createRow(1).createCell(0);
|
||||||
@ -65,7 +65,7 @@ public class Hyperlinks {
|
|||||||
link = helper.createHyperlink(HyperlinkType.FILE);
|
link = helper.createHyperlink(HyperlinkType.FILE);
|
||||||
link.setAddress("link1.xls");
|
link.setAddress("link1.xls");
|
||||||
cell.setHyperlink(link);
|
cell.setHyperlink(link);
|
||||||
cell.setCellStyle(hlink_style);
|
cell.setCellStyle(hlinkStyle);
|
||||||
|
|
||||||
//e-mail link
|
//e-mail link
|
||||||
cell = sheet.createRow(2).createCell(0);
|
cell = sheet.createRow(2).createCell(0);
|
||||||
@ -74,7 +74,7 @@ public class Hyperlinks {
|
|||||||
//note, if subject contains white spaces, make sure they are url-encoded
|
//note, if subject contains white spaces, make sure they are url-encoded
|
||||||
link.setAddress("mailto:poi@apache.org?subject=Hyperlinks");
|
link.setAddress("mailto:poi@apache.org?subject=Hyperlinks");
|
||||||
cell.setHyperlink(link);
|
cell.setHyperlink(link);
|
||||||
cell.setCellStyle(hlink_style);
|
cell.setCellStyle(hlinkStyle);
|
||||||
|
|
||||||
//link to a place in this workbook
|
//link to a place in this workbook
|
||||||
|
|
||||||
@ -87,7 +87,7 @@ public class Hyperlinks {
|
|||||||
link = helper.createHyperlink(HyperlinkType.DOCUMENT);
|
link = helper.createHyperlink(HyperlinkType.DOCUMENT);
|
||||||
link.setAddress("'Target Sheet'!A1");
|
link.setAddress("'Target Sheet'!A1");
|
||||||
cell.setHyperlink(link);
|
cell.setHyperlink(link);
|
||||||
cell.setCellStyle(hlink_style);
|
cell.setCellStyle(hlinkStyle);
|
||||||
|
|
||||||
try (FileOutputStream out = new FileOutputStream("hssf-links.xls")) {
|
try (FileOutputStream out = new FileOutputStream("hssf-links.xls")) {
|
||||||
wb.write(out);
|
wb.write(out);
|
||||||
|
@ -22,14 +22,15 @@ import java.io.File;
|
|||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
|
||||||
import org.apache.poi.hssf.usermodel.HSSFSheet;
|
|
||||||
import org.apache.poi.hssf.usermodel.HSSFRow;
|
|
||||||
import org.apache.poi.hssf.usermodel.HSSFCell;
|
import org.apache.poi.hssf.usermodel.HSSFCell;
|
||||||
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
|
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
|
||||||
import org.apache.poi.hssf.usermodel.HSSFDataFormat;
|
import org.apache.poi.hssf.usermodel.HSSFDataFormat;
|
||||||
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
|
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
|
||||||
|
import org.apache.poi.hssf.usermodel.HSSFRow;
|
||||||
|
import org.apache.poi.hssf.usermodel.HSSFSheet;
|
||||||
|
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class contains code that demonstrates how to insert plain, numbered
|
* This class contains code that demonstrates how to insert plain, numbered
|
||||||
@ -48,6 +49,7 @@ import org.apache.poi.hssf.usermodel.HSSFRichTextString;
|
|||||||
*
|
*
|
||||||
* @author Mark Beardsley [msb at apache.org]
|
* @author Mark Beardsley [msb at apache.org]
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings({"java:S106","java:S4823"})
|
||||||
public class InCellLists {
|
public class InCellLists {
|
||||||
|
|
||||||
// This character looks like a solid, black, loser case letter 'o'
|
// This character looks like a solid, black, loser case letter 'o'
|
||||||
@ -79,7 +81,7 @@ public class InCellLists {
|
|||||||
// whose items are neither bulleted or numbered - into that cell.
|
// whose items are neither bulleted or numbered - into that cell.
|
||||||
row = sheet.createRow(1);
|
row = sheet.createRow(1);
|
||||||
cell = row.createCell(0);
|
cell = row.createCell(0);
|
||||||
ArrayList<String> listItems = new ArrayList<>();
|
List<String> listItems = new ArrayList<>();
|
||||||
listItems.add("List Item One.");
|
listItems.add("List Item One.");
|
||||||
listItems.add("List Item Two.");
|
listItems.add("List Item Two.");
|
||||||
listItems.add("List Item Three.");
|
listItems.add("List Item Three.");
|
||||||
@ -123,7 +125,7 @@ public class InCellLists {
|
|||||||
// to preserve order.
|
// to preserve order.
|
||||||
row = sheet.createRow(4);
|
row = sheet.createRow(4);
|
||||||
cell = row.createCell(0);
|
cell = row.createCell(0);
|
||||||
ArrayList<MultiLevelListItem> multiLevelListItems = new ArrayList<>();
|
List<MultiLevelListItem> multiLevelListItems = new ArrayList<>();
|
||||||
listItems = new ArrayList<>();
|
listItems = new ArrayList<>();
|
||||||
listItems.add("ML List Item One - Sub Item One.");
|
listItems.add("ML List Item One - Sub Item One.");
|
||||||
listItems.add("ML List Item One - Sub Item Two.");
|
listItems.add("ML List Item One - Sub Item Two.");
|
||||||
@ -212,7 +214,7 @@ public class InCellLists {
|
|||||||
* reference to the spreadsheet cell into which the list
|
* reference to the spreadsheet cell into which the list
|
||||||
* will be written.
|
* will be written.
|
||||||
*/
|
*/
|
||||||
public void listInCell(HSSFWorkbook workbook, ArrayList<String> listItems, HSSFCell cell) {
|
public void listInCell(HSSFWorkbook workbook, List<String> listItems, HSSFCell cell) {
|
||||||
StringBuilder buffer = new StringBuilder();
|
StringBuilder buffer = new StringBuilder();
|
||||||
HSSFCellStyle wrapStyle = workbook.createCellStyle();
|
HSSFCellStyle wrapStyle = workbook.createCellStyle();
|
||||||
wrapStyle.setWrapText(true);
|
wrapStyle.setWrapText(true);
|
||||||
@ -242,7 +244,7 @@ public class InCellLists {
|
|||||||
* to calculate subsequent item numbers.
|
* to calculate subsequent item numbers.
|
||||||
*/
|
*/
|
||||||
public void numberedListInCell(HSSFWorkbook workbook,
|
public void numberedListInCell(HSSFWorkbook workbook,
|
||||||
ArrayList<String> listItems,
|
List<String> listItems,
|
||||||
HSSFCell cell,
|
HSSFCell cell,
|
||||||
int startingValue,
|
int startingValue,
|
||||||
int increment) {
|
int increment) {
|
||||||
@ -278,7 +280,7 @@ public class InCellLists {
|
|||||||
* will be written.
|
* will be written.
|
||||||
*/
|
*/
|
||||||
public void bulletedListInCell(HSSFWorkbook workbook,
|
public void bulletedListInCell(HSSFWorkbook workbook,
|
||||||
ArrayList<String> listItems,
|
List<String> listItems,
|
||||||
HSSFCell cell) {
|
HSSFCell cell) {
|
||||||
StringBuilder buffer = new StringBuilder();
|
StringBuilder buffer = new StringBuilder();
|
||||||
// Note that again, an HSSFCellStye object is required and that
|
// Note that again, an HSSFCellStye object is required and that
|
||||||
@ -314,7 +316,7 @@ public class InCellLists {
|
|||||||
* will be written.
|
* will be written.
|
||||||
*/
|
*/
|
||||||
public void multiLevelListInCell(HSSFWorkbook workbook,
|
public void multiLevelListInCell(HSSFWorkbook workbook,
|
||||||
ArrayList<MultiLevelListItem> multiLevelListItems,
|
List<MultiLevelListItem> multiLevelListItems,
|
||||||
HSSFCell cell) {
|
HSSFCell cell) {
|
||||||
StringBuilder buffer = new StringBuilder();
|
StringBuilder buffer = new StringBuilder();
|
||||||
// Note that again, an HSSFCellStye object is required and that
|
// Note that again, an HSSFCellStye object is required and that
|
||||||
@ -329,13 +331,14 @@ public class InCellLists {
|
|||||||
buffer.append("\n");
|
buffer.append("\n");
|
||||||
// and then an ArrayList whose elements encapsulate the text
|
// and then an ArrayList whose elements encapsulate the text
|
||||||
// for the lower level list items.
|
// for the lower level list items.
|
||||||
ArrayList<String> lowerLevelItems = multiLevelListItem.getLowerLevelItems();
|
List<String> lowerLevelItems = multiLevelListItem.getLowerLevelItems();
|
||||||
if(!(lowerLevelItems == null) && !(lowerLevelItems.isEmpty())) {
|
if (lowerLevelItems == null || lowerLevelItems.isEmpty()) {
|
||||||
for(String item : lowerLevelItems) {
|
continue;
|
||||||
buffer.append(InCellLists.TAB);
|
}
|
||||||
buffer.append(item);
|
for(String item : lowerLevelItems) {
|
||||||
buffer.append("\n");
|
buffer.append(InCellLists.TAB);
|
||||||
}
|
buffer.append(item);
|
||||||
|
buffer.append("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// The StringBuilder's contents are the source for the contents
|
// The StringBuilder's contents are the source for the contents
|
||||||
@ -371,7 +374,7 @@ public class InCellLists {
|
|||||||
* subsequent low level item.
|
* subsequent low level item.
|
||||||
*/
|
*/
|
||||||
public void multiLevelNumberedListInCell(HSSFWorkbook workbook,
|
public void multiLevelNumberedListInCell(HSSFWorkbook workbook,
|
||||||
ArrayList<MultiLevelListItem> multiLevelListItems,
|
List<MultiLevelListItem> multiLevelListItems,
|
||||||
HSSFCell cell,
|
HSSFCell cell,
|
||||||
int highLevelStartingValue,
|
int highLevelStartingValue,
|
||||||
int highLevelIncrement,
|
int highLevelIncrement,
|
||||||
@ -393,8 +396,8 @@ public class InCellLists {
|
|||||||
buffer.append("\n");
|
buffer.append("\n");
|
||||||
// and then an ArrayList whose elements encapsulate the text
|
// and then an ArrayList whose elements encapsulate the text
|
||||||
// for the lower level list items.
|
// for the lower level list items.
|
||||||
ArrayList<String> lowerLevelItems = multiLevelListItem.getLowerLevelItems();
|
List<String> lowerLevelItems = multiLevelListItem.getLowerLevelItems();
|
||||||
if(!(lowerLevelItems == null) && !(lowerLevelItems.isEmpty())) {
|
if(lowerLevelItems != null && !lowerLevelItems.isEmpty()) {
|
||||||
int lowLevelItemNumber = lowLevelStartingValue;
|
int lowLevelItemNumber = lowLevelStartingValue;
|
||||||
for(String item : lowerLevelItems) {
|
for(String item : lowerLevelItems) {
|
||||||
buffer.append(InCellLists.TAB);
|
buffer.append(InCellLists.TAB);
|
||||||
@ -431,7 +434,7 @@ public class InCellLists {
|
|||||||
* will be written.
|
* will be written.
|
||||||
*/
|
*/
|
||||||
public void multiLevelBulletedListInCell(HSSFWorkbook workbook,
|
public void multiLevelBulletedListInCell(HSSFWorkbook workbook,
|
||||||
ArrayList<MultiLevelListItem> multiLevelListItems,
|
List<MultiLevelListItem> multiLevelListItems,
|
||||||
HSSFCell cell) {
|
HSSFCell cell) {
|
||||||
StringBuilder buffer = new StringBuilder();
|
StringBuilder buffer = new StringBuilder();
|
||||||
// Note that again, an HSSFCellStye object is required and that
|
// Note that again, an HSSFCellStye object is required and that
|
||||||
@ -448,8 +451,8 @@ public class InCellLists {
|
|||||||
buffer.append("\n");
|
buffer.append("\n");
|
||||||
// and then an ArrayList whose elements encapsulate the text
|
// and then an ArrayList whose elements encapsulate the text
|
||||||
// for the lower level list items.
|
// for the lower level list items.
|
||||||
ArrayList<String> lowerLevelItems = multiLevelListItem.getLowerLevelItems();
|
List<String> lowerLevelItems = multiLevelListItem.getLowerLevelItems();
|
||||||
if(!(lowerLevelItems == null) && !(lowerLevelItems.isEmpty())) {
|
if(lowerLevelItems != null && !lowerLevelItems.isEmpty()) {
|
||||||
for(String item : lowerLevelItems) {
|
for(String item : lowerLevelItems) {
|
||||||
buffer.append(InCellLists.TAB);
|
buffer.append(InCellLists.TAB);
|
||||||
buffer.append(InCellLists.BULLET_CHARACTER);
|
buffer.append(InCellLists.BULLET_CHARACTER);
|
||||||
@ -498,7 +501,7 @@ public class InCellLists {
|
|||||||
public final class MultiLevelListItem {
|
public final class MultiLevelListItem {
|
||||||
|
|
||||||
private String itemText;
|
private String itemText;
|
||||||
private ArrayList<String> lowerLevelItems;
|
private List<String> lowerLevelItems;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new instance of the MultiLevelListItem class using the
|
* Create a new instance of the MultiLevelListItem class using the
|
||||||
@ -510,7 +513,7 @@ public class InCellLists {
|
|||||||
* text for the associated lower level list
|
* text for the associated lower level list
|
||||||
* items.
|
* items.
|
||||||
*/
|
*/
|
||||||
public MultiLevelListItem(String itemText, ArrayList<String> lowerLevelItems) {
|
public MultiLevelListItem(String itemText, List<String> lowerLevelItems) {
|
||||||
this.itemText = itemText;
|
this.itemText = itemText;
|
||||||
this.lowerLevelItems = lowerLevelItems;
|
this.lowerLevelItems = lowerLevelItems;
|
||||||
}
|
}
|
||||||
@ -531,8 +534,8 @@ public class InCellLists {
|
|||||||
* @return An ArrayList whose elements each encapsulate the text for a
|
* @return An ArrayList whose elements each encapsulate the text for a
|
||||||
* single associated lower level list item.
|
* single associated lower level list item.
|
||||||
*/
|
*/
|
||||||
public ArrayList<String> getLowerLevelItems() {
|
public List<String> getLowerLevelItems() {
|
||||||
return(this.lowerLevelItems);
|
return lowerLevelItems;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ public class ClipboardData {
|
|||||||
|
|
||||||
public void read( LittleEndianByteArrayInputStream lei ) {
|
public void read( LittleEndianByteArrayInputStream lei ) {
|
||||||
int offset = lei.getReadIndex();
|
int offset = lei.getReadIndex();
|
||||||
int size = lei.readInt();
|
long size = lei.readInt();
|
||||||
|
|
||||||
if ( size < 4 ) {
|
if ( size < 4 ) {
|
||||||
String msg =
|
String msg =
|
||||||
|
@ -417,7 +417,7 @@ public class Property {
|
|||||||
|
|
||||||
// skip length field
|
// skip length field
|
||||||
if(bos.size() > 2*LittleEndianConsts.INT_SIZE) {
|
if(bos.size() > 2*LittleEndianConsts.INT_SIZE) {
|
||||||
final String hex = HexDump.dump(bos.toByteArray(), -2*LittleEndianConsts.INT_SIZE, 2*LittleEndianConsts.INT_SIZE);
|
final String hex = HexDump.dump(bos.toByteArray(), -2L*LittleEndianConsts.INT_SIZE, 2*LittleEndianConsts.INT_SIZE);
|
||||||
b.append(hex);
|
b.append(hex);
|
||||||
}
|
}
|
||||||
} else if (value instanceof byte[]) {
|
} else if (value instanceof byte[]) {
|
||||||
|
@ -265,7 +265,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord {
|
|||||||
// 2 bytes reserved
|
// 2 bytes reserved
|
||||||
in.readUShort();
|
in.readUShort();
|
||||||
} else {
|
} else {
|
||||||
int len = readFormatOptions(in);
|
long len = readFormatOptions(in);
|
||||||
if (len < ext_formatting_length) {
|
if (len < ext_formatting_length) {
|
||||||
ext_formatting_data = IOUtils.safelyAllocate(ext_formatting_length-len, MAX_RECORD_LENGTH);
|
ext_formatting_data = IOUtils.safelyAllocate(ext_formatting_length-len, MAX_RECORD_LENGTH);
|
||||||
in.readFully(ext_formatting_data);
|
in.readFully(ext_formatting_data);
|
||||||
|
@ -40,11 +40,11 @@ public final class DocumentOutputStream extends OutputStream {
|
|||||||
private POIFSDocument _document;
|
private POIFSDocument _document;
|
||||||
/** and its Property */
|
/** and its Property */
|
||||||
private DocumentProperty _property;
|
private DocumentProperty _property;
|
||||||
|
|
||||||
/** our buffer, when null we're into normal blocks */
|
/** our buffer, when null we're into normal blocks */
|
||||||
private ByteArrayOutputStream _buffer =
|
private ByteArrayOutputStream _buffer =
|
||||||
new ByteArrayOutputStream(POIFSConstants.BIG_BLOCK_MINIMUM_DOCUMENT_SIZE);
|
new ByteArrayOutputStream(POIFSConstants.BIG_BLOCK_MINIMUM_DOCUMENT_SIZE);
|
||||||
|
|
||||||
/** our main block stream, when we're into normal blocks */
|
/** our main block stream, when we're into normal blocks */
|
||||||
private POIFSStream _stream;
|
private POIFSStream _stream;
|
||||||
private OutputStream _stream_output;
|
private OutputStream _stream_output;
|
||||||
@ -56,7 +56,7 @@ public final class DocumentOutputStream extends OutputStream {
|
|||||||
/**
|
/**
|
||||||
* Create an OutputStream from the specified DocumentEntry.
|
* Create an OutputStream from the specified DocumentEntry.
|
||||||
* The specified entry will be emptied.
|
* The specified entry will be emptied.
|
||||||
*
|
*
|
||||||
* @param document the DocumentEntry to be written
|
* @param document the DocumentEntry to be written
|
||||||
*/
|
*/
|
||||||
public DocumentOutputStream(DocumentEntry document) throws IOException {
|
public DocumentOutputStream(DocumentEntry document) throws IOException {
|
||||||
@ -65,7 +65,7 @@ public final class DocumentOutputStream extends OutputStream {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an OutputStream to create the specified new Entry
|
* Create an OutputStream to create the specified new Entry
|
||||||
*
|
*
|
||||||
* @param parent Where to create the Entry
|
* @param parent Where to create the Entry
|
||||||
* @param name Name of the new entry
|
* @param name Name of the new entry
|
||||||
*/
|
*/
|
||||||
@ -159,7 +159,7 @@ public final class DocumentOutputStream extends OutputStream {
|
|||||||
_property.updateSize(_document_size);
|
_property.updateSize(_document_size);
|
||||||
_property.setStartBlock(_stream.getStartBlock());
|
_property.setStartBlock(_stream.getStartBlock());
|
||||||
}
|
}
|
||||||
|
|
||||||
// No more!
|
// No more!
|
||||||
_closed = true;
|
_closed = true;
|
||||||
}
|
}
|
||||||
@ -168,6 +168,6 @@ public final class DocumentOutputStream extends OutputStream {
|
|||||||
* @return the amount of written bytes
|
* @return the amount of written bytes
|
||||||
*/
|
*/
|
||||||
public long size() {
|
public long size() {
|
||||||
return _document_size + (_buffer == null ? 0 : _buffer.size());
|
return _document_size + (_buffer == null ? 0L : _buffer.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -199,7 +199,7 @@ public class PathGradientPaint implements Paint {
|
|||||||
// it doesn't work to use just a color with transparency ...
|
// it doesn't work to use just a color with transparency ...
|
||||||
graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC, rgb[3]/255.0f));
|
graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC, rgb[3]/255.0f));
|
||||||
}
|
}
|
||||||
graphics.setStroke(new BasicStroke(i+1, capStyle, joinStyle));
|
graphics.setStroke(new BasicStroke(i+1F, capStyle, joinStyle));
|
||||||
graphics.setColor(c);
|
graphics.setColor(c);
|
||||||
if (i == gradientSteps-1) {
|
if (i == gradientSteps-1) {
|
||||||
graphics.fill(shape);
|
graphics.fill(shape);
|
||||||
|
@ -270,7 +270,7 @@ final class YearFracCalculator {
|
|||||||
for (int i=startYear; i<=endYear; i++) {
|
for (int i=startYear; i<=endYear; i++) {
|
||||||
dayCount += isLeapYear(i) ? DAYS_PER_LEAP_YEAR : DAYS_PER_NORMAL_YEAR;
|
dayCount += isLeapYear(i) ? DAYS_PER_LEAP_YEAR : DAYS_PER_NORMAL_YEAR;
|
||||||
}
|
}
|
||||||
double numberOfYears = endYear-startYear+1;
|
double numberOfYears = endYear-startYear+1.;
|
||||||
return dayCount / numberOfYears;
|
return dayCount / numberOfYears;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,9 +17,7 @@
|
|||||||
package org.apache.poi.ss.formula.functions;
|
package org.apache.poi.ss.formula.functions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Some utils for converting from and to any base<p>
|
* Some utils for converting from and to any base
|
||||||
*
|
|
||||||
* @author cedric dot walter @ gmail dot com
|
|
||||||
*/
|
*/
|
||||||
public class BaseNumberUtils {
|
public class BaseNumberUtils {
|
||||||
|
|
||||||
@ -43,11 +41,11 @@ public class BaseNumberUtils {
|
|||||||
long digit;
|
long digit;
|
||||||
|
|
||||||
if ('0' <= character && character <= '9') {
|
if ('0' <= character && character <= '9') {
|
||||||
digit = character - '0';
|
digit = (long)character - '0';
|
||||||
} else if ('A' <= character && character <= 'Z') {
|
} else if ('A' <= character && character <= 'Z') {
|
||||||
digit = 10 + (character - 'A');
|
digit = 10L + (character - 'A');
|
||||||
} else if ('a' <= character && character <= 'z') {
|
} else if ('a' <= character && character <= 'z') {
|
||||||
digit = 10 + (character - 'a');
|
digit = 10L + (character - 'a');
|
||||||
} else {
|
} else {
|
||||||
digit = base;
|
digit = base;
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ import org.apache.poi.ss.formula.eval.ValueEval;
|
|||||||
public final class Column implements Function0Arg, Function1Arg {
|
public final class Column implements Function0Arg, Function1Arg {
|
||||||
|
|
||||||
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex) {
|
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex) {
|
||||||
return new NumberEval(srcColumnIndex+1);
|
return new NumberEval(srcColumnIndex+1.);
|
||||||
}
|
}
|
||||||
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) {
|
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) {
|
||||||
int rnum;
|
int rnum;
|
||||||
@ -40,14 +40,14 @@ public final class Column implements Function0Arg, Function1Arg {
|
|||||||
return ErrorEval.VALUE_INVALID;
|
return ErrorEval.VALUE_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new NumberEval(rnum + 1);
|
return new NumberEval(rnum + 1.);
|
||||||
}
|
}
|
||||||
public ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
|
public ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
|
||||||
switch (args.length) {
|
switch (args.length) {
|
||||||
case 1:
|
case 1:
|
||||||
return evaluate(srcRowIndex, srcColumnIndex, args[0]);
|
return evaluate(srcRowIndex, srcColumnIndex, args[0]);
|
||||||
case 0:
|
case 0:
|
||||||
return new NumberEval(srcColumnIndex+1);
|
return new NumberEval(srcColumnIndex+1.);
|
||||||
}
|
}
|
||||||
return ErrorEval.VALUE_INVALID;
|
return ErrorEval.VALUE_INVALID;
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@ public final class Match extends Var2or3ArgFunction {
|
|||||||
ValueEval lookupValue = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex);
|
ValueEval lookupValue = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex);
|
||||||
ValueVector lookupRange = evaluateLookupRange(arg1);
|
ValueVector lookupRange = evaluateLookupRange(arg1);
|
||||||
int index = findIndexOfValue(lookupValue, lookupRange, matchExact, findLargestLessThanOrEqual);
|
int index = findIndexOfValue(lookupValue, lookupRange, matchExact, findLargestLessThanOrEqual);
|
||||||
return new NumberEval(index + 1); // +1 to convert to 1-based
|
return new NumberEval(index + 1.); // +1 to convert to 1-based
|
||||||
} catch (EvaluationException e) {
|
} catch (EvaluationException e) {
|
||||||
return e.getErrorEval();
|
return e.getErrorEval();
|
||||||
}
|
}
|
||||||
|
@ -85,7 +85,7 @@ public class Mirr extends MultiOperandNumericFunction {
|
|||||||
|
|
||||||
private static double mirr(double[] in, double financeRate, double reinvestRate) {
|
private static double mirr(double[] in, double financeRate, double reinvestRate) {
|
||||||
double value = 0;
|
double value = 0;
|
||||||
int numOfYears = in.length - 1;
|
double numOfYears = in.length - 1;
|
||||||
double pv = 0;
|
double pv = 0;
|
||||||
double fv = 0;
|
double fv = 0;
|
||||||
|
|
||||||
|
@ -25,13 +25,11 @@ import org.apache.poi.ss.formula.eval.ValueEval;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation for the Excel function ROW
|
* Implementation for the Excel function ROW
|
||||||
*
|
|
||||||
* @author Josh Micich
|
|
||||||
*/
|
*/
|
||||||
public final class RowFunc implements Function0Arg, Function1Arg {
|
public final class RowFunc implements Function0Arg, Function1Arg {
|
||||||
|
|
||||||
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex) {
|
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex) {
|
||||||
return new NumberEval(srcRowIndex+1);
|
return new NumberEval(srcRowIndex+1.);
|
||||||
}
|
}
|
||||||
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) {
|
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) {
|
||||||
int rnum;
|
int rnum;
|
||||||
@ -45,14 +43,14 @@ public final class RowFunc implements Function0Arg, Function1Arg {
|
|||||||
return ErrorEval.VALUE_INVALID;
|
return ErrorEval.VALUE_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new NumberEval(rnum + 1);
|
return new NumberEval(rnum + 1.);
|
||||||
}
|
}
|
||||||
public ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
|
public ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
|
||||||
switch (args.length) {
|
switch (args.length) {
|
||||||
case 1:
|
case 1:
|
||||||
return evaluate(srcRowIndex, srcColumnIndex, args[0]);
|
return evaluate(srcRowIndex, srcColumnIndex, args[0]);
|
||||||
case 0:
|
case 0:
|
||||||
return new NumberEval(srcRowIndex+1);
|
return new NumberEval(srcRowIndex+1.);
|
||||||
}
|
}
|
||||||
return ErrorEval.VALUE_INVALID;
|
return ErrorEval.VALUE_INVALID;
|
||||||
}
|
}
|
||||||
|
@ -17,11 +17,17 @@
|
|||||||
|
|
||||||
package org.apache.poi.ss.formula.functions;
|
package org.apache.poi.ss.formula.functions;
|
||||||
|
|
||||||
import org.apache.poi.ss.formula.eval.*;
|
|
||||||
import org.apache.poi.ss.usermodel.DataFormatter;
|
|
||||||
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import org.apache.poi.ss.formula.eval.BoolEval;
|
||||||
|
import org.apache.poi.ss.formula.eval.ErrorEval;
|
||||||
|
import org.apache.poi.ss.formula.eval.EvaluationException;
|
||||||
|
import org.apache.poi.ss.formula.eval.NumberEval;
|
||||||
|
import org.apache.poi.ss.formula.eval.OperandResolver;
|
||||||
|
import org.apache.poi.ss.formula.eval.StringEval;
|
||||||
|
import org.apache.poi.ss.formula.eval.ValueEval;
|
||||||
|
import org.apache.poi.ss.usermodel.DataFormatter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
|
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
|
||||||
* @author Josh Micich
|
* @author Josh Micich
|
||||||
@ -38,7 +44,7 @@ public abstract class TextFunction implements Function {
|
|||||||
ValueEval ve = OperandResolver.getSingleValue(arg, srcCellRow, srcCellCol);
|
ValueEval ve = OperandResolver.getSingleValue(arg, srcCellRow, srcCellCol);
|
||||||
return OperandResolver.coerceValueToInt(ve);
|
return OperandResolver.coerceValueToInt(ve);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static double evaluateDoubleArg(ValueEval arg, int srcCellRow, int srcCellCol) throws EvaluationException {
|
protected static double evaluateDoubleArg(ValueEval arg, int srcCellRow, int srcCellCol) throws EvaluationException {
|
||||||
ValueEval ve = OperandResolver.getSingleValue(arg, srcCellRow, srcCellCol);
|
ValueEval ve = OperandResolver.getSingleValue(arg, srcCellRow, srcCellCol);
|
||||||
return OperandResolver.coerceValueToDouble(ve);
|
return OperandResolver.coerceValueToDouble(ve);
|
||||||
@ -112,7 +118,7 @@ public abstract class TextFunction implements Function {
|
|||||||
* Implementation of the PROPER function:
|
* Implementation of the PROPER function:
|
||||||
* Normalizes all words (separated by non-word characters) by
|
* Normalizes all words (separated by non-word characters) by
|
||||||
* making the first letter upper and the rest lower case.
|
* making the first letter upper and the rest lower case.
|
||||||
*
|
*
|
||||||
* This is nearly equivalent to toTitleCase if the Java language had it
|
* This is nearly equivalent to toTitleCase if the Java language had it
|
||||||
*/
|
*/
|
||||||
public static final Function PROPER = new SingleArgTextFunc() {
|
public static final Function PROPER = new SingleArgTextFunc() {
|
||||||
@ -147,7 +153,7 @@ public abstract class TextFunction implements Function {
|
|||||||
return new StringEval(arg.trim());
|
return new StringEval(arg.trim());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An implementation of the CLEAN function:
|
* An implementation of the CLEAN function:
|
||||||
* In Excel, the Clean function removes all non-printable characters from a string.
|
* In Excel, the Clean function removes all non-printable characters from a string.
|
||||||
@ -244,11 +250,11 @@ public abstract class TextFunction implements Function {
|
|||||||
} catch (EvaluationException e) {
|
} catch (EvaluationException e) {
|
||||||
return e.getErrorEval();
|
return e.getErrorEval();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(index < 0) {
|
if(index < 0) {
|
||||||
return ErrorEval.VALUE_INVALID;
|
return ErrorEval.VALUE_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
String result;
|
String result;
|
||||||
if (_isLeft) {
|
if (_isLeft) {
|
||||||
result = arg.substring(0, Math.min(arg.length(), index));
|
result = arg.substring(0, Math.min(arg.length(), index));
|
||||||
@ -295,11 +301,11 @@ public abstract class TextFunction implements Function {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* An implementation of the TEXT function<br>
|
* An implementation of the TEXT function<br>
|
||||||
* TEXT returns a number value formatted with the given number formatting string.
|
* TEXT returns a number value formatted with the given number formatting string.
|
||||||
* This function is not a complete implementation of the Excel function, but
|
* This function is not a complete implementation of the Excel function, but
|
||||||
* handles most of the common cases. All work is passed down to
|
* handles most of the common cases. All work is passed down to
|
||||||
* {@link DataFormatter} to be done, as this works much the same as the
|
* {@link DataFormatter} to be done, as this works much the same as the
|
||||||
* display focused work that that does.
|
* display focused work that that does.
|
||||||
*
|
*
|
||||||
* <b>Syntax<b>:<br> <b>TEXT</b>(<b>value</b>, <b>format_text</b>)<br>
|
* <b>Syntax<b>:<br> <b>TEXT</b>(<b>value</b>, <b>format_text</b>)<br>
|
||||||
*/
|
*/
|
||||||
@ -314,7 +320,7 @@ public abstract class TextFunction implements Function {
|
|||||||
} catch (EvaluationException e) {
|
} catch (EvaluationException e) {
|
||||||
return e.getErrorEval();
|
return e.getErrorEval();
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Ask DataFormatter to handle the String for us
|
// Ask DataFormatter to handle the String for us
|
||||||
String formattedStr = formatter.formatRawCellContents(s0, -1, s1);
|
String formattedStr = formatter.formatRawCellContents(s0, -1, s1);
|
||||||
@ -324,7 +330,7 @@ public abstract class TextFunction implements Function {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private static final class SearchFind extends Var2or3ArgFunction {
|
private static final class SearchFind extends Var2or3ArgFunction {
|
||||||
|
|
||||||
private final boolean _isCaseSensitive;
|
private final boolean _isCaseSensitive;
|
||||||
@ -367,7 +373,7 @@ public abstract class TextFunction implements Function {
|
|||||||
if (result == -1) {
|
if (result == -1) {
|
||||||
return ErrorEval.VALUE_INVALID;
|
return ErrorEval.VALUE_INVALID;
|
||||||
}
|
}
|
||||||
return new NumberEval(result + 1);
|
return new NumberEval(result + 1.);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -25,6 +25,10 @@
|
|||||||
|
|
||||||
package org.apache.poi.ss.formula.functions;
|
package org.apache.poi.ss.formula.functions;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import org.apache.commons.math3.linear.SingularMatrixException;
|
||||||
|
import org.apache.commons.math3.stat.regression.OLSMultipleLinearRegression;
|
||||||
import org.apache.poi.ss.formula.CacheAreaEval;
|
import org.apache.poi.ss.formula.CacheAreaEval;
|
||||||
import org.apache.poi.ss.formula.eval.AreaEval;
|
import org.apache.poi.ss.formula.eval.AreaEval;
|
||||||
import org.apache.poi.ss.formula.eval.BoolEval;
|
import org.apache.poi.ss.formula.eval.BoolEval;
|
||||||
@ -36,15 +40,11 @@ import org.apache.poi.ss.formula.eval.NumberEval;
|
|||||||
import org.apache.poi.ss.formula.eval.NumericValueEval;
|
import org.apache.poi.ss.formula.eval.NumericValueEval;
|
||||||
import org.apache.poi.ss.formula.eval.RefEval;
|
import org.apache.poi.ss.formula.eval.RefEval;
|
||||||
import org.apache.poi.ss.formula.eval.ValueEval;
|
import org.apache.poi.ss.formula.eval.ValueEval;
|
||||||
import org.apache.commons.math3.linear.SingularMatrixException;
|
|
||||||
import org.apache.commons.math3.stat.regression.OLSMultipleLinearRegression;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation for the Excel function TREND<p>
|
* Implementation for the Excel function TREND<p>
|
||||||
*
|
*
|
||||||
* Syntax:<br>
|
* Syntax:<br>
|
||||||
* TREND(known_y's, known_x's, new_x's, constant)
|
* TREND(known_y's, known_x's, new_x's, constant)
|
||||||
* <table border="0" cellpadding="1" cellspacing="0" summary="Parameter descriptions">
|
* <table border="0" cellpadding="1" cellspacing="0" summary="Parameter descriptions">
|
||||||
@ -131,14 +131,14 @@ public final class Trend implements Function {
|
|||||||
} else {
|
} else {
|
||||||
throw new EvaluationException(ErrorEval.VALUE_INVALID);
|
throw new EvaluationException(ErrorEval.VALUE_INVALID);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ar;
|
return ar;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static double[][] getDefaultArrayOneD(int w) {
|
private static double[][] getDefaultArrayOneD(int w) {
|
||||||
double[][] array = new double[w][1];
|
double[][] array = new double[w][1];
|
||||||
for (int i = 0; i < w; i++) {
|
for (int i = 0; i < w; i++) {
|
||||||
array[i][0] = i + 1;
|
array[i][0] = i + 1.;
|
||||||
}
|
}
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
@ -319,11 +319,11 @@ public final class Trend implements Function {
|
|||||||
} else if (newXOrig.length == 1 && newXOrig[0].length > 1 && xOrig.length > 1 && xOrig[0].length == 1) {
|
} else if (newXOrig.length == 1 && newXOrig[0].length > 1 && xOrig.length > 1 && xOrig[0].length == 1) {
|
||||||
newX = switchRowsColumns(newXOrig);
|
newX = switchRowsColumns(newXOrig);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newX[0].length != x[0].length) {
|
if (newX[0].length != x[0].length) {
|
||||||
throw new EvaluationException(ErrorEval.REF_INVALID);
|
throw new EvaluationException(ErrorEval.REF_INVALID);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (x[0].length >= x.length) {
|
if (x[0].length >= x.length) {
|
||||||
/* See comment at top of file */
|
/* See comment at top of file */
|
||||||
throw new NotImplementedException("Sample size too small");
|
throw new NotImplementedException("Sample size too small");
|
||||||
|
@ -114,9 +114,11 @@ public final class WeekdayFunc implements Function {
|
|||||||
} else if (returnOption == 3) {
|
} else if (returnOption == 3) {
|
||||||
result = (weekday + 6 - 1) % 7;
|
result = (weekday + 6 - 1) % 7;
|
||||||
} else if (returnOption >= 11 && returnOption <= 17) {
|
} else if (returnOption >= 11 && returnOption <= 17) {
|
||||||
result = (weekday + 6 - (returnOption - 10)) % 7 + 1; // rotate in the value range 1 to 7
|
// rotate in the value range 1 to 7
|
||||||
|
result = (weekday + 6 - (returnOption - 10)) % 7 + 1.;
|
||||||
} else {
|
} else {
|
||||||
return ErrorEval.NUM_ERROR; // EXCEL uses this and no VALUE_ERROR
|
// EXCEL uses this and no VALUE_ERROR
|
||||||
|
return ErrorEval.NUM_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new NumberEval(result);
|
return new NumberEval(result);
|
||||||
|
@ -428,7 +428,7 @@ public class DateUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
LocalDateTime ldt = LocalDateTime.of(startYear, 1, 1, 0, 0);
|
LocalDateTime ldt = LocalDateTime.of(startYear, 1, 1, 0, 0);
|
||||||
ldt = ldt.plusDays(wholeDays+dayAdjust-1);
|
ldt = ldt.plusDays(wholeDays+dayAdjust-1L);
|
||||||
|
|
||||||
long nanosTime =
|
long nanosTime =
|
||||||
bd.subtract(BigDecimal.valueOf(wholeDays))
|
bd.subtract(BigDecimal.valueOf(wholeDays))
|
||||||
|
@ -128,7 +128,7 @@ public abstract class LZWDecompresser {
|
|||||||
// These are bytes as looked up in the dictionary
|
// These are bytes as looked up in the dictionary
|
||||||
// It needs to be signed, as it'll get passed on to
|
// It needs to be signed, as it'll get passed on to
|
||||||
// the output stream
|
// the output stream
|
||||||
final byte[] dataB = IOUtils.safelyAllocate(16 + codeLengthIncrease, MAX_RECORD_LENGTH);
|
final byte[] dataB = IOUtils.safelyAllocate(16L + codeLengthIncrease, MAX_RECORD_LENGTH);
|
||||||
// This is an unsigned byte read from the stream
|
// This is an unsigned byte read from the stream
|
||||||
// It needs to be unsigned, so that bit stuff works
|
// It needs to be unsigned, so that bit stuff works
|
||||||
int dataI;
|
int dataI;
|
||||||
|
@ -17,14 +17,14 @@
|
|||||||
|
|
||||||
package org.apache.poi.util;
|
package org.apache.poi.util;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper of InputStream which provides Run Length Encoding (RLE)
|
* Wrapper of InputStream which provides Run Length Encoding (RLE)
|
||||||
* decompression on the fly. Uses MS-OVBA decompression algorithm. See
|
* decompression on the fly. Uses MS-OVBA decompression algorithm. See
|
||||||
* http://download.microsoft.com/download/2/4/8/24862317-78F0-4C4B-B355-C7B2C1D997DB/[MS-OVBA].pdf
|
* http://download.microsoft.com/download/2/4/8/24862317-78F0-4C4B-B355-C7B2C1D997DB/[MS-OVBA].pdf
|
||||||
*/
|
*/
|
||||||
@ -66,7 +66,7 @@ public class RLEDecompressingInputStream extends InputStream {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new wrapper RLE Decompression InputStream.
|
* Creates a new wrapper RLE Decompression InputStream.
|
||||||
*
|
*
|
||||||
* @param in The stream to wrap with the RLE Decompression
|
* @param in The stream to wrap with the RLE Decompression
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
@ -131,7 +131,7 @@ public class RLEDecompressingInputStream extends InputStream {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int c = (int) Math.min(n, len - pos);
|
int c = (int) Math.min(n, len - (long)pos);
|
||||||
pos += c;
|
pos += c;
|
||||||
length -= c;
|
length -= c;
|
||||||
}
|
}
|
||||||
@ -150,7 +150,7 @@ public class RLEDecompressingInputStream extends InputStream {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads a single chunk from the underlying inputstream.
|
* Reads a single chunk from the underlying inputstream.
|
||||||
*
|
*
|
||||||
* @return number of bytes that were read, or -1 if the end of the stream was reached.
|
* @return number of bytes that were read, or -1 if the end of the stream was reached.
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
@ -215,7 +215,7 @@ public class RLEDecompressingInputStream extends InputStream {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper method to determine how many bits in the CopyToken are used for the CopyLength.
|
* Helper method to determine how many bits in the CopyToken are used for the CopyLength.
|
||||||
*
|
*
|
||||||
* @param offset
|
* @param offset
|
||||||
* @return returns the number of bits in the copy token (a value between 4 and 12)
|
* @return returns the number of bits in the copy token (a value between 4 and 12)
|
||||||
*/
|
*/
|
||||||
@ -230,7 +230,7 @@ public class RLEDecompressingInputStream extends InputStream {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience method for read a 2-bytes short in little endian encoding.
|
* Convenience method for read a 2-bytes short in little endian encoding.
|
||||||
*
|
*
|
||||||
* @return short value from the stream, -1 if end of stream is reached
|
* @return short value from the stream, -1 if end of stream is reached
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
@ -240,7 +240,7 @@ public class RLEDecompressingInputStream extends InputStream {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience method for read a 4-bytes int in little endian encoding.
|
* Convenience method for read a 4-bytes int in little endian encoding.
|
||||||
*
|
*
|
||||||
* @return integer value from the stream, -1 if end of stream is reached
|
* @return integer value from the stream, -1 if end of stream is reached
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
@ -279,7 +279,7 @@ public class RLEDecompressingInputStream extends InputStream {
|
|||||||
public static byte[] decompress(byte[] compressed) throws IOException {
|
public static byte[] decompress(byte[] compressed) throws IOException {
|
||||||
return decompress(compressed, 0, compressed.length);
|
return decompress(compressed, 0, compressed.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] decompress(byte[] compressed, int offset, int length) throws IOException {
|
public static byte[] decompress(byte[] compressed, int offset, int length) throws IOException {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
InputStream instream = new ByteArrayInputStream(compressed, offset, length);
|
InputStream instream = new ByteArrayInputStream(compressed, offset, length);
|
||||||
|
@ -20,12 +20,11 @@ package org.apache.poi.xdgf.usermodel;
|
|||||||
import java.awt.geom.Point2D;
|
import java.awt.geom.Point2D;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
|
|
||||||
|
import com.microsoft.schemas.office.visio.x2012.main.PageType;
|
||||||
import org.apache.poi.ooxml.POIXMLException;
|
import org.apache.poi.ooxml.POIXMLException;
|
||||||
import org.apache.poi.util.Internal;
|
import org.apache.poi.util.Internal;
|
||||||
import org.apache.poi.xdgf.geom.Dimension2dDouble;
|
import org.apache.poi.xdgf.geom.Dimension2dDouble;
|
||||||
|
|
||||||
import com.microsoft.schemas.office.visio.x2012.main.PageType;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides the API to work with an underlying page
|
* Provides the API to work with an underlying page
|
||||||
*/
|
*/
|
||||||
@ -69,7 +68,7 @@ public class XDGFPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public long getPageNumber() {
|
public long getPageNumber() {
|
||||||
return _pages.getPageList().indexOf(this) + 1;
|
return _pages.getPageList().indexOf(this) + 1L;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -195,7 +195,7 @@ public final class XSSFChart extends XDDFChart implements Chart, ChartAxisFactor
|
|||||||
@Deprecated
|
@Deprecated
|
||||||
@Removal(version = "4.2")
|
@Removal(version = "4.2")
|
||||||
public XSSFValueAxis createValueAxis(org.apache.poi.ss.usermodel.charts.AxisPosition pos) {
|
public XSSFValueAxis createValueAxis(org.apache.poi.ss.usermodel.charts.AxisPosition pos) {
|
||||||
long id = axis.size() + 1;
|
long id = axis.size() + 1L;
|
||||||
XSSFValueAxis valueAxis = new XSSFValueAxis(this, id, pos);
|
XSSFValueAxis valueAxis = new XSSFValueAxis(this, id, pos);
|
||||||
if (axis.size() == 1) {
|
if (axis.size() == 1) {
|
||||||
ChartAxis ax = axis.get(0);
|
ChartAxis ax = axis.get(0);
|
||||||
@ -210,7 +210,7 @@ public final class XSSFChart extends XDDFChart implements Chart, ChartAxisFactor
|
|||||||
@Deprecated
|
@Deprecated
|
||||||
@Removal(version = "4.2")
|
@Removal(version = "4.2")
|
||||||
public XSSFCategoryAxis createCategoryAxis(org.apache.poi.ss.usermodel.charts.AxisPosition pos) {
|
public XSSFCategoryAxis createCategoryAxis(org.apache.poi.ss.usermodel.charts.AxisPosition pos) {
|
||||||
long id = axis.size() + 1;
|
long id = axis.size() + 1L;
|
||||||
XSSFCategoryAxis categoryAxis = new XSSFCategoryAxis(this, id, pos);
|
XSSFCategoryAxis categoryAxis = new XSSFCategoryAxis(this, id, pos);
|
||||||
if (axis.size() == 1) {
|
if (axis.size() == 1) {
|
||||||
ChartAxis ax = axis.get(0);
|
ChartAxis ax = axis.get(0);
|
||||||
@ -225,7 +225,7 @@ public final class XSSFChart extends XDDFChart implements Chart, ChartAxisFactor
|
|||||||
@Deprecated
|
@Deprecated
|
||||||
@Removal(version = "4.2")
|
@Removal(version = "4.2")
|
||||||
public XSSFDateAxis createDateAxis(org.apache.poi.ss.usermodel.charts.AxisPosition pos) {
|
public XSSFDateAxis createDateAxis(org.apache.poi.ss.usermodel.charts.AxisPosition pos) {
|
||||||
long id = axis.size() + 1;
|
long id = axis.size() + 1L;
|
||||||
XSSFDateAxis dateAxis = new XSSFDateAxis(this, id, pos);
|
XSSFDateAxis dateAxis = new XSSFDateAxis(this, id, pos);
|
||||||
if (axis.size() == 1) {
|
if (axis.size() == 1) {
|
||||||
ChartAxis ax = axis.get(0);
|
ChartAxis ax = axis.get(0);
|
||||||
|
@ -17,10 +17,10 @@
|
|||||||
|
|
||||||
package org.apache.poi.xssf.usermodel;
|
package org.apache.poi.xssf.usermodel;
|
||||||
|
|
||||||
|
import org.apache.poi.util.Internal;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D;
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D;
|
import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D;
|
||||||
import org.apache.poi.util.Internal;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Yegor Kozlov
|
* @author Yegor Kozlov
|
||||||
@ -71,7 +71,7 @@ public final class XSSFChildAnchor extends XSSFAnchor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setDy2(int dy2) {
|
public void setDy2(int dy2) {
|
||||||
t2d.getExt().setCy(dy2 - getDy1());
|
t2d.getExt().setCy(dy2 - (long)getDy1());
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getDx2() {
|
public int getDx2() {
|
||||||
@ -79,6 +79,6 @@ public final class XSSFChildAnchor extends XSSFAnchor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setDx2(int dx2) {
|
public void setDx2(int dx2) {
|
||||||
t2d.getExt().setCx(dx2 - getDx1());
|
t2d.getExt().setCx(dx2 - (long)getDx1());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,11 +22,29 @@ package org.apache.poi.xssf.usermodel;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.poi.ss.usermodel.*;
|
import org.apache.poi.ss.usermodel.ComparisonOperator;
|
||||||
|
import org.apache.poi.ss.usermodel.ConditionFilterData;
|
||||||
|
import org.apache.poi.ss.usermodel.ConditionFilterType;
|
||||||
|
import org.apache.poi.ss.usermodel.ConditionType;
|
||||||
|
import org.apache.poi.ss.usermodel.ConditionalFormattingRule;
|
||||||
import org.apache.poi.ss.usermodel.ConditionalFormattingThreshold.RangeType;
|
import org.apache.poi.ss.usermodel.ConditionalFormattingThreshold.RangeType;
|
||||||
|
import org.apache.poi.ss.usermodel.ExcelNumberFormat;
|
||||||
import org.apache.poi.ss.usermodel.IconMultiStateFormatting.IconSet;
|
import org.apache.poi.ss.usermodel.IconMultiStateFormatting.IconSet;
|
||||||
import org.apache.poi.xssf.model.StylesTable;
|
import org.apache.poi.xssf.model.StylesTable;
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.*;
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBorder;
|
||||||
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCfRule;
|
||||||
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCfvo;
|
||||||
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColorScale;
|
||||||
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDataBar;
|
||||||
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDxf;
|
||||||
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFill;
|
||||||
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFont;
|
||||||
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTIconSet;
|
||||||
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTNumFmt;
|
||||||
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCfType;
|
||||||
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCfvoType;
|
||||||
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STConditionalFormattingOperator;
|
||||||
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STIconSetType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* XSSF support for Conditional Formatting rules
|
* XSSF support for Conditional Formatting rules
|
||||||
@ -34,7 +52,7 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.*;
|
|||||||
public class XSSFConditionalFormattingRule implements ConditionalFormattingRule {
|
public class XSSFConditionalFormattingRule implements ConditionalFormattingRule {
|
||||||
private final CTCfRule _cfRule;
|
private final CTCfRule _cfRule;
|
||||||
private XSSFSheet _sh;
|
private XSSFSheet _sh;
|
||||||
|
|
||||||
private static Map<STCfType.Enum, ConditionType> typeLookup = new HashMap<>();
|
private static Map<STCfType.Enum, ConditionType> typeLookup = new HashMap<>();
|
||||||
private static Map<STCfType.Enum, ConditionFilterType> filterTypeLookup = new HashMap<>();
|
private static Map<STCfType.Enum, ConditionFilterType> filterTypeLookup = new HashMap<>();
|
||||||
static {
|
static {
|
||||||
@ -43,7 +61,7 @@ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule
|
|||||||
typeLookup.put(STCfType.COLOR_SCALE, ConditionType.COLOR_SCALE);
|
typeLookup.put(STCfType.COLOR_SCALE, ConditionType.COLOR_SCALE);
|
||||||
typeLookup.put(STCfType.DATA_BAR, ConditionType.DATA_BAR);
|
typeLookup.put(STCfType.DATA_BAR, ConditionType.DATA_BAR);
|
||||||
typeLookup.put(STCfType.ICON_SET, ConditionType.ICON_SET);
|
typeLookup.put(STCfType.ICON_SET, ConditionType.ICON_SET);
|
||||||
|
|
||||||
// These are all subtypes of Filter, we think...
|
// These are all subtypes of Filter, we think...
|
||||||
typeLookup.put(STCfType.TOP_10, ConditionType.FILTER);
|
typeLookup.put(STCfType.TOP_10, ConditionType.FILTER);
|
||||||
typeLookup.put(STCfType.UNIQUE_VALUES, ConditionType.FILTER);
|
typeLookup.put(STCfType.UNIQUE_VALUES, ConditionType.FILTER);
|
||||||
@ -58,7 +76,7 @@ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule
|
|||||||
typeLookup.put(STCfType.NOT_CONTAINS_ERRORS, ConditionType.FILTER);
|
typeLookup.put(STCfType.NOT_CONTAINS_ERRORS, ConditionType.FILTER);
|
||||||
typeLookup.put(STCfType.TIME_PERIOD, ConditionType.FILTER);
|
typeLookup.put(STCfType.TIME_PERIOD, ConditionType.FILTER);
|
||||||
typeLookup.put(STCfType.ABOVE_AVERAGE, ConditionType.FILTER);
|
typeLookup.put(STCfType.ABOVE_AVERAGE, ConditionType.FILTER);
|
||||||
|
|
||||||
filterTypeLookup.put(STCfType.TOP_10, ConditionFilterType.TOP_10);
|
filterTypeLookup.put(STCfType.TOP_10, ConditionFilterType.TOP_10);
|
||||||
filterTypeLookup.put(STCfType.UNIQUE_VALUES, ConditionFilterType.UNIQUE_VALUES);
|
filterTypeLookup.put(STCfType.UNIQUE_VALUES, ConditionFilterType.UNIQUE_VALUES);
|
||||||
filterTypeLookup.put(STCfType.DUPLICATE_VALUES, ConditionFilterType.DUPLICATE_VALUES);
|
filterTypeLookup.put(STCfType.DUPLICATE_VALUES, ConditionFilterType.DUPLICATE_VALUES);
|
||||||
@ -74,7 +92,7 @@ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule
|
|||||||
filterTypeLookup.put(STCfType.ABOVE_AVERAGE, ConditionFilterType.ABOVE_AVERAGE);
|
filterTypeLookup.put(STCfType.ABOVE_AVERAGE, ConditionFilterType.ABOVE_AVERAGE);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NOTE: does not set priority, so this assumes the rule will not be added to the sheet yet
|
* NOTE: does not set priority, so this assumes the rule will not be added to the sheet yet
|
||||||
* @param sh
|
* @param sh
|
||||||
@ -103,7 +121,7 @@ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule
|
|||||||
if(create && dxf == null) {
|
if(create && dxf == null) {
|
||||||
dxf = CTDxf.Factory.newInstance();
|
dxf = CTDxf.Factory.newInstance();
|
||||||
int dxfId = styles.putDxf(dxf);
|
int dxfId = styles.putDxf(dxf);
|
||||||
_cfRule.setDxfId(dxfId - 1);
|
_cfRule.setDxfId(dxfId - 1L);
|
||||||
}
|
}
|
||||||
return dxf;
|
return dxf;
|
||||||
}
|
}
|
||||||
@ -113,11 +131,11 @@ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule
|
|||||||
// priorities start at 1, if it is less, it is undefined, use definition order in caller
|
// priorities start at 1, if it is less, it is undefined, use definition order in caller
|
||||||
return priority >=1 ? priority : 0;
|
return priority >=1 ? priority : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getStopIfTrue() {
|
public boolean getStopIfTrue() {
|
||||||
return _cfRule.getStopIfTrue();
|
return _cfRule.getStopIfTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new border formatting structure if it does not exist,
|
* Create a new border formatting structure if it does not exist,
|
||||||
* otherwise just return existing object.
|
* otherwise just return existing object.
|
||||||
@ -201,7 +219,7 @@ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule
|
|||||||
|
|
||||||
return new XSSFPatternFormatting(dxf.getFill(), _sh.getWorkbook().getStylesSource().getIndexedColors());
|
return new XSSFPatternFormatting(dxf.getFill(), _sh.getWorkbook().getStylesSource().getIndexedColors());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param color
|
* @param color
|
||||||
@ -211,7 +229,7 @@ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule
|
|||||||
// Is it already there?
|
// Is it already there?
|
||||||
if (_cfRule.isSetDataBar() && _cfRule.getType() == STCfType.DATA_BAR)
|
if (_cfRule.isSetDataBar() && _cfRule.getType() == STCfType.DATA_BAR)
|
||||||
return getDataBarFormatting();
|
return getDataBarFormatting();
|
||||||
|
|
||||||
// Mark it as being a Data Bar
|
// Mark it as being a Data Bar
|
||||||
_cfRule.setType(STCfType.DATA_BAR);
|
_cfRule.setType(STCfType.DATA_BAR);
|
||||||
|
|
||||||
@ -224,13 +242,13 @@ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule
|
|||||||
}
|
}
|
||||||
// Set the color
|
// Set the color
|
||||||
bar.setColor(color.getCTColor());
|
bar.setColor(color.getCTColor());
|
||||||
|
|
||||||
// Add the default thresholds
|
// Add the default thresholds
|
||||||
CTCfvo min = bar.addNewCfvo();
|
CTCfvo min = bar.addNewCfvo();
|
||||||
min.setType(STCfvoType.Enum.forString(RangeType.MIN.name));
|
min.setType(STCfvoType.Enum.forString(RangeType.MIN.name));
|
||||||
CTCfvo max = bar.addNewCfvo();
|
CTCfvo max = bar.addNewCfvo();
|
||||||
max.setType(STCfvoType.Enum.forString(RangeType.MAX.name));
|
max.setType(STCfvoType.Enum.forString(RangeType.MAX.name));
|
||||||
|
|
||||||
// Wrap and return
|
// Wrap and return
|
||||||
return new XSSFDataBarFormatting(bar, _sh.getWorkbook().getStylesSource().getIndexedColors());
|
return new XSSFDataBarFormatting(bar, _sh.getWorkbook().getStylesSource().getIndexedColors());
|
||||||
}
|
}
|
||||||
@ -242,12 +260,12 @@ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public XSSFIconMultiStateFormatting createMultiStateFormatting(IconSet iconSet) {
|
public XSSFIconMultiStateFormatting createMultiStateFormatting(IconSet iconSet) {
|
||||||
// Is it already there?
|
// Is it already there?
|
||||||
if (_cfRule.isSetIconSet() && _cfRule.getType() == STCfType.ICON_SET)
|
if (_cfRule.isSetIconSet() && _cfRule.getType() == STCfType.ICON_SET)
|
||||||
return getMultiStateFormatting();
|
return getMultiStateFormatting();
|
||||||
|
|
||||||
// Mark it as being an Icon Set
|
// Mark it as being an Icon Set
|
||||||
_cfRule.setType(STCfType.ICON_SET);
|
_cfRule.setType(STCfType.ICON_SET);
|
||||||
|
|
||||||
@ -263,7 +281,7 @@ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule
|
|||||||
STIconSetType.Enum xIconSet = STIconSetType.Enum.forString(iconSet.name);
|
STIconSetType.Enum xIconSet = STIconSetType.Enum.forString(iconSet.name);
|
||||||
icons.setIconSet(xIconSet);
|
icons.setIconSet(xIconSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a default set of thresholds
|
// Add a default set of thresholds
|
||||||
int jump = 100 / iconSet.num;
|
int jump = 100 / iconSet.num;
|
||||||
STCfvoType.Enum type = STCfvoType.Enum.forString(RangeType.PERCENT.name);
|
STCfvoType.Enum type = STCfvoType.Enum.forString(RangeType.PERCENT.name);
|
||||||
@ -272,7 +290,7 @@ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule
|
|||||||
cfvo.setType(type);
|
cfvo.setType(type);
|
||||||
cfvo.setVal(Integer.toString(i*jump));
|
cfvo.setVal(Integer.toString(i*jump));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrap and return
|
// Wrap and return
|
||||||
return new XSSFIconMultiStateFormatting(icons);
|
return new XSSFIconMultiStateFormatting(icons);
|
||||||
}
|
}
|
||||||
@ -284,12 +302,12 @@ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public XSSFColorScaleFormatting createColorScaleFormatting() {
|
public XSSFColorScaleFormatting createColorScaleFormatting() {
|
||||||
// Is it already there?
|
// Is it already there?
|
||||||
if (_cfRule.isSetColorScale() && _cfRule.getType() == STCfType.COLOR_SCALE)
|
if (_cfRule.isSetColorScale() && _cfRule.getType() == STCfType.COLOR_SCALE)
|
||||||
return getColorScaleFormatting();
|
return getColorScaleFormatting();
|
||||||
|
|
||||||
// Mark it as being a Color Scale
|
// Mark it as being a Color Scale
|
||||||
_cfRule.setType(STCfType.COLOR_SCALE);
|
_cfRule.setType(STCfType.COLOR_SCALE);
|
||||||
|
|
||||||
@ -300,7 +318,7 @@ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule
|
|||||||
} else {
|
} else {
|
||||||
scale = _cfRule.addNewColorScale();
|
scale = _cfRule.addNewColorScale();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a default set of thresholds and colors
|
// Add a default set of thresholds and colors
|
||||||
if (scale.sizeOfCfvoArray() == 0) {
|
if (scale.sizeOfCfvoArray() == 0) {
|
||||||
CTCfvo cfvo;
|
CTCfvo cfvo;
|
||||||
@ -311,12 +329,12 @@ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule
|
|||||||
cfvo.setVal("50");
|
cfvo.setVal("50");
|
||||||
cfvo = scale.addNewCfvo();
|
cfvo = scale.addNewCfvo();
|
||||||
cfvo.setType(STCfvoType.Enum.forString(RangeType.MAX.name));
|
cfvo.setType(STCfvoType.Enum.forString(RangeType.MAX.name));
|
||||||
|
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i<3; i++) {
|
||||||
scale.addNewColor();
|
scale.addNewColor();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrap and return
|
// Wrap and return
|
||||||
return new XSSFColorScaleFormatting(scale, _sh.getWorkbook().getStylesSource().getIndexedColors());
|
return new XSSFColorScaleFormatting(scale, _sh.getWorkbook().getStylesSource().getIndexedColors());
|
||||||
}
|
}
|
||||||
@ -336,11 +354,11 @@ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule
|
|||||||
public ExcelNumberFormat getNumberFormat() {
|
public ExcelNumberFormat getNumberFormat() {
|
||||||
CTDxf dxf = getDxf(false);
|
CTDxf dxf = getDxf(false);
|
||||||
if(dxf == null || !dxf.isSetNumFmt()) return null;
|
if(dxf == null || !dxf.isSetNumFmt()) return null;
|
||||||
|
|
||||||
CTNumFmt numFmt = dxf.getNumFmt();
|
CTNumFmt numFmt = dxf.getNumFmt();
|
||||||
return new ExcelNumberFormat((int) numFmt.getNumFmtId(), numFmt.getFormatCode());
|
return new ExcelNumberFormat((int) numFmt.getNumFmtId(), numFmt.getFormatCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type of conditional formatting rule.
|
* Type of conditional formatting rule.
|
||||||
*/
|
*/
|
||||||
@ -356,11 +374,11 @@ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule
|
|||||||
public ConditionFilterType getConditionFilterType() {
|
public ConditionFilterType getConditionFilterType() {
|
||||||
return filterTypeLookup.get(_cfRule.getType());
|
return filterTypeLookup.get(_cfRule.getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConditionFilterData getFilterConfiguration() {
|
public ConditionFilterData getFilterConfiguration() {
|
||||||
return new XSSFConditionFilterData(_cfRule);
|
return new XSSFConditionFilterData(_cfRule);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The comparison function used when the type of conditional formatting is set to
|
* The comparison function used when the type of conditional formatting is set to
|
||||||
* {@link ConditionType#CELL_VALUE_IS}
|
* {@link ConditionType#CELL_VALUE_IS}
|
||||||
@ -374,7 +392,7 @@ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule
|
|||||||
public byte getComparisonOperation(){
|
public byte getComparisonOperation(){
|
||||||
STConditionalFormattingOperator.Enum op = _cfRule.getOperator();
|
STConditionalFormattingOperator.Enum op = _cfRule.getOperator();
|
||||||
if(op == null) return ComparisonOperator.NO_COMPARISON;
|
if(op == null) return ComparisonOperator.NO_COMPARISON;
|
||||||
|
|
||||||
switch(op.intValue()){
|
switch(op.intValue()){
|
||||||
case STConditionalFormattingOperator.INT_LESS_THAN: return ComparisonOperator.LT;
|
case STConditionalFormattingOperator.INT_LESS_THAN: return ComparisonOperator.LT;
|
||||||
case STConditionalFormattingOperator.INT_LESS_THAN_OR_EQUAL: return ComparisonOperator.LE;
|
case STConditionalFormattingOperator.INT_LESS_THAN_OR_EQUAL: return ComparisonOperator.LE;
|
||||||
@ -416,11 +434,11 @@ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule
|
|||||||
public String getFormula2(){
|
public String getFormula2(){
|
||||||
return _cfRule.sizeOfFormulaArray() == 2 ? _cfRule.getFormulaArray(1) : null;
|
return _cfRule.sizeOfFormulaArray() == 2 ? _cfRule.getFormulaArray(1) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getText() {
|
public String getText() {
|
||||||
return _cfRule.getText();
|
return _cfRule.getText();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Conditional format rules don't define stripes, so always 0
|
* Conditional format rules don't define stripes, so always 0
|
||||||
* @see org.apache.poi.ss.usermodel.DifferentialStyleProvider#getStripeSize()
|
* @see org.apache.poi.ss.usermodel.DifferentialStyleProvider#getStripeSize()
|
||||||
|
@ -583,7 +583,7 @@ public final class XSSFDrawing extends POIXMLDocumentPart implements Drawing<XSS
|
|||||||
}
|
}
|
||||||
|
|
||||||
private long newShapeId() {
|
private long newShapeId() {
|
||||||
return 1 + drawing.sizeOfAbsoluteAnchorArray() + drawing.sizeOfOneCellAnchorArray() + drawing
|
return 1L + drawing.sizeOfAbsoluteAnchorArray() + drawing.sizeOfOneCellAnchorArray() + drawing
|
||||||
.sizeOfTwoCellAnchorArray();
|
.sizeOfTwoCellAnchorArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -423,7 +423,7 @@ public class XSSFRow implements Row, Comparable<XSSFRow> {
|
|||||||
throw new IllegalArgumentException("Invalid row number (" + rowIndex
|
throw new IllegalArgumentException("Invalid row number (" + rowIndex
|
||||||
+ ") outside allowable range (0.." + maxrow + ")");
|
+ ") outside allowable range (0.." + maxrow + ")");
|
||||||
}
|
}
|
||||||
_row.setR(rowIndex + 1);
|
_row.setR(rowIndex + 1L);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -92,50 +92,7 @@ import org.apache.xmlbeans.XmlCursor;
|
|||||||
import org.apache.xmlbeans.XmlException;
|
import org.apache.xmlbeans.XmlException;
|
||||||
import org.apache.xmlbeans.XmlObject;
|
import org.apache.xmlbeans.XmlObject;
|
||||||
import org.apache.xmlbeans.XmlOptions;
|
import org.apache.xmlbeans.XmlOptions;
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTAutoFilter;
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.*;
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBreak;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCalcPr;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCell;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCellFormula;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCol;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCols;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComment;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCommentList;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDataValidation;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDataValidations;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDrawing;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTHeaderFooter;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTHyperlink;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTIgnoredError;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTIgnoredErrors;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTLegacyDrawing;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTMergeCell;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTMergeCells;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTOleObject;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTOleObjects;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTOutlinePr;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPageBreak;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPageMargins;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPageSetUpPr;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPane;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPrintOptions;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRow;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSelection;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheet;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetCalcPr;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetFormatPr;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetPr;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetProtection;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetView;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetViews;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTablePart;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableParts;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheet;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCalcMode;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCellFormulaType;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STPane;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STPaneState;
|
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.WorksheetDocument;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* High level representation of a SpreadsheetML worksheet.
|
* High level representation of a SpreadsheetML worksheet.
|
||||||
@ -1916,9 +1873,11 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
|
|||||||
|
|
||||||
private void setBreak(int id, CTPageBreak ctPgBreak, int lastIndex) {
|
private void setBreak(int id, CTPageBreak ctPgBreak, int lastIndex) {
|
||||||
CTBreak brk = ctPgBreak.addNewBrk();
|
CTBreak brk = ctPgBreak.addNewBrk();
|
||||||
brk.setId(id + 1); // this is id of the element which is 1-based: <row r="1" ... >
|
// this is id of the element which is 1-based: <row r="1" ... >
|
||||||
|
brk.setId(id + 1L);
|
||||||
brk.setMan(true);
|
brk.setMan(true);
|
||||||
brk.setMax(lastIndex); //end column of the break
|
// end column of the break
|
||||||
|
brk.setMax(lastIndex);
|
||||||
|
|
||||||
int nPageBreaks = ctPgBreak.sizeOfBrkArray();
|
int nPageBreaks = ctPgBreak.sizeOfBrkArray();
|
||||||
ctPgBreak.setCount(nPageBreaks);
|
ctPgBreak.setCount(nPageBreaks);
|
||||||
@ -2256,13 +2215,12 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ciMin == targetColumnIx || ciMax == targetColumnIx) {
|
if (ciMin == targetColumnIx || ciMax == targetColumnIx) {
|
||||||
// The target column is at either end of the multi-column ColumnInfo
|
// The target column is at either end of the multi-column ColumnInfo ci
|
||||||
// ci
|
|
||||||
// we'll just divide the info and create a new one
|
// we'll just divide the info and create a new one
|
||||||
if (ciMin == targetColumnIx) {
|
if (ciMin == targetColumnIx) {
|
||||||
ci.setMin(targetColumnIx + 1);
|
ci.setMin(targetColumnIx + 1L);
|
||||||
} else {
|
} else {
|
||||||
ci.setMax(targetColumnIx - 1);
|
ci.setMax(targetColumnIx - 1L);
|
||||||
}
|
}
|
||||||
CTCol nci = columnHelper.cloneCol(cols, ci);
|
CTCol nci = columnHelper.cloneCol(cols, ci);
|
||||||
nci.setMin(targetColumnIx);
|
nci.setMin(targetColumnIx);
|
||||||
@ -2275,14 +2233,14 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
|
|||||||
CTCol ciEnd = columnHelper.cloneCol(cols, ci);
|
CTCol ciEnd = columnHelper.cloneCol(cols, ci);
|
||||||
int lastcolumn = Math.toIntExact(ciMax);
|
int lastcolumn = Math.toIntExact(ciMax);
|
||||||
|
|
||||||
ci.setMax(targetColumnIx - 1);
|
ci.setMax(targetColumnIx - 1L);
|
||||||
|
|
||||||
ciMid.setMin(targetColumnIx);
|
ciMid.setMin(targetColumnIx);
|
||||||
ciMid.setMax(targetColumnIx);
|
ciMid.setMax(targetColumnIx);
|
||||||
unsetCollapsed(collapsed, ciMid);
|
unsetCollapsed(collapsed, ciMid);
|
||||||
this.columnHelper.addCleanColIntoCols(cols, ciMid);
|
this.columnHelper.addCleanColIntoCols(cols, ciMid);
|
||||||
|
|
||||||
ciEnd.setMin(targetColumnIx + 1);
|
ciEnd.setMin(targetColumnIx + 1L);
|
||||||
ciEnd.setMax(lastcolumn);
|
ciEnd.setMax(lastcolumn);
|
||||||
this.columnHelper.addCleanColIntoCols(cols, ciEnd);
|
this.columnHelper.addCleanColIntoCols(cols, ciEnd);
|
||||||
}
|
}
|
||||||
@ -4069,7 +4027,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
|
|||||||
int currentCount = dataValidations.sizeOfDataValidationArray();
|
int currentCount = dataValidations.sizeOfDataValidationArray();
|
||||||
CTDataValidation newval = dataValidations.addNewDataValidation();
|
CTDataValidation newval = dataValidations.addNewDataValidation();
|
||||||
newval.set(xssfDataValidation.getCtDdataValidation());
|
newval.set(xssfDataValidation.getCtDdataValidation());
|
||||||
dataValidations.setCount(currentCount + 1);
|
dataValidations.setCount(currentCount + 1L);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,7 +152,7 @@ public class XWPFNumbering extends POIXMLDocumentPart {
|
|||||||
CTNum ctNum = this.ctNumbering.addNewNum();
|
CTNum ctNum = this.ctNumbering.addNewNum();
|
||||||
ctNum.addNewAbstractNumId();
|
ctNum.addNewAbstractNumId();
|
||||||
ctNum.getAbstractNumId().setVal(abstractNumID);
|
ctNum.getAbstractNumId().setVal(abstractNumID);
|
||||||
ctNum.setNumId(BigInteger.valueOf(nums.size() + 1));
|
ctNum.setNumId(BigInteger.valueOf(nums.size() + 1L));
|
||||||
XWPFNum num = new XWPFNum(ctNum, this);
|
XWPFNum num = new XWPFNum(ctNum, this);
|
||||||
nums.add(num);
|
nums.add(num);
|
||||||
return ctNum.getNumId();
|
return ctNum.getNumId();
|
||||||
|
@ -26,7 +26,6 @@ import java.io.InputStream;
|
|||||||
import javax.crypto.spec.SecretKeySpec;
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
|
||||||
import org.apache.poi.hssf.record.crypto.Biff8DecryptingStream;
|
import org.apache.poi.hssf.record.crypto.Biff8DecryptingStream;
|
||||||
import org.apache.poi.util.HexDump;
|
|
||||||
import org.apache.poi.util.HexRead;
|
import org.apache.poi.util.HexRead;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
@ -87,15 +86,15 @@ public final class TestBiff8DecryptingStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void confirmByte(int expVal) {
|
public void confirmByte(int expVal) {
|
||||||
assertEquals(HexDump.byteToHex(expVal), HexDump.byteToHex(_bds.readUByte()));
|
assertEquals(expVal, _bds.readUByte());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void confirmShort(int expVal) {
|
public void confirmShort(int expVal) {
|
||||||
assertEquals(HexDump.shortToHex(expVal), HexDump.shortToHex(_bds.readShort()));
|
assertEquals((short)expVal, _bds.readShort());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void confirmUShort(int expVal) {
|
public void confirmUShort(int expVal) {
|
||||||
assertEquals(HexDump.shortToHex(expVal), HexDump.shortToHex(_bds.readUShort()));
|
assertEquals(expVal, _bds.readUShort());
|
||||||
}
|
}
|
||||||
|
|
||||||
public short readShort() {
|
public short readShort() {
|
||||||
@ -107,11 +106,11 @@ public final class TestBiff8DecryptingStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void confirmInt(int expVal) {
|
public void confirmInt(int expVal) {
|
||||||
assertEquals(HexDump.intToHex(expVal), HexDump.intToHex(_bds.readInt()));
|
assertEquals(expVal, _bds.readInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void confirmLong(long expVal) {
|
public void confirmLong(long expVal) {
|
||||||
assertEquals(HexDump.longToHex(expVal), HexDump.longToHex(_bds.readLong()));
|
assertEquals(expVal, _bds.readLong());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void confirmData(String expHexData) {
|
public void confirmData(String expHexData) {
|
||||||
|
@ -19,11 +19,9 @@ package org.apache.poi.poifs.storage;
|
|||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
import java.util.zip.GZIPInputStream;
|
import java.util.zip.GZIPInputStream;
|
||||||
|
|
||||||
import org.apache.poi.util.HexDump;
|
|
||||||
import org.apache.poi.util.HexRead;
|
import org.apache.poi.util.HexRead;
|
||||||
import org.apache.poi.util.IOUtils;
|
import org.apache.poi.util.IOUtils;
|
||||||
|
|
||||||
@ -31,11 +29,11 @@ import org.apache.poi.util.IOUtils;
|
|||||||
* Test utility class.<br>
|
* Test utility class.<br>
|
||||||
*
|
*
|
||||||
* Creates raw <code>byte[]</code> data from hex-dump String arrays.
|
* Creates raw <code>byte[]</code> data from hex-dump String arrays.
|
||||||
*
|
|
||||||
* @author Josh Micich
|
|
||||||
*/
|
*/
|
||||||
public final class RawDataUtil {
|
public final class RawDataUtil {
|
||||||
|
|
||||||
|
private RawDataUtil() {}
|
||||||
|
|
||||||
public static byte[] decode(String[] hexDataLines) {
|
public static byte[] decode(String[] hexDataLines) {
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(hexDataLines.length * 32 + 32);
|
ByteArrayOutputStream baos = new ByteArrayOutputStream(hexDataLines.length * 32 + 32);
|
||||||
|
|
||||||
@ -46,47 +44,6 @@ public final class RawDataUtil {
|
|||||||
return baos.toByteArray();
|
return baos.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Development time utility method.<br>
|
|
||||||
* Transforms a byte array into hex-dump String lines in java source code format.
|
|
||||||
*/
|
|
||||||
public static void dumpData(byte[] data) {
|
|
||||||
int i=0;
|
|
||||||
System.out.println("String[] hexDataLines = {");
|
|
||||||
System.out.print("\t\"");
|
|
||||||
while(true) {
|
|
||||||
System.out.print(HexDump.byteToHex(data[i]).substring(2));
|
|
||||||
i++;
|
|
||||||
if (i>=data.length) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (i % 32 == 0) {
|
|
||||||
System.out.println("\",");
|
|
||||||
System.out.print("\t\"");
|
|
||||||
} else {
|
|
||||||
System.out.print(" ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
System.out.println("\",");
|
|
||||||
System.out.println("};");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Development time utility method.<br>
|
|
||||||
* Confirms that the specified byte array is equivalent to the hex-dump String lines.
|
|
||||||
*/
|
|
||||||
public static void confirmEqual(byte[] expected, String[] hexDataLines) {
|
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(hexDataLines.length * 32 + 32);
|
|
||||||
|
|
||||||
for (String hexDataLine : hexDataLines) {
|
|
||||||
byte[] lineData = HexRead.readFromString(hexDataLine);
|
|
||||||
baos.write(lineData, 0, lineData.length);
|
|
||||||
}
|
|
||||||
if (!Arrays.equals(expected, baos.toByteArray())) {
|
|
||||||
throw new RuntimeException("different");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decompress previously gziped/base64ed data
|
* Decompress previously gziped/base64ed data
|
||||||
*
|
*
|
||||||
@ -98,7 +55,7 @@ public final class RawDataUtil {
|
|||||||
byte[] base64Bytes = Base64.getDecoder().decode(data);
|
byte[] base64Bytes = Base64.getDecoder().decode(data);
|
||||||
return IOUtils.toByteArray(new GZIPInputStream(new ByteArrayInputStream(base64Bytes)));
|
return IOUtils.toByteArray(new GZIPInputStream(new ByteArrayInputStream(base64Bytes)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compress raw data for test runs - usually called while debugging :)
|
* Compress raw data for test runs - usually called while debugging :)
|
||||||
*
|
*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user