- 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-ffa450edef68tags/before_ooxml_3rd_edition
@@ -25,6 +25,7 @@ import java.nio.file.Paths; | |||
import java.security.GeneralSecurityException; | |||
import java.util.Optional; | |||
import java.util.function.Predicate; | |||
import java.util.stream.Stream; | |||
import org.apache.poi.poifs.crypt.Decryptor; | |||
import org.apache.poi.poifs.crypt.EncryptionInfo; | |||
@@ -50,7 +51,8 @@ public final class OOXMLPasswordsTry { | |||
System.err.println(" OOXMLPasswordsTry <file.ooxml> <wordlist>"); | |||
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(); | |||
@@ -61,7 +63,7 @@ public final class OOXMLPasswordsTry { | |||
final long start = System.currentTimeMillis(); | |||
final int[] count = { 0 }; | |||
Predicate<String> counter = (s) -> { | |||
Predicate<String> counter = s -> { | |||
if (++count[0] % 1000 == 0) { | |||
int secs = (int) ((System.currentTimeMillis() - start) / 1000); | |||
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 | |||
Optional<String> found = Files.lines(Paths.get(words)).filter(counter).filter(w -> isValid(d, w)).findFirst(); | |||
System.out.println(found.map(s -> "Password found: " + s).orElse("Error - No password matched")); | |||
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")); | |||
} | |||
} | |||
} | |||
@@ -17,33 +17,27 @@ | |||
package org.apache.poi.hpsf.examples; | |||
import java.io.ByteArrayInputStream; | |||
import java.io.File; | |||
import java.io.FileOutputStream; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.io.OutputStream; | |||
import java.io.UnsupportedEncodingException; | |||
import java.util.HashMap; | |||
import java.util.Map; | |||
import org.apache.poi.hpsf.DocumentSummaryInformation; | |||
import org.apache.poi.hpsf.HPSFException; | |||
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.PropertySetFactory; | |||
import org.apache.poi.hpsf.SummaryInformation; | |||
import org.apache.poi.hpsf.UnexpectedPropertySetTypeException; | |||
import org.apache.poi.hpsf.WritingNotSupportedException; | |||
import org.apache.poi.poifs.eventfilesystem.POIFSReader; | |||
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.DocumentInputStream; | |||
import org.apache.poi.poifs.filesystem.EntryUtils; | |||
import org.apache.poi.poifs.filesystem.POIFSDocumentPath; | |||
import org.apache.poi.poifs.filesystem.POIFSFileSystem; | |||
import org.apache.poi.util.IOUtils; | |||
import org.apache.poi.util.TempFile; | |||
/** | |||
@@ -89,7 +83,7 @@ public final class CopyCompare { | |||
String originalFileName = null; | |||
String copyFileName = null; | |||
/* Check the command-line arguments. */ | |||
// Check the command-line arguments. | |||
if (args.length == 1) { | |||
originalFileName = args[0]; | |||
File f = TempFile.createTempFile("CopyOfPOIFileSystem-", ".ole2"); | |||
@@ -99,25 +93,26 @@ public final class CopyCompare { | |||
originalFileName = args[0]; | |||
copyFileName = args[1]; | |||
} else { | |||
System.err.println("Usage: " + CopyCompare.class.getName() + | |||
"originPOIFS [copyPOIFS]"); | |||
System.err.println("Usage: CopyCompare originPOIFS [copyPOIFS]"); | |||
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 CopyFile cf = new CopyFile(copyFileName); | |||
r.registerListener(cf); | |||
r.setNotifyEmptyDirectories(true); | |||
try (final POIFSFileSystem poiFs = new POIFSFileSystem(); | |||
OutputStream fos = new FileOutputStream(copyFileName)) { | |||
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. */ | |||
cf.close(); | |||
// Write the new POIFS to disk. | |||
poiFs.writeFilesystem(fos); | |||
} | |||
/* Read all documents from the original POI file system and compare them | |||
* with the equivalent document from the copy. */ | |||
// Read all documents from the original POI file system and compare them with | |||
// the equivalent document from the copy. | |||
try (POIFSFileSystem opfs = new POIFSFileSystem(new File(originalFileName)); | |||
POIFSFileSystem cpfs = new POIFSFileSystem(new File(copyFileName))) { | |||
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 | |||
* #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> | |||
* The method is called by POI's eventing API for each file in the origin POIFS. | |||
*/ | |||
static class CopyFile implements POIFSReaderListener { | |||
private final String dstName; | |||
private final POIFSFileSystem poiFs; | |||
/** | |||
* <p>The constructor of a {@link CopyFile} instance creates the target | |||
* POIFS. It also stores the name of the file the POIFS will be written | |||
* to once it is complete.</p> | |||
* | |||
* @param dstName The name of the disk file the destination POIFS is to | |||
* be written to. | |||
*/ | |||
CopyFile(final String dstName) { | |||
this.dstName = dstName; | |||
poiFs = new POIFSFileSystem(); | |||
} | |||
public static void handleEvent(final POIFSFileSystem poiFs, final POIFSReaderEvent event) { | |||
// The following declarations are shortcuts for accessing the "event" object. | |||
final DocumentInputStream stream = event.getStream(); | |||
/** | |||
* <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(); | |||
try { | |||
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); | |||
} | |||
} | |||
// Find out whether the current document is a property set stream or not. | |||
InputStreamSupplier su; | |||
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); | |||
/** | |||
* 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 { | |||
// Copy the property set to the destination POI file system. | |||
final PropertySet mps; | |||
if (ps instanceof DocumentSummaryInformation) { | |||
mps = new DocumentSummaryInformation(ps); | |||
} else if (ps instanceof SummaryInformation) { | |||
@@ -221,112 +150,32 @@ public final class CopyCompare { | |||
} else { | |||
mps = new PropertySet(ps); | |||
} | |||
} catch (UnexpectedPropertySetTypeException e) { | |||
throw new IOException(e); | |||
} | |||
de.createDocument(name, mps.toInputStream()); | |||
} | |||
/** | |||
* Copies the bytes from a {@link DocumentInputStream} to a new | |||
* stream in a POI filesystem. | |||
* | |||
* @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)); | |||
su = mps::toInputStream; | |||
} else { | |||
// No, the current document is not a property set stream. | |||
// We copy it unmodified to the destination POIFS. | |||
su = event::getStream; | |||
} | |||
} | |||
try (InputStream is = su.get()) { | |||
final POIFSDocumentPath path = event.getPath(); | |||
/** | |||
* Writes the POI file system to a disk file. | |||
*/ | |||
public void close() throws IOException { | |||
try (OutputStream fos = new FileOutputStream(dstName)) { | |||
poiFs.writeFilesystem(fos); | |||
} | |||
} | |||
// Ensures that the directory hierarchy for a document in a POI fileystem is in place. | |||
// Get the root directory. It does not have to be created since it always exists in a POIFS. | |||
DirectoryEntry de = poiFs.getRoot(); | |||
/** | |||
* 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; | |||
for (int i=0; i<path.length(); i++) { | |||
String subDir = path.getComponent(i); | |||
de = (de.hasEntry(subDir)) ? (DirectoryEntry)de.getEntry(subDir) : de.createDirectory(subDir); | |||
} | |||
/* No: We have to create the directory - or return the root's | |||
* 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); | |||
de.createDocument(event.getName(), is); | |||
} | |||
} 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.util.List; | |||
import org.apache.poi.hpsf.HPSFRuntimeException; | |||
import org.apache.poi.hpsf.NoPropertySetStreamException; | |||
import org.apache.poi.hpsf.Property; | |||
import org.apache.poi.hpsf.PropertySet; | |||
@@ -65,7 +66,7 @@ public final class ReadCustomPropertySets { | |||
out("No property set stream: \"" + streamName + "\""); | |||
return; | |||
} 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: */ |
@@ -93,7 +93,8 @@ public final class WriteAuthorAndTitle { | |||
} | |||
/* 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 | |||
* in the class ModifySICopyTheRest which is registered here as a | |||
@@ -101,7 +102,7 @@ public final class WriteAuthorAndTitle { | |||
try (POIFSFileSystem poifs = new POIFSFileSystem(); | |||
OutputStream out = new FileOutputStream(dstName)) { | |||
final POIFSReader r = new POIFSReader(); | |||
r.registerListener((e) -> handleEvent(poifs, e)); | |||
r.registerListener(e -> handleEvent(poifs, e)); | |||
r.read(new File(srcName)); | |||
/* Write the new POIFS to disk. */ |
@@ -392,7 +392,8 @@ public final class ApacheconEU08 { | |||
Graphics2D graphics = new SLGraphics(group); | |||
//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)); | |||
for (int i = 0, idx = 1; i < def.length; i+=2, idx++) { | |||
graphics.setColor(Color.black); |
@@ -60,42 +60,40 @@ public final class DataExtraction { | |||
handleSound(aSound); | |||
} | |||
int oleIdx = -1, picIdx = -1; | |||
int oleIdx = -1; | |||
int picIdx = -1; | |||
for (HSLFSlide slide : ppt.getSlides()) { | |||
//extract embedded OLE documents | |||
for (HSLFShape shape : slide.getShapes()) { | |||
if (shape instanceof HSLFObjectShape) { | |||
oleIdx++; | |||
HSLFObjectShape ole = (HSLFObjectShape) shape; | |||
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; | |||
} | |||
} | |||
//Pictures | |||
else if (shape instanceof HSLFPictureShape) { | |||
picIdx++; | |||
HSLFPictureShape p = (HSLFPictureShape) shape; | |||
HSLFPictureData data = p.getPictureData(); | |||
handlePicture(data, picIdx); | |||
handleShape((HSLFObjectShape) shape, ++oleIdx); | |||
} else if (shape instanceof HSLFPictureShape) { | |||
handlePicture((HSLFPictureShape) shape, ++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 { | |||
try (InputStream is = data.getInputStream(); | |||
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; | |||
try (FileOutputStream out = new FileOutputStream("pict-" + picIdx + ext)) { | |||
out.write(data.getData()); |
@@ -42,7 +42,7 @@ public final class Graphics2DDemo { | |||
try (HSLFSlideShow ppt = new HSLFSlideShow(); | |||
FileOutputStream out = new FileOutputStream("hslf-graphics.ppt")) { | |||
//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.green, 60, | |||
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 | |||
* a text file from available chunks and a directory that contains | |||
* attachments. | |||
* | |||
* @author Bruno Girin | |||
*/ | |||
@SuppressWarnings({"java:S106","java:S4823"}) | |||
public class Msg2txt { | |||
/** | |||
* The stem used to create file names for the text file and the directory | |||
* that contains the attachments. | |||
*/ | |||
private String fileNameStem; | |||
/** | |||
* The Outlook MSG file being processed. | |||
*/ | |||
private MAPIMessage msg; | |||
public Msg2txt(String fileName) throws IOException { | |||
fileNameStem = fileName; | |||
if(fileNameStem.endsWith(".msg") || fileNameStem.endsWith(".MSG")) { | |||
@@ -54,10 +53,10 @@ public class Msg2txt { | |||
} | |||
msg = new MAPIMessage(fileName); | |||
} | |||
/** | |||
* Processes the message. | |||
* | |||
* | |||
* @throws IOException if an exception occurs while writing the message out | |||
*/ | |||
public void processMessage() throws IOException { | |||
@@ -114,7 +113,7 @@ public class Msg2txt { | |||
} | |||
} | |||
} | |||
/** | |||
* Processes a single attachment: reads it from the Outlook MSG file and | |||
* 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 | |||
* @throws IOException when any of the file operations fails | |||
*/ | |||
public void processAttachment(AttachmentChunks attachment, | |||
public void processAttachment(AttachmentChunks attachment, | |||
File dir) throws IOException { | |||
String fileName = attachment.getAttachFileName().toString(); | |||
if(attachment.getAttachLongFileName() != null) { | |||
fileName = attachment.getAttachLongFileName().toString(); | |||
} | |||
File f = new File(dir, fileName); | |||
try (OutputStream fileOut = new FileOutputStream(f)) { | |||
fileOut.write(attachment.getAttachData().getValue()); | |||
} | |||
} | |||
/** | |||
* Processes the list of arguments as a list of names of Outlook MSG files. | |||
* | |||
* | |||
* @param args the list of MSG files to process | |||
*/ | |||
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.NumberRecord; | |||
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.StringRecord; | |||
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. | |||
* @author Nick Burch | |||
*/ | |||
@SuppressWarnings({"java:S106","java:S4823"}) | |||
public class XLS2CSVmra implements HSSFListener { | |||
private int minColumns; | |||
private POIFSFileSystem fs; | |||
@@ -72,7 +72,7 @@ public class XLS2CSVmra implements HSSFListener { | |||
// Records we pick up as we process | |||
private SSTRecord sstRecord; | |||
private FormatTrackingHSSFListener formatListener; | |||
/** So we known which sheet we're on */ | |||
private int sheetIndex = -1; | |||
private BoundSheetRecord[] orderedBSRs; | |||
@@ -149,7 +149,7 @@ public class XLS2CSVmra implements HSSFListener { | |||
if(workbookBuildingListener != null && stubWorkbook == null) { | |||
stubWorkbook = workbookBuildingListener.getStubHSSFWorkbook(); | |||
} | |||
// Output the worksheet name | |||
// Works by ordering the BSRs by the location of | |||
// their BOFRecords, and then knowing that we | |||
@@ -159,7 +159,7 @@ public class XLS2CSVmra implements HSSFListener { | |||
orderedBSRs = BoundSheetRecord.orderByBofPosition(boundSheetRecords); | |||
} | |||
output.println(); | |||
output.println( | |||
output.println( | |||
orderedBSRs[sheetIndex].getSheetname() + | |||
" [" + (sheetIndex+1) + "]:" | |||
); |
@@ -18,873 +18,6 @@ | |||
package org.apache.poi.hssf.usermodel.examples; | |||
import java.io.File; | |||
import java.io.FileInputStream; | |||
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))); | |||
} | |||
} | |||
/* Placeholder - this is now handled in the Common SS example **/ | |||
public class AddDimensionedImage extends org.apache.poi.ss.examples.AddDimensionedImage { | |||
} |
@@ -96,7 +96,6 @@ public class BigExample { | |||
r.setHeight((short) 0x249); | |||
} | |||
//r.setRowNum(( short ) rownum); | |||
// create 50 cells (0-49) (the += 2 becomes apparent later | |||
for (int cellnum = 0; cellnum < 50; cellnum += 2) { | |||
// 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 | |||
*/ | |||
public class EmbeddedObjects { | |||
@SuppressWarnings({"java:S106","java:S4823"}) | |||
public final class EmbeddedObjects { | |||
private EmbeddedObjects() {} | |||
@SuppressWarnings("unused") | |||
public static void main(String[] args) throws Exception { | |||
try ( | |||
@@ -43,23 +46,28 @@ public class EmbeddedObjects { | |||
String oleName = obj.getOLE2ClassName(); | |||
DirectoryNode dn = (obj.hasDirectoryEntry()) ? (DirectoryNode) obj.getDirectory() : null; | |||
Closeable document = null; | |||
if (oleName.equals("Worksheet")) { | |||
document = new HSSFWorkbook(dn, fs, false); | |||
} else if (oleName.equals("Document")) { | |||
document = new HWPFDocument(dn); | |||
} else if (oleName.equals("Presentation")) { | |||
document = new HSLFSlideShow(dn); | |||
} else { | |||
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(); | |||
switch (oleName) { | |||
case "Worksheet": | |||
document = new HSSFWorkbook(dn, fs, false); | |||
break; | |||
case "Document": | |||
document = new HWPFDocument(dn); | |||
break; | |||
case "Presentation": | |||
document = new HSLFSlideShow(dn); | |||
break; | |||
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 { | |||
// There is no DirectoryEntry | |||
// Recover the object's data from the HSSFObjectData instance. | |||
byte[] objectData = obj.getObjectData(); | |||
} | |||
break; | |||
} | |||
if (document != null) { | |||
document.close(); |
@@ -15,22 +15,28 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.hssf.usermodel.examples; | |||
import java.io.FileInputStream; | |||
import java.io.IOException; | |||
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.*; | |||
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; | |||
import java.io.FileInputStream; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
/** | |||
* This example shows how to use the event API for reading a file. | |||
*/ | |||
@SuppressWarnings({"java:S106","java:S4823"}) | |||
public class EventExample implements HSSFListener { | |||
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 | |||
* users. | |||
*/ | |||
@SuppressWarnings({"java:S106","java:S4823"}) | |||
public final class HSSFReadWrite { | |||
private HSSFReadWrite() {} | |||
/** | |||
* creates an {@link HSSFWorkbook} with the specified OS filename. | |||
*/ |
@@ -42,11 +42,11 @@ public class Hyperlinks { | |||
//cell style for hyperlinks | |||
//by default hyperlinks are blue and underlined | |||
HSSFCellStyle hlink_style = wb.createCellStyle(); | |||
HSSFFont hlink_font = wb.createFont(); | |||
hlink_font.setUnderline(Font.U_SINGLE); | |||
hlink_font.setColor(HSSFColorPredefined.BLUE.getIndex()); | |||
hlink_style.setFont(hlink_font); | |||
HSSFCellStyle hlinkStyle = wb.createCellStyle(); | |||
HSSFFont hlinkFont = wb.createFont(); | |||
hlinkFont.setUnderline(Font.U_SINGLE); | |||
hlinkFont.setColor(HSSFColorPredefined.BLUE.getIndex()); | |||
hlinkStyle.setFont(hlinkFont); | |||
HSSFCell cell; | |||
HSSFSheet sheet = wb.createSheet("Hyperlinks"); | |||
@@ -57,7 +57,7 @@ public class Hyperlinks { | |||
HSSFHyperlink link = helper.createHyperlink(HyperlinkType.URL); | |||
link.setAddress("https://poi.apache.org/"); | |||
cell.setHyperlink(link); | |||
cell.setCellStyle(hlink_style); | |||
cell.setCellStyle(hlinkStyle); | |||
//link to a file in the current directory | |||
cell = sheet.createRow(1).createCell(0); | |||
@@ -65,7 +65,7 @@ public class Hyperlinks { | |||
link = helper.createHyperlink(HyperlinkType.FILE); | |||
link.setAddress("link1.xls"); | |||
cell.setHyperlink(link); | |||
cell.setCellStyle(hlink_style); | |||
cell.setCellStyle(hlinkStyle); | |||
//e-mail link | |||
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 | |||
link.setAddress("mailto:poi@apache.org?subject=Hyperlinks"); | |||
cell.setHyperlink(link); | |||
cell.setCellStyle(hlink_style); | |||
cell.setCellStyle(hlinkStyle); | |||
//link to a place in this workbook | |||
@@ -87,7 +87,7 @@ public class Hyperlinks { | |||
link = helper.createHyperlink(HyperlinkType.DOCUMENT); | |||
link.setAddress("'Target Sheet'!A1"); | |||
cell.setHyperlink(link); | |||
cell.setCellStyle(hlink_style); | |||
cell.setCellStyle(hlinkStyle); | |||
try (FileOutputStream out = new FileOutputStream("hssf-links.xls")) { | |||
wb.write(out); |
@@ -22,14 +22,15 @@ import java.io.File; | |||
import java.io.FileOutputStream; | |||
import java.io.IOException; | |||
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.HSSFCellStyle; | |||
import org.apache.poi.hssf.usermodel.HSSFDataFormat; | |||
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 | |||
@@ -48,6 +49,7 @@ import org.apache.poi.hssf.usermodel.HSSFRichTextString; | |||
* | |||
* @author Mark Beardsley [msb at apache.org] | |||
*/ | |||
@SuppressWarnings({"java:S106","java:S4823"}) | |||
public class InCellLists { | |||
// 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. | |||
row = sheet.createRow(1); | |||
cell = row.createCell(0); | |||
ArrayList<String> listItems = new ArrayList<>(); | |||
List<String> listItems = new ArrayList<>(); | |||
listItems.add("List Item One."); | |||
listItems.add("List Item Two."); | |||
listItems.add("List Item Three."); | |||
@@ -123,7 +125,7 @@ public class InCellLists { | |||
// to preserve order. | |||
row = sheet.createRow(4); | |||
cell = row.createCell(0); | |||
ArrayList<MultiLevelListItem> multiLevelListItems = new ArrayList<>(); | |||
List<MultiLevelListItem> multiLevelListItems = new ArrayList<>(); | |||
listItems = new ArrayList<>(); | |||
listItems.add("ML List Item One - Sub Item One."); | |||
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 | |||
* 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(); | |||
HSSFCellStyle wrapStyle = workbook.createCellStyle(); | |||
wrapStyle.setWrapText(true); | |||
@@ -242,7 +244,7 @@ public class InCellLists { | |||
* to calculate subsequent item numbers. | |||
*/ | |||
public void numberedListInCell(HSSFWorkbook workbook, | |||
ArrayList<String> listItems, | |||
List<String> listItems, | |||
HSSFCell cell, | |||
int startingValue, | |||
int increment) { | |||
@@ -278,7 +280,7 @@ public class InCellLists { | |||
* will be written. | |||
*/ | |||
public void bulletedListInCell(HSSFWorkbook workbook, | |||
ArrayList<String> listItems, | |||
List<String> listItems, | |||
HSSFCell cell) { | |||
StringBuilder buffer = new StringBuilder(); | |||
// Note that again, an HSSFCellStye object is required and that | |||
@@ -314,7 +316,7 @@ public class InCellLists { | |||
* will be written. | |||
*/ | |||
public void multiLevelListInCell(HSSFWorkbook workbook, | |||
ArrayList<MultiLevelListItem> multiLevelListItems, | |||
List<MultiLevelListItem> multiLevelListItems, | |||
HSSFCell cell) { | |||
StringBuilder buffer = new StringBuilder(); | |||
// Note that again, an HSSFCellStye object is required and that | |||
@@ -329,13 +331,14 @@ public class InCellLists { | |||
buffer.append("\n"); | |||
// and then an ArrayList whose elements encapsulate the text | |||
// for the lower level list items. | |||
ArrayList<String> lowerLevelItems = multiLevelListItem.getLowerLevelItems(); | |||
if(!(lowerLevelItems == null) && !(lowerLevelItems.isEmpty())) { | |||
for(String item : lowerLevelItems) { | |||
buffer.append(InCellLists.TAB); | |||
buffer.append(item); | |||
buffer.append("\n"); | |||
} | |||
List<String> lowerLevelItems = multiLevelListItem.getLowerLevelItems(); | |||
if (lowerLevelItems == null || lowerLevelItems.isEmpty()) { | |||
continue; | |||
} | |||
for(String item : lowerLevelItems) { | |||
buffer.append(InCellLists.TAB); | |||
buffer.append(item); | |||
buffer.append("\n"); | |||
} | |||
} | |||
// The StringBuilder's contents are the source for the contents | |||
@@ -371,7 +374,7 @@ public class InCellLists { | |||
* subsequent low level item. | |||
*/ | |||
public void multiLevelNumberedListInCell(HSSFWorkbook workbook, | |||
ArrayList<MultiLevelListItem> multiLevelListItems, | |||
List<MultiLevelListItem> multiLevelListItems, | |||
HSSFCell cell, | |||
int highLevelStartingValue, | |||
int highLevelIncrement, | |||
@@ -393,8 +396,8 @@ public class InCellLists { | |||
buffer.append("\n"); | |||
// and then an ArrayList whose elements encapsulate the text | |||
// for the lower level list items. | |||
ArrayList<String> lowerLevelItems = multiLevelListItem.getLowerLevelItems(); | |||
if(!(lowerLevelItems == null) && !(lowerLevelItems.isEmpty())) { | |||
List<String> lowerLevelItems = multiLevelListItem.getLowerLevelItems(); | |||
if(lowerLevelItems != null && !lowerLevelItems.isEmpty()) { | |||
int lowLevelItemNumber = lowLevelStartingValue; | |||
for(String item : lowerLevelItems) { | |||
buffer.append(InCellLists.TAB); | |||
@@ -431,7 +434,7 @@ public class InCellLists { | |||
* will be written. | |||
*/ | |||
public void multiLevelBulletedListInCell(HSSFWorkbook workbook, | |||
ArrayList<MultiLevelListItem> multiLevelListItems, | |||
List<MultiLevelListItem> multiLevelListItems, | |||
HSSFCell cell) { | |||
StringBuilder buffer = new StringBuilder(); | |||
// Note that again, an HSSFCellStye object is required and that | |||
@@ -448,8 +451,8 @@ public class InCellLists { | |||
buffer.append("\n"); | |||
// and then an ArrayList whose elements encapsulate the text | |||
// for the lower level list items. | |||
ArrayList<String> lowerLevelItems = multiLevelListItem.getLowerLevelItems(); | |||
if(!(lowerLevelItems == null) && !(lowerLevelItems.isEmpty())) { | |||
List<String> lowerLevelItems = multiLevelListItem.getLowerLevelItems(); | |||
if(lowerLevelItems != null && !lowerLevelItems.isEmpty()) { | |||
for(String item : lowerLevelItems) { | |||
buffer.append(InCellLists.TAB); | |||
buffer.append(InCellLists.BULLET_CHARACTER); | |||
@@ -498,7 +501,7 @@ public class InCellLists { | |||
public final class MultiLevelListItem { | |||
private String itemText; | |||
private ArrayList<String> lowerLevelItems; | |||
private List<String> lowerLevelItems; | |||
/** | |||
* Create a new instance of the MultiLevelListItem class using the | |||
@@ -510,7 +513,7 @@ public class InCellLists { | |||
* text for the associated lower level list | |||
* items. | |||
*/ | |||
public MultiLevelListItem(String itemText, ArrayList<String> lowerLevelItems) { | |||
public MultiLevelListItem(String itemText, List<String> lowerLevelItems) { | |||
this.itemText = itemText; | |||
this.lowerLevelItems = lowerLevelItems; | |||
} | |||
@@ -531,8 +534,8 @@ public class InCellLists { | |||
* @return An ArrayList whose elements each encapsulate the text for a | |||
* single associated lower level list item. | |||
*/ | |||
public ArrayList<String> getLowerLevelItems() { | |||
return(this.lowerLevelItems); | |||
public List<String> getLowerLevelItems() { | |||
return lowerLevelItems; | |||
} | |||
} | |||
} |
@@ -36,7 +36,7 @@ public class ClipboardData { | |||
public void read( LittleEndianByteArrayInputStream lei ) { | |||
int offset = lei.getReadIndex(); | |||
int size = lei.readInt(); | |||
long size = lei.readInt(); | |||
if ( size < 4 ) { | |||
String msg = |
@@ -417,7 +417,7 @@ public class Property { | |||
// skip length field | |||
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); | |||
} | |||
} else if (value instanceof byte[]) { |
@@ -265,7 +265,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord { | |||
// 2 bytes reserved | |||
in.readUShort(); | |||
} else { | |||
int len = readFormatOptions(in); | |||
long len = readFormatOptions(in); | |||
if (len < ext_formatting_length) { | |||
ext_formatting_data = IOUtils.safelyAllocate(ext_formatting_length-len, MAX_RECORD_LENGTH); | |||
in.readFully(ext_formatting_data); |
@@ -40,11 +40,11 @@ public final class DocumentOutputStream extends OutputStream { | |||
private POIFSDocument _document; | |||
/** and its Property */ | |||
private DocumentProperty _property; | |||
/** our buffer, when null we're into normal blocks */ | |||
private ByteArrayOutputStream _buffer = | |||
private ByteArrayOutputStream _buffer = | |||
new ByteArrayOutputStream(POIFSConstants.BIG_BLOCK_MINIMUM_DOCUMENT_SIZE); | |||
/** our main block stream, when we're into normal blocks */ | |||
private POIFSStream _stream; | |||
private OutputStream _stream_output; | |||
@@ -56,7 +56,7 @@ public final class DocumentOutputStream extends OutputStream { | |||
/** | |||
* Create an OutputStream from the specified DocumentEntry. | |||
* The specified entry will be emptied. | |||
* | |||
* | |||
* @param document the DocumentEntry to be written | |||
*/ | |||
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 | |||
* | |||
* | |||
* @param parent Where to create the Entry | |||
* @param name Name of the new entry | |||
*/ | |||
@@ -159,7 +159,7 @@ public final class DocumentOutputStream extends OutputStream { | |||
_property.updateSize(_document_size); | |||
_property.setStartBlock(_stream.getStartBlock()); | |||
} | |||
// No more! | |||
_closed = true; | |||
} | |||
@@ -168,6 +168,6 @@ public final class DocumentOutputStream extends OutputStream { | |||
* @return the amount of written bytes | |||
*/ | |||
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 ... | |||
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); | |||
if (i == gradientSteps-1) { | |||
graphics.fill(shape); |
@@ -270,7 +270,7 @@ final class YearFracCalculator { | |||
for (int i=startYear; i<=endYear; i++) { | |||
dayCount += isLeapYear(i) ? DAYS_PER_LEAP_YEAR : DAYS_PER_NORMAL_YEAR; | |||
} | |||
double numberOfYears = endYear-startYear+1; | |||
double numberOfYears = endYear-startYear+1.; | |||
return dayCount / numberOfYears; | |||
} | |||
@@ -17,9 +17,7 @@ | |||
package org.apache.poi.ss.formula.functions; | |||
/** | |||
* <p>Some utils for converting from and to any base<p> | |||
* | |||
* @author cedric dot walter @ gmail dot com | |||
* Some utils for converting from and to any base | |||
*/ | |||
public class BaseNumberUtils { | |||
@@ -43,11 +41,11 @@ public class BaseNumberUtils { | |||
long digit; | |||
if ('0' <= character && character <= '9') { | |||
digit = character - '0'; | |||
digit = (long)character - '0'; | |||
} else if ('A' <= character && character <= 'Z') { | |||
digit = 10 + (character - 'A'); | |||
digit = 10L + (character - 'A'); | |||
} else if ('a' <= character && character <= 'z') { | |||
digit = 10 + (character - 'a'); | |||
digit = 10L + (character - 'a'); | |||
} else { | |||
digit = base; | |||
} |
@@ -26,7 +26,7 @@ import org.apache.poi.ss.formula.eval.ValueEval; | |||
public final class Column implements Function0Arg, Function1Arg { | |||
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) { | |||
int rnum; | |||
@@ -40,14 +40,14 @@ public final class Column implements Function0Arg, Function1Arg { | |||
return ErrorEval.VALUE_INVALID; | |||
} | |||
return new NumberEval(rnum + 1); | |||
return new NumberEval(rnum + 1.); | |||
} | |||
public ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) { | |||
switch (args.length) { | |||
case 1: | |||
return evaluate(srcRowIndex, srcColumnIndex, args[0]); | |||
case 0: | |||
return new NumberEval(srcColumnIndex+1); | |||
return new NumberEval(srcColumnIndex+1.); | |||
} | |||
return ErrorEval.VALUE_INVALID; | |||
} |
@@ -95,7 +95,7 @@ public final class Match extends Var2or3ArgFunction { | |||
ValueEval lookupValue = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex); | |||
ValueVector lookupRange = evaluateLookupRange(arg1); | |||
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) { | |||
return e.getErrorEval(); | |||
} |
@@ -85,7 +85,7 @@ public class Mirr extends MultiOperandNumericFunction { | |||
private static double mirr(double[] in, double financeRate, double reinvestRate) { | |||
double value = 0; | |||
int numOfYears = in.length - 1; | |||
double numOfYears = in.length - 1; | |||
double pv = 0; | |||
double fv = 0; | |||
@@ -25,13 +25,11 @@ import org.apache.poi.ss.formula.eval.ValueEval; | |||
/** | |||
* Implementation for the Excel function ROW | |||
* | |||
* @author Josh Micich | |||
*/ | |||
public final class RowFunc implements Function0Arg, Function1Arg { | |||
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) { | |||
int rnum; | |||
@@ -45,14 +43,14 @@ public final class RowFunc implements Function0Arg, Function1Arg { | |||
return ErrorEval.VALUE_INVALID; | |||
} | |||
return new NumberEval(rnum + 1); | |||
return new NumberEval(rnum + 1.); | |||
} | |||
public ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) { | |||
switch (args.length) { | |||
case 1: | |||
return evaluate(srcRowIndex, srcColumnIndex, args[0]); | |||
case 0: | |||
return new NumberEval(srcRowIndex+1); | |||
return new NumberEval(srcRowIndex+1.); | |||
} | |||
return ErrorEval.VALUE_INVALID; | |||
} |
@@ -17,11 +17,17 @@ | |||
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 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 Josh Micich | |||
@@ -38,7 +44,7 @@ public abstract class TextFunction implements Function { | |||
ValueEval ve = OperandResolver.getSingleValue(arg, srcCellRow, srcCellCol); | |||
return OperandResolver.coerceValueToInt(ve); | |||
} | |||
protected static double evaluateDoubleArg(ValueEval arg, int srcCellRow, int srcCellCol) throws EvaluationException { | |||
ValueEval ve = OperandResolver.getSingleValue(arg, srcCellRow, srcCellCol); | |||
return OperandResolver.coerceValueToDouble(ve); | |||
@@ -112,7 +118,7 @@ public abstract class TextFunction implements Function { | |||
* Implementation of the PROPER function: | |||
* Normalizes all words (separated by non-word characters) by | |||
* making the first letter upper and the rest lower case. | |||
* | |||
* | |||
* This is nearly equivalent to toTitleCase if the Java language had it | |||
*/ | |||
public static final Function PROPER = new SingleArgTextFunc() { | |||
@@ -147,7 +153,7 @@ public abstract class TextFunction implements Function { | |||
return new StringEval(arg.trim()); | |||
} | |||
}; | |||
/** | |||
* An implementation of the CLEAN function: | |||
* 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) { | |||
return e.getErrorEval(); | |||
} | |||
if(index < 0) { | |||
return ErrorEval.VALUE_INVALID; | |||
} | |||
String result; | |||
if (_isLeft) { | |||
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> | |||
* 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 | |||
* 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 | |||
* 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> | |||
*/ | |||
@@ -314,7 +320,7 @@ public abstract class TextFunction implements Function { | |||
} catch (EvaluationException e) { | |||
return e.getErrorEval(); | |||
} | |||
try { | |||
// Ask DataFormatter to handle the String for us | |||
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 final boolean _isCaseSensitive; | |||
@@ -367,7 +373,7 @@ public abstract class TextFunction implements Function { | |||
if (result == -1) { | |||
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; | |||
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.eval.AreaEval; | |||
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.RefEval; | |||
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> | |||
* | |||
* | |||
* Syntax:<br> | |||
* TREND(known_y's, known_x's, new_x's, constant) | |||
* <table border="0" cellpadding="1" cellspacing="0" summary="Parameter descriptions"> | |||
@@ -131,14 +131,14 @@ public final class Trend implements Function { | |||
} else { | |||
throw new EvaluationException(ErrorEval.VALUE_INVALID); | |||
} | |||
return ar; | |||
} | |||
private static double[][] getDefaultArrayOneD(int w) { | |||
double[][] array = new double[w][1]; | |||
for (int i = 0; i < w; i++) { | |||
array[i][0] = i + 1; | |||
array[i][0] = i + 1.; | |||
} | |||
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) { | |||
newX = switchRowsColumns(newXOrig); | |||
} | |||
if (newX[0].length != x[0].length) { | |||
throw new EvaluationException(ErrorEval.REF_INVALID); | |||
} | |||
if (x[0].length >= x.length) { | |||
/* See comment at top of file */ | |||
throw new NotImplementedException("Sample size too small"); |
@@ -114,9 +114,11 @@ public final class WeekdayFunc implements Function { | |||
} else if (returnOption == 3) { | |||
result = (weekday + 6 - 1) % 7; | |||
} 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 { | |||
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); |
@@ -428,7 +428,7 @@ public class DateUtil { | |||
} | |||
LocalDateTime ldt = LocalDateTime.of(startYear, 1, 1, 0, 0); | |||
ldt = ldt.plusDays(wholeDays+dayAdjust-1); | |||
ldt = ldt.plusDays(wholeDays+dayAdjust-1L); | |||
long nanosTime = | |||
bd.subtract(BigDecimal.valueOf(wholeDays)) |
@@ -128,7 +128,7 @@ public abstract class LZWDecompresser { | |||
// These are bytes as looked up in the dictionary | |||
// It needs to be signed, as it'll get passed on to | |||
// 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 | |||
// It needs to be unsigned, so that bit stuff works | |||
int dataI; |
@@ -17,14 +17,14 @@ | |||
package org.apache.poi.util; | |||
import java.io.ByteArrayInputStream; | |||
import java.io.ByteArrayOutputStream; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
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 | |||
* 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. | |||
* | |||
* | |||
* @param in The stream to wrap with the RLE Decompression | |||
* @throws IOException | |||
*/ | |||
@@ -131,7 +131,7 @@ public class RLEDecompressingInputStream extends InputStream { | |||
return -1; | |||
} | |||
} | |||
int c = (int) Math.min(n, len - pos); | |||
int c = (int) Math.min(n, len - (long)pos); | |||
pos += c; | |||
length -= c; | |||
} | |||
@@ -150,7 +150,7 @@ public class RLEDecompressingInputStream extends 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. | |||
* @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. | |||
* | |||
* | |||
* @param offset | |||
* @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. | |||
* | |||
* | |||
* @return short value from the stream, -1 if end of stream is reached | |||
* @throws IOException | |||
*/ | |||
@@ -240,7 +240,7 @@ public class RLEDecompressingInputStream extends InputStream { | |||
/** | |||
* 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 | |||
* @throws IOException | |||
*/ | |||
@@ -279,7 +279,7 @@ public class RLEDecompressingInputStream extends InputStream { | |||
public static byte[] decompress(byte[] compressed) throws IOException { | |||
return decompress(compressed, 0, compressed.length); | |||
} | |||
public static byte[] decompress(byte[] compressed, int offset, int length) throws IOException { | |||
ByteArrayOutputStream out = new ByteArrayOutputStream(); | |||
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.Rectangle2D; | |||
import com.microsoft.schemas.office.visio.x2012.main.PageType; | |||
import org.apache.poi.ooxml.POIXMLException; | |||
import org.apache.poi.util.Internal; | |||
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 | |||
*/ | |||
@@ -69,7 +68,7 @@ public class XDGFPage { | |||
} | |||
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 | |||
@Removal(version = "4.2") | |||
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); | |||
if (axis.size() == 1) { | |||
ChartAxis ax = axis.get(0); | |||
@@ -210,7 +210,7 @@ public final class XSSFChart extends XDDFChart implements Chart, ChartAxisFactor | |||
@Deprecated | |||
@Removal(version = "4.2") | |||
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); | |||
if (axis.size() == 1) { | |||
ChartAxis ax = axis.get(0); | |||
@@ -225,7 +225,7 @@ public final class XSSFChart extends XDDFChart implements Chart, ChartAxisFactor | |||
@Deprecated | |||
@Removal(version = "4.2") | |||
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); | |||
if (axis.size() == 1) { | |||
ChartAxis ax = axis.get(0); |
@@ -17,10 +17,10 @@ | |||
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.CTPositiveSize2D; | |||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D; | |||
import org.apache.poi.util.Internal; | |||
/** | |||
* @author Yegor Kozlov | |||
@@ -71,7 +71,7 @@ public final class XSSFChildAnchor extends XSSFAnchor { | |||
} | |||
public void setDy2(int dy2) { | |||
t2d.getExt().setCy(dy2 - getDy1()); | |||
t2d.getExt().setCy(dy2 - (long)getDy1()); | |||
} | |||
public int getDx2() { | |||
@@ -79,6 +79,6 @@ public final class XSSFChildAnchor extends XSSFAnchor { | |||
} | |||
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.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.ExcelNumberFormat; | |||
import org.apache.poi.ss.usermodel.IconMultiStateFormatting.IconSet; | |||
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 | |||
@@ -34,7 +52,7 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.*; | |||
public class XSSFConditionalFormattingRule implements ConditionalFormattingRule { | |||
private final CTCfRule _cfRule; | |||
private XSSFSheet _sh; | |||
private static Map<STCfType.Enum, ConditionType> typeLookup = new HashMap<>(); | |||
private static Map<STCfType.Enum, ConditionFilterType> filterTypeLookup = new HashMap<>(); | |||
static { | |||
@@ -43,7 +61,7 @@ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule | |||
typeLookup.put(STCfType.COLOR_SCALE, ConditionType.COLOR_SCALE); | |||
typeLookup.put(STCfType.DATA_BAR, ConditionType.DATA_BAR); | |||
typeLookup.put(STCfType.ICON_SET, ConditionType.ICON_SET); | |||
// These are all subtypes of Filter, we think... | |||
typeLookup.put(STCfType.TOP_10, 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.TIME_PERIOD, ConditionType.FILTER); | |||
typeLookup.put(STCfType.ABOVE_AVERAGE, ConditionType.FILTER); | |||
filterTypeLookup.put(STCfType.TOP_10, ConditionFilterType.TOP_10); | |||
filterTypeLookup.put(STCfType.UNIQUE_VALUES, ConditionFilterType.UNIQUE_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); | |||
} | |||
/** | |||
* NOTE: does not set priority, so this assumes the rule will not be added to the sheet yet | |||
* @param sh | |||
@@ -103,7 +121,7 @@ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule | |||
if(create && dxf == null) { | |||
dxf = CTDxf.Factory.newInstance(); | |||
int dxfId = styles.putDxf(dxf); | |||
_cfRule.setDxfId(dxfId - 1); | |||
_cfRule.setDxfId(dxfId - 1L); | |||
} | |||
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 | |||
return priority >=1 ? priority : 0; | |||
} | |||
public boolean getStopIfTrue() { | |||
return _cfRule.getStopIfTrue(); | |||
} | |||
/** | |||
* Create a new border formatting structure if it does not exist, | |||
* otherwise just return existing object. | |||
@@ -201,7 +219,7 @@ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule | |||
return new XSSFPatternFormatting(dxf.getFill(), _sh.getWorkbook().getStylesSource().getIndexedColors()); | |||
} | |||
/** | |||
* | |||
* @param color | |||
@@ -211,7 +229,7 @@ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule | |||
// Is it already there? | |||
if (_cfRule.isSetDataBar() && _cfRule.getType() == STCfType.DATA_BAR) | |||
return getDataBarFormatting(); | |||
// Mark it as being a Data Bar | |||
_cfRule.setType(STCfType.DATA_BAR); | |||
@@ -224,13 +242,13 @@ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule | |||
} | |||
// Set the color | |||
bar.setColor(color.getCTColor()); | |||
// Add the default thresholds | |||
CTCfvo min = bar.addNewCfvo(); | |||
min.setType(STCfvoType.Enum.forString(RangeType.MIN.name)); | |||
CTCfvo max = bar.addNewCfvo(); | |||
max.setType(STCfvoType.Enum.forString(RangeType.MAX.name)); | |||
// Wrap and return | |||
return new XSSFDataBarFormatting(bar, _sh.getWorkbook().getStylesSource().getIndexedColors()); | |||
} | |||
@@ -242,12 +260,12 @@ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule | |||
return null; | |||
} | |||
} | |||
public XSSFIconMultiStateFormatting createMultiStateFormatting(IconSet iconSet) { | |||
// Is it already there? | |||
if (_cfRule.isSetIconSet() && _cfRule.getType() == STCfType.ICON_SET) | |||
return getMultiStateFormatting(); | |||
// Mark it as being an Icon Set | |||
_cfRule.setType(STCfType.ICON_SET); | |||
@@ -263,7 +281,7 @@ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule | |||
STIconSetType.Enum xIconSet = STIconSetType.Enum.forString(iconSet.name); | |||
icons.setIconSet(xIconSet); | |||
} | |||
// Add a default set of thresholds | |||
int jump = 100 / iconSet.num; | |||
STCfvoType.Enum type = STCfvoType.Enum.forString(RangeType.PERCENT.name); | |||
@@ -272,7 +290,7 @@ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule | |||
cfvo.setType(type); | |||
cfvo.setVal(Integer.toString(i*jump)); | |||
} | |||
// Wrap and return | |||
return new XSSFIconMultiStateFormatting(icons); | |||
} | |||
@@ -284,12 +302,12 @@ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule | |||
return null; | |||
} | |||
} | |||
public XSSFColorScaleFormatting createColorScaleFormatting() { | |||
// Is it already there? | |||
if (_cfRule.isSetColorScale() && _cfRule.getType() == STCfType.COLOR_SCALE) | |||
return getColorScaleFormatting(); | |||
// Mark it as being a Color Scale | |||
_cfRule.setType(STCfType.COLOR_SCALE); | |||
@@ -300,7 +318,7 @@ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule | |||
} else { | |||
scale = _cfRule.addNewColorScale(); | |||
} | |||
// Add a default set of thresholds and colors | |||
if (scale.sizeOfCfvoArray() == 0) { | |||
CTCfvo cfvo; | |||
@@ -311,12 +329,12 @@ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule | |||
cfvo.setVal("50"); | |||
cfvo = scale.addNewCfvo(); | |||
cfvo.setType(STCfvoType.Enum.forString(RangeType.MAX.name)); | |||
for (int i=0; i<3; i++) { | |||
scale.addNewColor(); | |||
} | |||
} | |||
// Wrap and return | |||
return new XSSFColorScaleFormatting(scale, _sh.getWorkbook().getStylesSource().getIndexedColors()); | |||
} | |||
@@ -336,11 +354,11 @@ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule | |||
public ExcelNumberFormat getNumberFormat() { | |||
CTDxf dxf = getDxf(false); | |||
if(dxf == null || !dxf.isSetNumFmt()) return null; | |||
CTNumFmt numFmt = dxf.getNumFmt(); | |||
return new ExcelNumberFormat((int) numFmt.getNumFmtId(), numFmt.getFormatCode()); | |||
} | |||
/** | |||
* Type of conditional formatting rule. | |||
*/ | |||
@@ -356,11 +374,11 @@ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule | |||
public ConditionFilterType getConditionFilterType() { | |||
return filterTypeLookup.get(_cfRule.getType()); | |||
} | |||
public ConditionFilterData getFilterConfiguration() { | |||
return new XSSFConditionFilterData(_cfRule); | |||
} | |||
/** | |||
* The comparison function used when the type of conditional formatting is set to | |||
* {@link ConditionType#CELL_VALUE_IS} | |||
@@ -374,7 +392,7 @@ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule | |||
public byte getComparisonOperation(){ | |||
STConditionalFormattingOperator.Enum op = _cfRule.getOperator(); | |||
if(op == null) return ComparisonOperator.NO_COMPARISON; | |||
switch(op.intValue()){ | |||
case STConditionalFormattingOperator.INT_LESS_THAN: return ComparisonOperator.LT; | |||
case STConditionalFormattingOperator.INT_LESS_THAN_OR_EQUAL: return ComparisonOperator.LE; | |||
@@ -416,11 +434,11 @@ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule | |||
public String getFormula2(){ | |||
return _cfRule.sizeOfFormulaArray() == 2 ? _cfRule.getFormulaArray(1) : null; | |||
} | |||
public String getText() { | |||
return _cfRule.getText(); | |||
} | |||
/** | |||
* Conditional format rules don't define stripes, so always 0 | |||
* @see org.apache.poi.ss.usermodel.DifferentialStyleProvider#getStripeSize() |
@@ -583,7 +583,7 @@ public final class XSSFDrawing extends POIXMLDocumentPart implements Drawing<XSS | |||
} | |||
private long newShapeId() { | |||
return 1 + drawing.sizeOfAbsoluteAnchorArray() + drawing.sizeOfOneCellAnchorArray() + drawing | |||
return 1L + drawing.sizeOfAbsoluteAnchorArray() + drawing.sizeOfOneCellAnchorArray() + drawing | |||
.sizeOfTwoCellAnchorArray(); | |||
} | |||
@@ -423,7 +423,7 @@ public class XSSFRow implements Row, Comparable<XSSFRow> { | |||
throw new IllegalArgumentException("Invalid row number (" + rowIndex | |||
+ ") 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.XmlObject; | |||
import org.apache.xmlbeans.XmlOptions; | |||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTAutoFilter; | |||
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; | |||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.*; | |||
/** | |||
* 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) { | |||
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.setMax(lastIndex); //end column of the break | |||
// end column of the break | |||
brk.setMax(lastIndex); | |||
int nPageBreaks = ctPgBreak.sizeOfBrkArray(); | |||
ctPgBreak.setCount(nPageBreaks); | |||
@@ -2256,13 +2215,12 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { | |||
} | |||
if (ciMin == targetColumnIx || ciMax == targetColumnIx) { | |||
// The target column is at either end of the multi-column ColumnInfo | |||
// ci | |||
// The target column is at either end of the multi-column ColumnInfo ci | |||
// we'll just divide the info and create a new one | |||
if (ciMin == targetColumnIx) { | |||
ci.setMin(targetColumnIx + 1); | |||
ci.setMin(targetColumnIx + 1L); | |||
} else { | |||
ci.setMax(targetColumnIx - 1); | |||
ci.setMax(targetColumnIx - 1L); | |||
} | |||
CTCol nci = columnHelper.cloneCol(cols, ci); | |||
nci.setMin(targetColumnIx); | |||
@@ -2275,14 +2233,14 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { | |||
CTCol ciEnd = columnHelper.cloneCol(cols, ci); | |||
int lastcolumn = Math.toIntExact(ciMax); | |||
ci.setMax(targetColumnIx - 1); | |||
ci.setMax(targetColumnIx - 1L); | |||
ciMid.setMin(targetColumnIx); | |||
ciMid.setMax(targetColumnIx); | |||
unsetCollapsed(collapsed, ciMid); | |||
this.columnHelper.addCleanColIntoCols(cols, ciMid); | |||
ciEnd.setMin(targetColumnIx + 1); | |||
ciEnd.setMin(targetColumnIx + 1L); | |||
ciEnd.setMax(lastcolumn); | |||
this.columnHelper.addCleanColIntoCols(cols, ciEnd); | |||
} | |||
@@ -4069,7 +4027,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { | |||
int currentCount = dataValidations.sizeOfDataValidationArray(); | |||
CTDataValidation newval = dataValidations.addNewDataValidation(); | |||
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.addNewAbstractNumId(); | |||
ctNum.getAbstractNumId().setVal(abstractNumID); | |||
ctNum.setNumId(BigInteger.valueOf(nums.size() + 1)); | |||
ctNum.setNumId(BigInteger.valueOf(nums.size() + 1L)); | |||
XWPFNum num = new XWPFNum(ctNum, this); | |||
nums.add(num); | |||
return ctNum.getNumId(); |
@@ -26,7 +26,6 @@ import java.io.InputStream; | |||
import javax.crypto.spec.SecretKeySpec; | |||
import org.apache.poi.hssf.record.crypto.Biff8DecryptingStream; | |||
import org.apache.poi.util.HexDump; | |||
import org.apache.poi.util.HexRead; | |||
import org.junit.Test; | |||
@@ -87,15 +86,15 @@ public final class TestBiff8DecryptingStream { | |||
} | |||
public void confirmByte(int expVal) { | |||
assertEquals(HexDump.byteToHex(expVal), HexDump.byteToHex(_bds.readUByte())); | |||
assertEquals(expVal, _bds.readUByte()); | |||
} | |||
public void confirmShort(int expVal) { | |||
assertEquals(HexDump.shortToHex(expVal), HexDump.shortToHex(_bds.readShort())); | |||
assertEquals((short)expVal, _bds.readShort()); | |||
} | |||
public void confirmUShort(int expVal) { | |||
assertEquals(HexDump.shortToHex(expVal), HexDump.shortToHex(_bds.readUShort())); | |||
assertEquals(expVal, _bds.readUShort()); | |||
} | |||
public short readShort() { | |||
@@ -107,11 +106,11 @@ public final class TestBiff8DecryptingStream { | |||
} | |||
public void confirmInt(int expVal) { | |||
assertEquals(HexDump.intToHex(expVal), HexDump.intToHex(_bds.readInt())); | |||
assertEquals(expVal, _bds.readInt()); | |||
} | |||
public void confirmLong(long expVal) { | |||
assertEquals(HexDump.longToHex(expVal), HexDump.longToHex(_bds.readLong())); | |||
assertEquals(expVal, _bds.readLong()); | |||
} | |||
public void confirmData(String expHexData) { |
@@ -19,11 +19,9 @@ package org.apache.poi.poifs.storage; | |||
import java.io.ByteArrayInputStream; | |||
import java.io.ByteArrayOutputStream; | |||
import java.io.IOException; | |||
import java.util.Arrays; | |||
import java.util.Base64; | |||
import java.util.zip.GZIPInputStream; | |||
import org.apache.poi.util.HexDump; | |||
import org.apache.poi.util.HexRead; | |||
import org.apache.poi.util.IOUtils; | |||
@@ -31,11 +29,11 @@ import org.apache.poi.util.IOUtils; | |||
* Test utility class.<br> | |||
* | |||
* Creates raw <code>byte[]</code> data from hex-dump String arrays. | |||
* | |||
* @author Josh Micich | |||
*/ | |||
public final class RawDataUtil { | |||
private RawDataUtil() {} | |||
public static byte[] decode(String[] hexDataLines) { | |||
ByteArrayOutputStream baos = new ByteArrayOutputStream(hexDataLines.length * 32 + 32); | |||
@@ -46,47 +44,6 @@ public final class RawDataUtil { | |||
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 | |||
* | |||
@@ -98,7 +55,7 @@ public final class RawDataUtil { | |||
byte[] base64Bytes = Base64.getDecoder().decode(data); | |||
return IOUtils.toByteArray(new GZIPInputStream(new ByteArrayInputStream(base64Bytes))); | |||
} | |||
/** | |||
* Compress raw data for test runs - usually called while debugging :) | |||
* |