git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1871911 13f79535-47bb-0310-9956-ffa450edef68tags/REL_4_1_2
@@ -65,26 +65,26 @@ import org.junit.runners.Parameterized.Parameters; | |||
/** | |||
* This is an integration test which performs various actions on all stored test-files and tries | |||
* to reveal problems which are introduced, but not covered (yet) by unit tests. | |||
* | |||
* This test looks for any file under the test-data directory and tries to do some useful | |||
* to reveal problems which are introduced, but not covered (yet) by unit tests. | |||
* | |||
* This test looks for any file under the test-data directory and tries to do some useful | |||
* processing with it based on it's type. | |||
* | |||
* | |||
* The test is implemented as a junit {@link Parameterized} test, which leads | |||
* to one test-method call for each file (currently around 950 files are handled). | |||
* | |||
* There is a a mapping of extension to implementations of the interface | |||
* {@link FileHandler} which defines how the file is loaded and which actions are | |||
* tried with the file. | |||
* | |||
* to one test-method call for each file (currently around 950 files are handled). | |||
* | |||
* There is a a mapping of extension to implementations of the interface | |||
* {@link FileHandler} which defines how the file is loaded and which actions are | |||
* tried with the file. | |||
* | |||
* The test can be expanded by adding more actions to the FileHandlers, this automatically | |||
* applies the action to any such file in our test-data repository. | |||
* | |||
* | |||
* There is also a list of files that should actually fail. | |||
* | |||
* Note: It is also a test-failure if a file that is expected to fail now actually works, | |||
* i.e. if a bug was fixed in POI itself, the file should be removed from the expected-failures | |||
* here as well! This is to ensure that files that should not work really do not work, e.g. | |||
* | |||
* Note: It is also a test-failure if a file that is expected to fail now actually works, | |||
* i.e. if a bug was fixed in POI itself, the file should be removed from the expected-failures | |||
* here as well! This is to ensure that files that should not work really do not work, e.g. | |||
* that we do not remove expected sanity checks. | |||
*/ | |||
@RunWith(Parameterized.class) | |||
@@ -96,7 +96,7 @@ public class TestAllFiles { | |||
private static final Map<String,String> FILE_PASSWORD; | |||
// map file extensions to the actual mappers | |||
public static final Map<String, FileHandler> HANDLERS = new HashMap<>(); | |||
@@ -136,7 +136,7 @@ public class TestAllFiles { | |||
// Visio - binary | |||
HANDLERS.put(".vsd", IGNORE_SCRATCHPAD ? new HPSFFileHandler() : new HDGFFileHandler()); | |||
// Visio - ooxml | |||
HANDLERS.put(".vsdm", new XDGFFileHandler()); | |||
HANDLERS.put(".vsdx", new XDGFFileHandler()); | |||
@@ -238,7 +238,7 @@ public class TestAllFiles { | |||
passmap.put("poifs/protected_agile.docx", Decryptor.DEFAULT_PASSWORD); | |||
passmap.put("poifs/60320-protected.xlsx", "Test001!!"); | |||
passmap.put("poifs/protected_sha512.xlsx", "this is a test"); | |||
FILE_PASSWORD = Collections.unmodifiableMap(passmap); | |||
} | |||
@@ -326,7 +326,7 @@ public class TestAllFiles { | |||
"spreadsheet/testEXCEL_95.xls", | |||
"spreadsheet/59074.xls", | |||
"spreadsheet/60284.xls", | |||
// OOXML Strict is not yet supported, see bug #57699 | |||
"spreadsheet/SampleSS.strict.xlsx", | |||
"spreadsheet/SimpleStrict.xlsx", | |||
@@ -342,7 +342,7 @@ public class TestAllFiles { | |||
// sheet cloning errors | |||
"spreadsheet/56450.xls", | |||
"spreadsheet/OddStyleRecord.xls", | |||
// "spreadsheet/OddStyleRecord.xls", | |||
// msg files with non-standard encodings | |||
"hsmf/ASCII_CP1251_LCID1049.msg", | |||
@@ -377,7 +377,7 @@ public class TestAllFiles { | |||
} | |||
FileHandler handler = HANDLERS.get(getExtension(file)); | |||
files.add(new Object[] { file, handler }); | |||
// for some file-types also run OPCFileHandler | |||
if(handler instanceof XSSFFileHandler || | |||
handler instanceof XWPFFileHandler || | |||
@@ -385,7 +385,7 @@ public class TestAllFiles { | |||
handler instanceof XDGFFileHandler) { | |||
files.add(new Object[] { file, new OPCFileHandler() }); | |||
} | |||
if (handler instanceof HSSFFileHandler || | |||
handler instanceof HSLFFileHandler || | |||
handler instanceof HWPFFileHandler || | |||
@@ -410,7 +410,7 @@ public class TestAllFiles { | |||
String pass = TestAllFiles.FILE_PASSWORD.get(file); | |||
Biff8EncryptionKey.setCurrentUserPassword(pass); | |||
} | |||
@Test | |||
public void testAllFiles() throws Exception { | |||
if(handler == null) { | |||
@@ -426,7 +426,7 @@ public class TestAllFiles { | |||
file.endsWith(".xlsb") || file.endsWith(".pptx")) && | |||
handler instanceof OPCFileHandler; | |||
boolean ignoreHPSF = (handler instanceof HPSFFileHandler); | |||
try { | |||
try (InputStream stream = new BufferedInputStream(new FileInputStream(inputFile), 64 * 1024)) { | |||
handler.handleFile(stream, file); | |||
@@ -436,7 +436,7 @@ public class TestAllFiles { | |||
handler.handleExtracting(inputFile); | |||
assertFalse("Expected to fail for file " + file + " and handler " + handler + ", but did not fail!", | |||
assertFalse("Expected to fail for file " + file + " and handler " + handler + ", but did not fail!", | |||
EXPECTED_FAILURES.contains(file) && !ignoredOPC && !ignoreHPSF); | |||
} catch (OldFileFormatException e) { | |||
// for old word files we should still support extracting text |
@@ -28,14 +28,14 @@ import org.apache.poi.hssf.record.Record; | |||
import org.junit.Test; | |||
/** | |||
* Needs to be implemented in this package to have access to | |||
* Needs to be implemented in this package to have access to | |||
* HSSFWorkbook.getWorkbook() | |||
*/ | |||
public class RecordsStresser { | |||
public static void handleWorkbook(HSSFWorkbook wb) { | |||
List<Record> records = wb.getWorkbook().getRecords(); | |||
for(Record record : records) { | |||
// some Records do not implement clone ?! | |||
// some Records do not implement clone ?! | |||
// equals instead of instanceof is on purpose here to only skip exactly this class and not any derived ones | |||
// if(record.getClass().equals(InterfaceHdrRecord.class) || | |||
// record.getClass().equals(MMSRecord.class) || | |||
@@ -46,18 +46,16 @@ public class RecordsStresser { | |||
// continue; | |||
// } | |||
try { | |||
Record newRecord = (Record) record.clone(); | |||
assertEquals("Expecting the same class back from clone(), but had Record of type " + record.getClass() + " and got back a " + newRecord.getClass() + " from clone()", | |||
record.getClass(), newRecord.getClass()); | |||
Record newRecord = record.copy(); | |||
assertEquals("Expecting the same class back from clone(), but had Record of type " + record.getClass() + " and got back a " + newRecord.getClass() + " from clone()", | |||
record.getClass(), newRecord.getClass()); | |||
byte[] origBytes = record.serialize(); | |||
byte[] newBytes = newRecord.serialize(); | |||
assertArrayEquals("Record of type " + record.getClass() + " should return the same byte array via the clone() method, but did return a different array", | |||
assertArrayEquals("Record of type " + record.getClass() + " should return the same byte array via the clone() method, but did return a different array", | |||
origBytes, newBytes); | |||
} catch (CloneNotSupportedException e) { | |||
throw new RuntimeException(e); | |||
} catch (RuntimeException e) { | |||
// some Records do not implement clone, ignore those for now | |||
assertTrue(e.getMessage().contains("needs to define a clone method")); |
@@ -0,0 +1,39 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
this work for additional information regarding copyright ownership. | |||
The ASF licenses this file to You under the Apache License, Version 2.0 | |||
(the "License"); you may not use this file except in compliance with | |||
the License. You may obtain a copy of the License at | |||
http://www.apache.org/licenses/LICENSE-2.0 | |||
Unless required by applicable law or agreed to in writing, software | |||
distributed under the License is distributed on an "AS IS" BASIS, | |||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.common; | |||
/** | |||
* This is an alternative to the {@link Cloneable} interface without its side-effects. | |||
* A class implementing Duplicatable provides a deep-copy of itself - usually this is done via a copy-constructor, | |||
* which is invoked with a self-reference by the copy method. | |||
* References to child objects are duplicated - references to parents are kept as-is and | |||
* might need to be replaced by the parent copy operation. | |||
* | |||
* @param <T> the implementing class itself | |||
* | |||
* @see <a href="https://www.artima.com/intv/bloch.html#part13">Copy Constructor versus Cloning</a> | |||
*/ | |||
public interface Duplicatable { | |||
// Providing a generics interface Duplicatable<T extends Duplicatable<T>> pushes too many | |||
// changes to the implementing classes and the benefit of providing a subtype-specific copy method | |||
// is not sufficient | |||
/** | |||
* @return a deep copy of the implementing class / instance | |||
*/ | |||
Duplicatable copy(); | |||
} |
@@ -171,7 +171,4 @@ public abstract class AbstractEscherOptRecord extends EscherRecord { | |||
"properties", this::getEscherProperties | |||
); | |||
} | |||
@Override | |||
public abstract AbstractEscherOptRecord copy(); | |||
} |
@@ -142,13 +142,9 @@ public final class EscherContainerRecord extends EscherRecord implements Iterabl | |||
* @return true, if any child has the given recordId | |||
*/ | |||
public boolean hasChildOfType(short recordId) { | |||
for (EscherRecord r : this) { | |||
if(r.getRecordId() == recordId) { | |||
return true; | |||
} | |||
} | |||
return false; | |||
return _childRecords.stream().anyMatch(r -> r.getRecordId() == recordId); | |||
} | |||
@Override | |||
public EscherRecord getChild( int index ) { | |||
return _childRecords.get(index); | |||
@@ -170,6 +166,7 @@ public final class EscherContainerRecord extends EscherRecord implements Iterabl | |||
return Collections.unmodifiableList(_childRecords).iterator(); | |||
} | |||
/** | |||
* replaces the internal child list with the contents of the supplied <tt>childRecords</tt> | |||
*/ |
@@ -24,6 +24,7 @@ import java.util.List; | |||
import java.util.Map; | |||
import java.util.function.Supplier; | |||
import org.apache.poi.common.Duplicatable; | |||
import org.apache.poi.common.usermodel.GenericRecord; | |||
import org.apache.poi.util.BitField; | |||
import org.apache.poi.util.BitFieldFactory; | |||
@@ -32,12 +33,13 @@ import org.apache.poi.util.GenericRecordUtil; | |||
import org.apache.poi.util.GenericRecordXmlWriter; | |||
import org.apache.poi.util.Internal; | |||
import org.apache.poi.util.LittleEndian; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* The base abstract record from which all escher records are defined. Subclasses will need | |||
* to define methods for serialization/deserialization and for determining the record size. | |||
*/ | |||
public abstract class EscherRecord implements Cloneable, GenericRecord { | |||
public abstract class EscherRecord implements Duplicatable, GenericRecord { | |||
private static final BitField fInstance = BitFieldFactory.getInstance(0xfff0); | |||
private static final BitField fVersion = BitFieldFactory.getInstance(0x000f); | |||
@@ -238,9 +240,12 @@ public abstract class EscherRecord implements Cloneable, GenericRecord { | |||
* Escher records may need to be clonable in the future. | |||
* | |||
* @return the cloned object | |||
* @deprecated use {@link #copy()} | |||
*/ | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public final EscherRecord clone() { | |||
return copy(); | |||
} | |||
@@ -350,5 +355,6 @@ public abstract class EscherRecord implements Cloneable, GenericRecord { | |||
); | |||
} | |||
@Override | |||
public abstract EscherRecord copy(); | |||
} |
@@ -31,7 +31,7 @@ import org.apache.poi.util.RecordFormatException; | |||
* Escher format. We don't attempt to understand the contents, since | |||
* they will be in the parent's format, not Escher format. | |||
*/ | |||
public final class EscherTextboxRecord extends EscherRecord implements Cloneable { | |||
public final class EscherTextboxRecord extends EscherRecord { | |||
//arbitrarily selected; may need to increase | |||
private static final int MAX_RECORD_LENGTH = 100_000; |
@@ -31,7 +31,7 @@ import org.apache.poi.util.LittleEndian; | |||
* This record is used whenever a escher record is encountered that | |||
* we do not explicitly support. | |||
*/ | |||
public final class UnknownEscherRecord extends EscherRecord implements Cloneable { | |||
public final class UnknownEscherRecord extends EscherRecord { | |||
//arbitrarily selected; may need to increase | |||
private static final int MAX_RECORD_LENGTH = 100_000_000; |
@@ -23,11 +23,9 @@ import org.apache.poi.util.RecordFormatException; | |||
/** | |||
*/ | |||
abstract class DummyRecordBase extends Record { | |||
protected DummyRecordBase() { | |||
// | |||
} | |||
protected DummyRecordBase() {} | |||
public final short getSid() { | |||
return -1; | |||
} |
@@ -25,37 +25,42 @@ package org.apache.poi.hssf.eventusermodel.dummyrecord; | |||
public final class LastCellOfRowDummyRecord extends DummyRecordBase { | |||
private final int row; | |||
private final int lastColumnNumber; | |||
public LastCellOfRowDummyRecord(int row, int lastColumnNumber) { | |||
this.row = row; | |||
this.lastColumnNumber = lastColumnNumber; | |||
} | |||
/** | |||
* Returns the (0 based) number of the row we are | |||
* currently working on. | |||
* | |||
* | |||
* @return the (0 based) number of the row | |||
*/ | |||
public int getRow() { | |||
return row; | |||
} | |||
/** | |||
* Returns the (0 based) number of the last column | |||
* seen for this row. You should have already been | |||
* called with that record. | |||
* This is -1 in the case of there being no columns | |||
* for the row. | |||
* | |||
* | |||
* @return the (0 based) number of the last column | |||
*/ | |||
public int getLastColumnNumber() { | |||
return lastColumnNumber; | |||
} | |||
@Override | |||
public String toString() { | |||
return "End-of-Row for Row=" + row + " at Column=" + lastColumnNumber; | |||
} | |||
@Override | |||
public LastCellOfRowDummyRecord copy() { | |||
return this; | |||
} | |||
} |
@@ -23,13 +23,18 @@ package org.apache.poi.hssf.eventusermodel.dummyrecord; | |||
* but still want to trigger something | |||
*/ | |||
public final class MissingCellDummyRecord extends DummyRecordBase { | |||
private int row; | |||
private int column; | |||
private final int row; | |||
private final int column; | |||
public MissingCellDummyRecord(int row, int column) { | |||
this.row = row; | |||
this.column = column; | |||
} | |||
public int getRow() { return row; } | |||
public int getColumn() { return column; } | |||
@Override | |||
public MissingCellDummyRecord copy() { | |||
return this; | |||
} | |||
} |
@@ -23,12 +23,17 @@ package org.apache.poi.hssf.eventusermodel.dummyrecord; | |||
* want to trigger something | |||
*/ | |||
public final class MissingRowDummyRecord extends DummyRecordBase { | |||
private int rowNumber; | |||
private final int rowNumber; | |||
public MissingRowDummyRecord(int rowNumber) { | |||
this.rowNumber = rowNumber; | |||
} | |||
public int getRowNumber() { | |||
return rowNumber; | |||
} | |||
@Override | |||
public MissingRowDummyRecord copy() { | |||
return this; | |||
} | |||
} |
@@ -132,7 +132,7 @@ public final class InternalSheet { | |||
if (rs.peekNextSid() != BOFRecord.sid) { | |||
throw new RecordFormatException("BOF record expected"); | |||
} | |||
BOFRecord bof = (BOFRecord) rs.getNext(); | |||
if (bof.getType() == BOFRecord.TYPE_WORKSHEET) { | |||
// Good, well supported | |||
@@ -152,7 +152,7 @@ public final class InternalSheet { | |||
throw new UnsupportedBOFType(bof.getType()); | |||
} | |||
records.add(bof); | |||
while (rs.hasNext()) { | |||
int recSid = rs.peekNextSid(); | |||
@@ -339,14 +339,14 @@ public final class InternalSheet { | |||
recs.add(r); | |||
}}); | |||
} | |||
public static class UnsupportedBOFType extends RecordFormatException { | |||
private final int type; | |||
protected UnsupportedBOFType(int type) { | |||
super("BOF not of a supported type, found " + type); | |||
this.type = type; | |||
} | |||
public int getType() { | |||
return type; | |||
} | |||
@@ -360,11 +360,7 @@ public final class InternalSheet { | |||
_destList = destList; | |||
} | |||
public void visitRecord(Record r) { | |||
try { | |||
_destList.add((Record)r.clone()); | |||
} catch (CloneNotSupportedException e) { | |||
throw new RecordFormatException(e); | |||
} | |||
_destList.add(r.copy()); | |||
} | |||
} | |||
@@ -374,7 +370,7 @@ public final class InternalSheet { | |||
* can be added to a sheet. The <b>Record</b> object does not implement cloneable. | |||
* When adding a new record, implement a public clone method if and only if the record | |||
* belongs to a sheet. | |||
* | |||
* | |||
* @return the cloned sheet | |||
*/ | |||
public InternalSheet cloneSheet() { | |||
@@ -391,12 +387,8 @@ public final class InternalSheet { | |||
*/ | |||
rb = new DrawingRecord(); | |||
} | |||
try { | |||
Record rec = (Record) ((Record) rb).clone(); | |||
clonedRecords.add(rec); | |||
} catch (CloneNotSupportedException e) { | |||
throw new RecordFormatException(e); | |||
} | |||
Record rec = ((Record) rb).copy(); | |||
clonedRecords.add(rec); | |||
} | |||
return createSheet(new RecordStream(clonedRecords, 0)); | |||
} | |||
@@ -478,7 +470,7 @@ public final class InternalSheet { | |||
/** | |||
* Updates formulas in cells and conditional formats due to moving of cells | |||
* | |||
* | |||
* @param shifter the formular shifter | |||
* @param externSheetIndex the externSheet index of this sheet | |||
*/ | |||
@@ -995,7 +987,7 @@ public final class InternalSheet { | |||
/** | |||
* set the default row height for the sheet (if the rows do not define their own height) | |||
* | |||
* | |||
* @param dch the default row height | |||
*/ | |||
public void setDefaultRowHeight(short dch) { | |||
@@ -1247,7 +1239,7 @@ public final class InternalSheet { | |||
/** | |||
* Gets the gridset record for this sheet. | |||
* | |||
* | |||
* @return the gridset record for this sheet | |||
*/ | |||
public GridsetRecord getGridsetRecord() | |||
@@ -1257,9 +1249,9 @@ public final class InternalSheet { | |||
/** | |||
* Returns the first occurrence of a record matching a particular sid. | |||
* | |||
* | |||
* @param sid the sid to search for | |||
* | |||
* | |||
* @return the matching record or {@code null} if it wasn't found | |||
*/ | |||
public Record findFirstRecordBySid(short sid) { | |||
@@ -1330,7 +1322,7 @@ public final class InternalSheet { | |||
{ | |||
printGridlines = newPrintGridlines; | |||
} | |||
/** | |||
* Returns the PrintHeadersRecord. | |||
* @return PrintHeadersRecord for the sheet. | |||
@@ -1519,7 +1511,7 @@ public final class InternalSheet { | |||
public boolean isDisplayRowColHeadings() { | |||
return windowTwo.getDisplayRowColHeadings(); | |||
} | |||
/** | |||
* Sets whether the RowColHeadings are shown in a viewer. | |||
* @param show whether to show RowColHeadings or not | |||
@@ -1681,7 +1673,7 @@ public final class InternalSheet { | |||
temp.toArray(result); | |||
return result; | |||
} | |||
public int getColumnOutlineLevel(int columnIndex) { | |||
return _columnInfos.getOutlineLevel(columnIndex); | |||
} |
@@ -32,7 +32,7 @@ public final class RecordStream { | |||
/** | |||
* Creates a RecordStream bounded by startIndex and endIndex | |||
* | |||
* | |||
* @param inputList the list to iterate over | |||
* @param startIndex the start index within the list | |||
* @param endIx the end index within the list, which is the index of the end element + 1 | |||
@@ -70,6 +70,13 @@ public final class RecordStream { | |||
return _list.get(_nextIndex).getClass(); | |||
} | |||
/** | |||
* @return the next Record. <code>null</code> if this stream is exhausted. | |||
*/ | |||
public Record peekNextRecord() { | |||
return (hasNext()) ? _list.get(_nextIndex) : null; | |||
} | |||
/** | |||
* @return -1 if at end of records | |||
*/ |
@@ -25,14 +25,15 @@ import org.apache.poi.ddf.EscherContainerRecord; | |||
import org.apache.poi.ddf.EscherRecord; | |||
import org.apache.poi.ddf.EscherRecordFactory; | |||
import org.apache.poi.ddf.NullEscherSerializationListener; | |||
import org.apache.poi.util.LittleEndian; | |||
import org.apache.poi.hssf.util.LazilyConcatenatedByteArray; | |||
import org.apache.poi.util.LittleEndian; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* The escher container record is used to hold escher records. It is abstract and | |||
* must be subclassed for maximum benefit. | |||
*/ | |||
public abstract class AbstractEscherHolderRecord extends Record implements Cloneable { | |||
public abstract class AbstractEscherHolderRecord extends Record { | |||
private static boolean DESERIALISE; | |||
static { | |||
try { | |||
@@ -42,17 +43,17 @@ public abstract class AbstractEscherHolderRecord extends Record implements Clone | |||
} | |||
} | |||
private final List<EscherRecord> escherRecords; | |||
private final List<EscherRecord> escherRecords = new ArrayList<>(); | |||
private final LazilyConcatenatedByteArray rawDataContainer = new LazilyConcatenatedByteArray(); | |||
public AbstractEscherHolderRecord() | |||
{ | |||
escherRecords = new ArrayList<>(); | |||
public AbstractEscherHolderRecord() {} | |||
public AbstractEscherHolderRecord(AbstractEscherHolderRecord other) { | |||
other.escherRecords.stream().map(EscherRecord::copy).forEach(escherRecords::add); | |||
rawDataContainer.concatenate(other.rawDataContainer); | |||
} | |||
public AbstractEscherHolderRecord(RecordInputStream in) | |||
{ | |||
escherRecords = new ArrayList<>(); | |||
public AbstractEscherHolderRecord(RecordInputStream in) { | |||
if (! DESERIALISE ) { | |||
rawDataContainer.concatenate(in.readRemainder()); | |||
} else { | |||
@@ -143,10 +144,16 @@ public abstract class AbstractEscherHolderRecord extends Record implements Clone | |||
public abstract short getSid(); | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public AbstractEscherHolderRecord clone() { | |||
return (AbstractEscherHolderRecord)cloneViaReserialise(); | |||
return copy(); | |||
} | |||
@Override | |||
public abstract AbstractEscherHolderRecord copy(); | |||
public void addEscherRecord(int index, EscherRecord element) | |||
{ | |||
escherRecords.add( index, element ); | |||
@@ -171,7 +178,7 @@ public abstract class AbstractEscherHolderRecord extends Record implements Clone | |||
* If we have a EscherContainerRecord as one of our | |||
* children (and most top level escher holders do), | |||
* then return that. | |||
* | |||
* | |||
* @return the EscherContainerRecord or {@code null} if no child is a container record | |||
*/ | |||
public EscherContainerRecord getEscherContainer() { | |||
@@ -187,15 +194,15 @@ public abstract class AbstractEscherHolderRecord extends Record implements Clone | |||
* Descends into all our children, returning the | |||
* first EscherRecord with the given id, or null | |||
* if none found | |||
* | |||
* | |||
* @param id the record to look for | |||
* | |||
* | |||
* @return the record or {@code null} if it can't be found | |||
*/ | |||
public EscherRecord findFirstWithId(short id) { | |||
return findFirstWithId(id, getEscherRecords()); | |||
} | |||
private EscherRecord findFirstWithId(short id, List<EscherRecord> records) { | |||
// Check at our level | |||
for (EscherRecord r : records) { | |||
@@ -227,7 +234,7 @@ public abstract class AbstractEscherHolderRecord extends Record implements Clone | |||
/** | |||
* Big drawing group records are split but it's easier to deal with them | |||
* as a whole group so we need to join them together. | |||
* | |||
* | |||
* @param record the record data to concatenate to the end | |||
*/ | |||
public void join( AbstractEscherHolderRecord record ) |
@@ -17,18 +17,19 @@ | |||
package org.apache.poi.hssf.record; | |||
import org.apache.poi.ss.formula.ptg.Ptg; | |||
import org.apache.poi.hssf.util.CellRangeAddress8Bit; | |||
import org.apache.poi.ss.formula.Formula; | |||
import org.apache.poi.ss.formula.ptg.Ptg; | |||
import org.apache.poi.util.HexDump; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* ARRAY (0x0221)<p> | |||
* | |||
* Treated in a similar way to SharedFormulaRecord | |||
*/ | |||
public final class ArrayRecord extends SharedValueRecordBase implements Cloneable { | |||
public final class ArrayRecord extends SharedValueRecordBase { | |||
public final static short sid = 0x0221; | |||
private static final int OPT_ALWAYS_RECALCULATE = 0x0001; | |||
@@ -38,6 +39,13 @@ public final class ArrayRecord extends SharedValueRecordBase implements Cloneabl | |||
private int _field3notUsed; | |||
private Formula _formula; | |||
public ArrayRecord(ArrayRecord other) { | |||
super(other); | |||
_options = other._options; | |||
_field3notUsed = other._field3notUsed; | |||
_formula = (other._formula == null) ? null : other._formula.copy(); | |||
} | |||
public ArrayRecord(RecordInputStream in) { | |||
super(in); | |||
_options = in.readUShort(); | |||
@@ -92,16 +100,18 @@ public final class ArrayRecord extends SharedValueRecordBase implements Cloneabl | |||
} | |||
sb.append("]"); | |||
return sb.toString(); | |||
} | |||
@Override | |||
public ArrayRecord clone() { | |||
ArrayRecord rec = new ArrayRecord(_formula.copy(), getRange()); | |||
} | |||
// they both seem unused, but clone them nevertheless to have an exact copy | |||
rec._options = _options; | |||
rec._field3notUsed = _field3notUsed; | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public ArrayRecord clone() { | |||
return copy(); | |||
} | |||
return rec; | |||
@Override | |||
public ArrayRecord copy() { | |||
return new ArrayRecord(this); | |||
} | |||
} |
@@ -20,27 +20,28 @@ | |||
package org.apache.poi.hssf.record; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* The AutoFilterInfo record specifies the number of columns that have AutoFilter enabled | |||
* and indicates the beginning of the collection of AutoFilter records. | |||
* | |||
* @author Yegor Kozlov | |||
*/ | |||
public final class AutoFilterInfoRecord extends StandardRecord implements Cloneable { | |||
public final static short sid = 0x9D; | |||
public final class AutoFilterInfoRecord extends StandardRecord { | |||
public static final short sid = 0x9D; | |||
/** | |||
* Number of AutoFilter drop-down arrows on the sheet | |||
*/ | |||
private short _cEntries; // = 0; | |||
private short _cEntries; | |||
public AutoFilterInfoRecord() | |||
{ | |||
public AutoFilterInfoRecord() {} | |||
public AutoFilterInfoRecord(AutoFilterInfoRecord other) { | |||
super(other); | |||
_cEntries = other._cEntries; | |||
} | |||
public AutoFilterInfoRecord(RecordInputStream in) | |||
{ | |||
public AutoFilterInfoRecord(RecordInputStream in) { | |||
_cEntries = in.readShort(); | |||
} | |||
@@ -91,9 +92,15 @@ public final class AutoFilterInfoRecord extends StandardRecord implements Clonea | |||
} | |||
@Override | |||
public AutoFilterInfoRecord clone() | |||
{ | |||
return (AutoFilterInfoRecord)cloneViaReserialise(); | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public AutoFilterInfoRecord clone() { | |||
return copy(); | |||
} | |||
@Override | |||
public AutoFilterInfoRecord copy() { | |||
return new AutoFilterInfoRecord(this); | |||
} | |||
} |
@@ -19,44 +19,40 @@ package org.apache.poi.hssf.record; | |||
import org.apache.poi.util.HexDump; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* Title: Beginning Of File (0x0809)<P> | |||
* Description: Somewhat of a misnomer, its used for the beginning of a set of | |||
* records that have a particular purpose or subject. | |||
* Used in sheets and workbooks.<P> | |||
* REFERENCE: PG 289 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> | |||
* @author Andrew C. Oliver | |||
* @author Jason Height (jheight at chariot dot net dot au) | |||
* Somewhat of a misnomer, its used for the beginning of a set of records that | |||
* have a particular purpose or subject. Used in sheets and workbooks. | |||
*/ | |||
public final class BOFRecord extends StandardRecord implements Cloneable { | |||
public final class BOFRecord extends StandardRecord { | |||
/** | |||
* for BIFF8 files the BOF is 0x809. For earlier versions see | |||
* {@link #biff2_sid} {@link #biff3_sid} {@link #biff4_sid} | |||
* {@link #biff2_sid} {@link #biff3_sid} {@link #biff4_sid} | |||
* {@link #biff5_sid} | |||
*/ | |||
public final static short sid = 0x809; | |||
public static final short sid = 0x809; | |||
// SIDs from earlier BIFF versions | |||
public final static short biff2_sid = 0x009; | |||
public final static short biff3_sid = 0x209; | |||
public final static short biff4_sid = 0x409; | |||
public final static short biff5_sid = 0x809; | |||
public static final short biff2_sid = 0x009; | |||
public static final short biff3_sid = 0x209; | |||
public static final short biff4_sid = 0x409; | |||
public static final short biff5_sid = 0x809; | |||
/** suggested default (0x0600 - BIFF8) */ | |||
public final static int VERSION = 0x0600; | |||
public static final int VERSION = 0x0600; | |||
/** suggested default 0x10d3 */ | |||
public final static int BUILD = 0x10d3; | |||
public static final int BUILD = 0x10d3; | |||
/** suggested default 0x07CC (1996) */ | |||
public final static int BUILD_YEAR = 0x07CC; // 1996 | |||
public static final int BUILD_YEAR = 0x07CC; // 1996 | |||
/** suggested default for a normal sheet (0x41) */ | |||
public final static int HISTORY_MASK = 0x41; | |||
public static final int HISTORY_MASK = 0x41; | |||
public final static int TYPE_WORKBOOK = 0x05; | |||
public final static int TYPE_VB_MODULE = 0x06; | |||
public final static int TYPE_WORKSHEET = 0x10; | |||
public final static int TYPE_CHART = 0x20; | |||
public final static int TYPE_EXCEL_4_MACRO = 0x40; | |||
public final static int TYPE_WORKSPACE_FILE = 0x100; | |||
public static final int TYPE_WORKBOOK = 0x05; | |||
public static final int TYPE_VB_MODULE = 0x06; | |||
public static final int TYPE_WORKSHEET = 0x10; | |||
public static final int TYPE_CHART = 0x20; | |||
public static final int TYPE_EXCEL_4_MACRO = 0x40; | |||
public static final int TYPE_WORKSPACE_FILE = 0x100; | |||
private int field_1_version; | |||
private int field_2_type; | |||
@@ -68,9 +64,18 @@ public final class BOFRecord extends StandardRecord implements Cloneable { | |||
/** | |||
* Constructs an empty BOFRecord with no fields set. | |||
*/ | |||
public BOFRecord() { | |||
public BOFRecord() {} | |||
public BOFRecord(BOFRecord other) { | |||
super(other); | |||
field_1_version = other.field_1_version; | |||
field_2_type = other.field_2_type; | |||
field_3_build = other.field_3_build; | |||
field_4_year = other.field_4_year; | |||
field_5_history = other.field_5_history; | |||
field_6_rversion = other.field_6_rversion; | |||
} | |||
private BOFRecord(int type) { | |||
field_1_version = VERSION; | |||
field_2_type = type; | |||
@@ -79,7 +84,7 @@ public final class BOFRecord extends StandardRecord implements Cloneable { | |||
field_5_history = 0x01; | |||
field_6_rversion = VERSION; | |||
} | |||
public static BOFRecord createSheetBOF() { | |||
return new BOFRecord(TYPE_WORKSHEET); | |||
} | |||
@@ -269,14 +274,15 @@ public final class BOFRecord extends StandardRecord implements Cloneable { | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public BOFRecord clone() { | |||
BOFRecord rec = new BOFRecord(); | |||
rec.field_1_version = field_1_version; | |||
rec.field_2_type = field_2_type; | |||
rec.field_3_build = field_3_build; | |||
rec.field_4_year = field_4_year; | |||
rec.field_5_history = field_5_history; | |||
rec.field_6_rversion = field_6_rversion; | |||
return rec; | |||
return copy(); | |||
} | |||
@Override | |||
public BOFRecord copy() { | |||
return new BOFRecord(this); | |||
} | |||
} |
@@ -15,33 +15,31 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.hssf.record; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
/** | |||
* Title: Backup Record <P> | |||
* Description: Boolean specifying whether | |||
* the GUI should store a backup of the file.<P> | |||
* REFERENCE: PG 287 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> | |||
* @author Andrew C. Oliver (acoliver at apache dot org) | |||
* Boolean specifying whether the GUI should store a backup of the file. | |||
* | |||
* @version 2.0-pre | |||
*/ | |||
public final class BackupRecord | |||
extends StandardRecord | |||
{ | |||
public final static short sid = 0x40; | |||
private short field_1_backup; // = 0; | |||
public final class BackupRecord extends StandardRecord { | |||
public static final short sid = 0x40; | |||
public BackupRecord() | |||
{ | |||
private short field_1_backup; | |||
public BackupRecord() {} | |||
public BackupRecord(BackupRecord other) { | |||
super(other); | |||
field_1_backup = other.field_1_backup; | |||
} | |||
public BackupRecord(RecordInputStream in) | |||
{ | |||
public BackupRecord(RecordInputStream in) { | |||
field_1_backup = in.readShort(); | |||
} | |||
@@ -90,4 +88,9 @@ public final class BackupRecord | |||
{ | |||
return sid; | |||
} | |||
@Override | |||
public BackupRecord copy() { | |||
return new BackupRecord(this); | |||
} | |||
} |
@@ -19,28 +19,32 @@ package org.apache.poi.hssf.record; | |||
import org.apache.poi.util.HexDump; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* Title: Blank cell record (0x0201) <P> | |||
* Description: Represents a column in a row with no value but with styling.<P> | |||
* REFERENCE: PG 287 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> | |||
* @author Andrew C. Oliver (acoliver at apache dot org) | |||
* @author Jason Height (jheight at chariot dot net dot au) | |||
* Represents a column in a row with no value but with styling. | |||
* | |||
* @version 2.0-pre | |||
*/ | |||
public final class BlankRecord extends StandardRecord implements CellValueRecordInterface, Cloneable { | |||
public final static short sid = 0x0201; | |||
private int field_1_row; | |||
private short field_2_col; | |||
private short field_3_xf; | |||
public final class BlankRecord extends StandardRecord implements CellValueRecordInterface { | |||
public static final short sid = 0x0201; | |||
private int field_1_row; | |||
private short field_2_col; | |||
private short field_3_xf; | |||
/** Creates a new instance of BlankRecord */ | |||
public BlankRecord() | |||
{ | |||
public BlankRecord() {} | |||
public BlankRecord(BlankRecord other) { | |||
super(other); | |||
field_1_row = other.field_1_row; | |||
field_2_col = other.field_2_col; | |||
field_3_xf = other.field_3_xf; | |||
} | |||
public BlankRecord(RecordInputStream in) | |||
{ | |||
public BlankRecord(RecordInputStream in) { | |||
field_1_row = in.readUShort(); | |||
field_2_col = in.readShort(); | |||
field_3_xf = in.readShort(); | |||
@@ -138,11 +142,15 @@ public final class BlankRecord extends StandardRecord implements CellValueRecord | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public BlankRecord clone() { | |||
BlankRecord rec = new BlankRecord(); | |||
rec.field_1_row = field_1_row; | |||
rec.field_2_col = field_2_col; | |||
rec.field_3_xf = field_3_xf; | |||
return rec; | |||
return copy(); | |||
} | |||
@Override | |||
public BlankRecord copy() { | |||
return new BlankRecord(this); | |||
} | |||
} |
@@ -15,33 +15,31 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.hssf.record; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
/** | |||
* Title: Save External Links record (BookBool)<P> | |||
* Description: Contains a flag specifying whether the Gui should save externally | |||
* linked values from other workbooks. <P> | |||
* REFERENCE: PG 289 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> | |||
* @author Andrew C. Oliver (acoliver at apache dot org) | |||
* Contains a flag specifying whether the Gui should save externally linked values from other workbooks. | |||
* | |||
* @version 2.0-pre | |||
*/ | |||
public final class BookBoolRecord | |||
extends StandardRecord | |||
{ | |||
public final static short sid = 0xDA; | |||
private short field_1_save_link_values; | |||
public final class BookBoolRecord extends StandardRecord { | |||
public static final short sid = 0xDA; | |||
public BookBoolRecord() | |||
{ | |||
private short field_1_save_link_values; | |||
public BookBoolRecord() {} | |||
public BookBoolRecord(BookBoolRecord other) { | |||
super(other); | |||
field_1_save_link_values = other.field_1_save_link_values; | |||
} | |||
public BookBoolRecord(RecordInputStream in) | |||
{ | |||
public BookBoolRecord(RecordInputStream in) { | |||
field_1_save_link_values = in.readShort(); | |||
} | |||
@@ -90,4 +88,9 @@ public final class BookBoolRecord | |||
{ | |||
return sid; | |||
} | |||
@Override | |||
public BookBoolRecord copy() { | |||
return new BookBoolRecord(this); | |||
} | |||
} |
@@ -21,24 +21,27 @@ import org.apache.poi.ss.usermodel.FormulaError; | |||
import org.apache.poi.util.HexDump; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.RecordFormatException; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* Creates new BoolErrRecord. (0x0205) <P> | |||
* REFERENCE: PG ??? Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> | |||
* @author Michael P. Harhen | |||
* @author Jason Height (jheight at chariot dot net dot au) | |||
* Creates new BoolErrRecord. (0x0205) | |||
*/ | |||
public final class BoolErrRecord extends CellRecord implements Cloneable { | |||
public final static short sid = 0x0205; | |||
public final class BoolErrRecord extends CellRecord { | |||
public static final short sid = 0x0205; | |||
private int _value; | |||
/** | |||
* If <code>true</code>, this record represents an error cell value, otherwise this record represents a boolean cell value | |||
* If <code>true</code>, this record represents an error cell value, | |||
* otherwise this record represents a boolean cell value | |||
*/ | |||
private boolean _isError; | |||
/** Creates new BoolErrRecord */ | |||
public BoolErrRecord() { | |||
// fields uninitialised | |||
public BoolErrRecord() {} | |||
public BoolErrRecord(BoolErrRecord other) { | |||
super(other); | |||
_value = other._value; | |||
_isError = other._isError; | |||
} | |||
/** | |||
@@ -183,11 +186,15 @@ public final class BoolErrRecord extends CellRecord implements Cloneable { | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public BoolErrRecord clone() { | |||
BoolErrRecord rec = new BoolErrRecord(); | |||
copyBaseFields(rec); | |||
rec._value = _value; | |||
rec._isError = _isError; | |||
return rec; | |||
return copy(); | |||
} | |||
@Override | |||
public BoolErrRecord copy() { | |||
return new BoolErrRecord(this); | |||
} | |||
} |
@@ -20,22 +20,24 @@ package org.apache.poi.hssf.record; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* Record for the bottom margin. | |||
*/ | |||
public final class BottomMarginRecord extends StandardRecord implements Margin, Cloneable { | |||
public final static short sid = 0x29; | |||
public final class BottomMarginRecord extends StandardRecord implements Margin { | |||
public static final short sid = 0x29; | |||
private double field_1_margin; | |||
public BottomMarginRecord() | |||
{ | |||
public BottomMarginRecord() {} | |||
public BottomMarginRecord(BottomMarginRecord other) { | |||
super(other); | |||
field_1_margin = other.field_1_margin; | |||
} | |||
public BottomMarginRecord( RecordInputStream in ) | |||
{ | |||
public BottomMarginRecord( RecordInputStream in ) { | |||
field_1_margin = in.readDouble(); | |||
} | |||
@@ -79,10 +81,15 @@ public final class BottomMarginRecord extends StandardRecord implements Margin, | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public BottomMarginRecord clone() { | |||
BottomMarginRecord rec = new BottomMarginRecord(); | |||
rec.field_1_margin = this.field_1_margin; | |||
return rec; | |||
return copy(); | |||
} | |||
} // END OF | |||
@Override | |||
public BottomMarginRecord copy() { | |||
return new BottomMarginRecord(this); | |||
} | |||
} |
@@ -18,9 +18,9 @@ | |||
package org.apache.poi.hssf.record; | |||
import java.util.Arrays; | |||
import java.util.Comparator; | |||
import java.util.List; | |||
import org.apache.poi.ss.util.WorkbookUtil; | |||
import org.apache.poi.util.BitField; | |||
import org.apache.poi.util.BitFieldFactory; | |||
import org.apache.poi.util.HexDump; | |||
@@ -28,20 +28,16 @@ import org.apache.poi.util.LittleEndian; | |||
import org.apache.poi.util.LittleEndianConsts; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.StringUtil; | |||
import org.apache.poi.ss.util.WorkbookUtil; | |||
/** | |||
* Title: Bound Sheet Record (aka BundleSheet) (0x0085)<P> | |||
* Description: Defines a sheet within a workbook. Basically stores the sheet name | |||
* and tells where the Beginning of file record is within the HSSF | |||
* file. <P> | |||
* REFERENCE: PG 291 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) | |||
* Defines a sheet within a workbook. Basically stores the sheet name and | |||
* tells where the Beginning of file record is within the HSSF file. | |||
*/ | |||
public final class BoundSheetRecord extends StandardRecord { | |||
public final static short sid = 0x0085; | |||
public static final short sid = 0x0085; | |||
private static final BitField hiddenFlag = BitFieldFactory.getInstance(0x01); | |||
private static final BitField veryHiddenFlag = BitFieldFactory.getInstance(0x02); | |||
private int field_1_position_of_BOF; | |||
private int field_2_option_flags; | |||
private int field_4_isMultibyteUnicode; | |||
@@ -52,13 +48,21 @@ public final class BoundSheetRecord extends StandardRecord { | |||
setSheetname(sheetname); | |||
} | |||
public BoundSheetRecord(BoundSheetRecord other) { | |||
super(other); | |||
field_1_position_of_BOF = other.field_1_position_of_BOF; | |||
field_2_option_flags = other.field_2_option_flags; | |||
field_4_isMultibyteUnicode = other.field_4_isMultibyteUnicode; | |||
field_5_sheetname = other.field_5_sheetname; | |||
} | |||
/** | |||
* UTF8: sid + len + bof + flags + len(str) + unicode + str 2 + 2 + 4 + 2 + | |||
* 1 + 1 + len(str) | |||
* | |||
* UNICODE: sid + len + bof + flags + len(str) + unicode + str 2 + 2 + 4 + 2 + | |||
* 1 + 1 + 2 * len(str) | |||
* | |||
* | |||
* @param in the record stream to read from | |||
*/ | |||
public BoundSheetRecord(RecordInputStream in) { | |||
@@ -158,7 +162,7 @@ public final class BoundSheetRecord extends StandardRecord { | |||
/** | |||
* Is the sheet hidden? Different from very hidden | |||
* | |||
* | |||
* @return {@code true} if hidden | |||
*/ | |||
public boolean isHidden() { | |||
@@ -167,7 +171,7 @@ public final class BoundSheetRecord extends StandardRecord { | |||
/** | |||
* Is the sheet hidden? Different from very hidden | |||
* | |||
* | |||
* @param hidden {@code true} if hidden | |||
*/ | |||
public void setHidden(boolean hidden) { | |||
@@ -176,7 +180,7 @@ public final class BoundSheetRecord extends StandardRecord { | |||
/** | |||
* Is the sheet very hidden? Different from (normal) hidden | |||
* | |||
* | |||
* @return {@code true} if very hidden | |||
*/ | |||
public boolean isVeryHidden() { | |||
@@ -185,7 +189,7 @@ public final class BoundSheetRecord extends StandardRecord { | |||
/** | |||
* Is the sheet very hidden? Different from (normal) hidden | |||
* | |||
* | |||
* @param veryHidden {@code true} if very hidden | |||
*/ | |||
public void setVeryHidden(boolean veryHidden) { | |||
@@ -195,22 +199,24 @@ public final class BoundSheetRecord extends StandardRecord { | |||
/** | |||
* Converts a List of {@link BoundSheetRecord}s to an array and sorts by the position of their | |||
* BOFs. | |||
* | |||
* | |||
* @param boundSheetRecords the boundSheetRecord list to arrayify | |||
* | |||
* | |||
* @return the sorted boundSheetRecords | |||
*/ | |||
public static BoundSheetRecord[] orderByBofPosition(List<BoundSheetRecord> boundSheetRecords) { | |||
BoundSheetRecord[] bsrs = new BoundSheetRecord[boundSheetRecords.size()]; | |||
boundSheetRecords.toArray(bsrs); | |||
Arrays.sort(bsrs, BOFComparator); | |||
Arrays.sort(bsrs, BoundSheetRecord::compareRecords); | |||
return bsrs; | |||
} | |||
private static final Comparator<BoundSheetRecord> BOFComparator = new Comparator<BoundSheetRecord>() { | |||
public int compare(BoundSheetRecord bsr1, BoundSheetRecord bsr2) { | |||
return bsr1.getPositionOfBof() - bsr2.getPositionOfBof(); | |||
} | |||
}; | |||
private static int compareRecords(BoundSheetRecord bsr1, BoundSheetRecord bsr2) { | |||
return bsr1.getPositionOfBof() - bsr2.getPositionOfBof(); | |||
} | |||
@Override | |||
public BoundSheetRecord copy() { | |||
return new BoundSheetRecord(this); | |||
} | |||
} |
@@ -21,22 +21,28 @@ import org.apache.poi.hssf.record.common.FtrHeader; | |||
import org.apache.poi.hssf.record.common.FutureRecord; | |||
import org.apache.poi.ss.util.CellRangeAddress; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* Conditional Formatting Header v12 record CFHEADER12 (0x0879), | |||
* for conditional formattings introduced in Excel 2007 and newer. | |||
*/ | |||
public final class CFHeader12Record extends CFHeaderBase implements FutureRecord, Cloneable { | |||
public final class CFHeader12Record extends CFHeaderBase implements FutureRecord { | |||
public static final short sid = 0x0879; | |||
private FtrHeader futureHeader; | |||
/** Creates new CFHeaderRecord */ | |||
public CFHeader12Record() { | |||
createEmpty(); | |||
futureHeader = new FtrHeader(); | |||
futureHeader.setRecordType(sid); | |||
} | |||
public CFHeader12Record(CFHeader12Record other) { | |||
super(other); | |||
futureHeader = other.futureHeader.copy(); | |||
} | |||
public CFHeader12Record(CellRangeAddress[] regions, int nRules) { | |||
super(regions, nRules); | |||
futureHeader = new FtrHeader(); | |||
@@ -78,12 +84,17 @@ public final class CFHeader12Record extends CFHeaderBase implements FutureRecord | |||
public CellRangeAddress getAssociatedRange() { | |||
return futureHeader.getAssociatedRange(); | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public CFHeader12Record clone() { | |||
CFHeader12Record result = new CFHeader12Record(); | |||
result.futureHeader = (FtrHeader)futureHeader.clone(); | |||
super.copyTo(result); | |||
return result; | |||
return copy(); | |||
} | |||
@Override | |||
public CFHeader12Record copy() { | |||
return new CFHeader12Record(this); | |||
} | |||
} |
@@ -21,20 +21,28 @@ import org.apache.poi.ss.util.CellRangeAddress; | |||
import org.apache.poi.ss.util.CellRangeAddressList; | |||
import org.apache.poi.ss.util.CellRangeUtil; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* Parent of Conditional Formatting Header records, | |||
* {@link CFHeaderRecord} and {@link CFHeader12Record}. | |||
*/ | |||
public abstract class CFHeaderBase extends StandardRecord implements Cloneable { | |||
public abstract class CFHeaderBase extends StandardRecord { | |||
private int field_1_numcf; | |||
private int field_2_need_recalculation_and_id; | |||
private CellRangeAddress field_3_enclosing_cell_range; | |||
private CellRangeAddressList field_4_cell_ranges; | |||
/** Creates new CFHeaderBase */ | |||
protected CFHeaderBase() { | |||
protected CFHeaderBase() {} | |||
protected CFHeaderBase(CFHeaderBase other) { | |||
super(other); | |||
field_1_numcf = other.field_1_numcf; | |||
field_2_need_recalculation_and_id = other.field_2_need_recalculation_and_id; | |||
field_3_enclosing_cell_range = other.field_3_enclosing_cell_range.copy(); | |||
field_4_cell_ranges = other.field_4_cell_ranges.copy(); | |||
} | |||
protected CFHeaderBase(CellRangeAddress[] regions, int nRules) { | |||
CellRangeAddress[] mergeCellRanges = CellRangeUtil.mergeCellRanges(regions); | |||
setCellRanges(mergeCellRanges); | |||
@@ -97,7 +105,7 @@ public abstract class CFHeaderBase extends StandardRecord implements Cloneable { | |||
} | |||
/** | |||
* Set cell ranges list to a single cell range and | |||
* Set cell ranges list to a single cell range and | |||
* modify the enclosing cell range accordingly. | |||
* @param cellRanges - list of CellRange objects | |||
*/ | |||
@@ -151,13 +159,12 @@ public abstract class CFHeaderBase extends StandardRecord implements Cloneable { | |||
field_4_cell_ranges.serialize(out); | |||
} | |||
protected void copyTo(CFHeaderBase result) { | |||
result.field_1_numcf = field_1_numcf; | |||
result.field_2_need_recalculation_and_id = field_2_need_recalculation_and_id; | |||
result.field_3_enclosing_cell_range = field_3_enclosing_cell_range.copy(); | |||
result.field_4_cell_ranges = field_4_cell_ranges.copy(); | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public abstract CFHeaderBase clone(); | |||
@Override | |||
public abstract CFHeaderBase clone(); // NOSONAR | |||
public abstract CFHeaderBase copy(); | |||
} |
@@ -18,19 +18,24 @@ | |||
package org.apache.poi.hssf.record; | |||
import org.apache.poi.ss.util.CellRangeAddress; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* Conditional Formatting Header record CFHEADER (0x01B0). | |||
* Used to describe a {@link CFRuleRecord}. | |||
* @see CFHeader12Record | |||
*/ | |||
public final class CFHeaderRecord extends CFHeaderBase implements Cloneable { | |||
public final class CFHeaderRecord extends CFHeaderBase { | |||
public static final short sid = 0x01B0; | |||
/** Creates new CFHeaderRecord */ | |||
public CFHeaderRecord() { | |||
createEmpty(); | |||
} | |||
public CFHeaderRecord(CFHeaderRecord other) { | |||
super(other); | |||
} | |||
public CFHeaderRecord(CellRangeAddress[] regions, int nRules) { | |||
super(regions, nRules); | |||
} | |||
@@ -48,9 +53,15 @@ public final class CFHeaderRecord extends CFHeaderBase implements Cloneable { | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public CFHeaderRecord clone() { | |||
CFHeaderRecord result = new CFHeaderRecord(); | |||
super.copyTo(result); | |||
return result; | |||
return copy(); | |||
} | |||
@Override | |||
public CFHeaderRecord copy() { | |||
return new CFHeaderRecord(this); | |||
} | |||
} |
@@ -39,18 +39,19 @@ import org.apache.poi.util.HexDump; | |||
import org.apache.poi.util.IOUtils; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.POILogger; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* Conditional Formatting v12 Rule Record (0x087A). | |||
* | |||
* Conditional Formatting v12 Rule Record (0x087A). | |||
* | |||
* <p>This is for newer-style Excel conditional formattings, | |||
* from Excel 2007 onwards. | |||
* | |||
* | |||
* <p>{@link CFRuleRecord} is used where the condition type is | |||
* {@link #CONDITION_TYPE_CELL_VALUE_IS} or {@link #CONDITION_TYPE_FORMULA}, | |||
* this is only used for the other types | |||
*/ | |||
public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cloneable { | |||
public final class CFRule12Record extends CFRuleBase implements FutureRecord { | |||
//arbitrarily selected; may need to increase | |||
private static final int MAX_RECORD_LENGTH = 100_000; | |||
@@ -66,14 +67,35 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl | |||
private int template_type; | |||
private byte template_param_length; | |||
private byte[] template_params; | |||
private DataBarFormatting data_bar; | |||
private IconMultiStateFormatting multistate; | |||
private ColorGradientFormatting color_gradient; | |||
// TODO Parse this, see #58150 | |||
private byte[] filter_data; | |||
/** Creates new CFRuleRecord */ | |||
public CFRule12Record(CFRule12Record other) { | |||
super(other); | |||
futureHeader = (other.futureHeader == null) ? null : other.futureHeader.copy(); | |||
// use min() to gracefully handle cases where the length-property and the array-length do not match | |||
// we saw some such files in circulation | |||
ext_formatting_length = Math.min(other.ext_formatting_length, other.ext_formatting_data.length); | |||
ext_formatting_data = other.ext_formatting_data.clone(); | |||
formula_scale = other.formula_scale.copy(); | |||
ext_opts = other.ext_opts; | |||
priority = other.priority; | |||
template_type = other.template_type; | |||
template_param_length = other.template_param_length; | |||
template_params = (other.template_params == null) ? null : other.template_params.clone(); | |||
color_gradient = (other.color_gradient == null) ? null : other.color_gradient.copy(); | |||
multistate = (other.multistate == null) ? null : other.multistate.copy(); | |||
data_bar = (other.data_bar == null) ? null : other.data_bar.copy(); | |||
filter_data = (other.filter_data == null) ? null : other.filter_data.clone(); | |||
} | |||
private CFRule12Record(byte conditionType, byte comparisonOperation) { | |||
super(conditionType, comparisonOperation); | |||
setDefaults(); | |||
@@ -84,15 +106,17 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl | |||
setDefaults(); | |||
this.formula_scale = Formula.create(formulaScale); | |||
} | |||
private void setDefaults() { | |||
futureHeader = new FtrHeader(); | |||
futureHeader.setRecordType(sid); | |||
ext_formatting_length = 0; | |||
ext_formatting_data = new byte[4]; | |||
formula_scale = Formula.create(Ptg.EMPTY_PTG_ARRAY); | |||
ext_opts = 0; | |||
priority = 0; | |||
template_type = getConditionType(); | |||
@@ -102,10 +126,10 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl | |||
/** | |||
* Creates a new comparison operation rule | |||
* | |||
* | |||
* @param sheet the sheet | |||
* @param formulaText the first formula text | |||
* | |||
* | |||
* @return a new comparison operation rule | |||
*/ | |||
public static CFRule12Record create(HSSFSheet sheet, String formulaText) { | |||
@@ -113,34 +137,34 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl | |||
return new CFRule12Record(CONDITION_TYPE_FORMULA, ComparisonOperator.NO_COMPARISON, | |||
formula1, null, null); | |||
} | |||
/** | |||
* Creates a new comparison operation rule | |||
* | |||
* | |||
* @param sheet the sheet | |||
* @param comparisonOperation the comparison operation | |||
* @param formulaText1 the first formula text | |||
* @param formulaText2 the second formula text | |||
* | |||
* | |||
* @return a new comparison operation rule | |||
*/ | |||
public static CFRule12Record create(HSSFSheet sheet, byte comparisonOperation, | |||
String formulaText1, String formulaText2) { | |||
Ptg[] formula1 = parseFormula(formulaText1, sheet); | |||
Ptg[] formula2 = parseFormula(formulaText2, sheet); | |||
return new CFRule12Record(CONDITION_TYPE_CELL_VALUE_IS, comparisonOperation, | |||
return new CFRule12Record(CONDITION_TYPE_CELL_VALUE_IS, comparisonOperation, | |||
formula1, formula2, null); | |||
} | |||
/** | |||
* Creates a new comparison operation rule | |||
* | |||
* | |||
* @param sheet the sheet | |||
* @param comparisonOperation the comparison operation | |||
* @param formulaText1 the first formula text | |||
* @param formulaText2 the second formula text | |||
* @param formulaTextScale the scale to apply for the comparison | |||
* | |||
* | |||
* @return a new comparison operation rule | |||
*/ | |||
public static CFRule12Record create(HSSFSheet sheet, byte comparisonOperation, | |||
@@ -148,43 +172,43 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl | |||
Ptg[] formula1 = parseFormula(formulaText1, sheet); | |||
Ptg[] formula2 = parseFormula(formulaText2, sheet); | |||
Ptg[] formula3 = parseFormula(formulaTextScale, sheet); | |||
return new CFRule12Record(CONDITION_TYPE_CELL_VALUE_IS, comparisonOperation, | |||
return new CFRule12Record(CONDITION_TYPE_CELL_VALUE_IS, comparisonOperation, | |||
formula1, formula2, formula3); | |||
} | |||
/** | |||
* Creates a new Data Bar formatting | |||
* | |||
* | |||
* @param sheet the sheet | |||
* @param color the data bar color | |||
* | |||
* | |||
* @return a new Data Bar formatting | |||
*/ | |||
public static CFRule12Record create(HSSFSheet sheet, ExtendedColor color) { | |||
CFRule12Record r = new CFRule12Record(CONDITION_TYPE_DATA_BAR, | |||
CFRule12Record r = new CFRule12Record(CONDITION_TYPE_DATA_BAR, | |||
ComparisonOperator.NO_COMPARISON); | |||
DataBarFormatting dbf = r.createDataBarFormatting(); | |||
dbf.setColor(color); | |||
dbf.setPercentMin((byte)0); | |||
dbf.setPercentMax((byte)100); | |||
DataBarThreshold min = new DataBarThreshold(); | |||
min.setType(RangeType.MIN.id); | |||
dbf.setThresholdMin(min); | |||
DataBarThreshold max = new DataBarThreshold(); | |||
max.setType(RangeType.MAX.id); | |||
dbf.setThresholdMax(max); | |||
return r; | |||
} | |||
/** | |||
* Creates a new Icon Set / Multi-State formatting | |||
* | |||
* | |||
* @param sheet the sheet | |||
* @param iconSet the icon set | |||
* | |||
* | |||
* @return a new Icon Set / Multi-State formatting | |||
*/ | |||
public static CFRule12Record create(HSSFSheet sheet, IconSet iconSet) { | |||
@@ -192,20 +216,20 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl | |||
for (int i=0; i<ts.length; i++) { | |||
ts[i] = new IconMultiStateThreshold(); | |||
} | |||
CFRule12Record r = new CFRule12Record(CONDITION_TYPE_ICON_SET, | |||
CFRule12Record r = new CFRule12Record(CONDITION_TYPE_ICON_SET, | |||
ComparisonOperator.NO_COMPARISON); | |||
IconMultiStateFormatting imf = r.createMultiStateFormatting(); | |||
imf.setIconSet(iconSet); | |||
imf.setThresholds(ts); | |||
return r; | |||
} | |||
/** | |||
* Creates a new Color Scale / Color Gradient formatting | |||
* | |||
* | |||
* @param sheet the sheet | |||
* | |||
* | |||
* @return a new Color Scale / Color Gradient formatting | |||
*/ | |||
public static CFRule12Record createColorScale(HSSFSheet sheet) { | |||
@@ -216,8 +240,8 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl | |||
ts[i] = new ColorGradientThreshold(); | |||
colors[i] = new ExtendedColor(); | |||
} | |||
CFRule12Record r = new CFRule12Record(CONDITION_TYPE_COLOR_SCALE, | |||
CFRule12Record r = new CFRule12Record(CONDITION_TYPE_COLOR_SCALE, | |||
ComparisonOperator.NO_COMPARISON); | |||
ColorGradientFormatting cgf = r.createColorGradientFormatting(); | |||
cgf.setNumControlPoints(numPoints); | |||
@@ -232,7 +256,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl | |||
setComparisonOperation(in.readByte()); | |||
int field_3_formula1_len = in.readUShort(); | |||
int field_4_formula2_len = in.readUShort(); | |||
ext_formatting_length = in.readInt(); | |||
ext_formatting_data = new byte[0]; | |||
if (ext_formatting_length == 0) { | |||
@@ -245,13 +269,13 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl | |||
in.readFully(ext_formatting_data); | |||
} | |||
} | |||
setFormula1(Formula.read(field_3_formula1_len, in)); | |||
setFormula2(Formula.read(field_4_formula2_len, in)); | |||
int formula_scale_len = in.readUShort(); | |||
formula_scale = Formula.read(formula_scale_len, in); | |||
ext_opts = in.readByte(); | |||
priority = in.readUShort(); | |||
template_type = in.readUShort(); | |||
@@ -263,7 +287,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl | |||
logger.log(POILogger.WARN, "CF Rule v12 template params length should be 0 or 16, found " + template_param_length); | |||
in.readRemainder(); | |||
} | |||
byte type = getConditionType(); | |||
if (type == CONDITION_TYPE_COLOR_SCALE) { | |||
color_gradient = new ColorGradientFormatting(in); | |||
@@ -275,7 +299,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl | |||
multistate = new IconMultiStateFormatting(in); | |||
} | |||
} | |||
public boolean containsDataBarBlock() { | |||
return (data_bar != null); | |||
} | |||
@@ -284,7 +308,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl | |||
} | |||
public DataBarFormatting createDataBarFormatting() { | |||
if (data_bar != null) return data_bar; | |||
// Convert, setup and return | |||
setConditionType(CONDITION_TYPE_DATA_BAR); | |||
data_bar = new DataBarFormatting(); | |||
@@ -299,7 +323,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl | |||
} | |||
public IconMultiStateFormatting createMultiStateFormatting() { | |||
if (multistate != null) return multistate; | |||
// Convert, setup and return | |||
setConditionType(CONDITION_TYPE_ICON_SET); | |||
multistate = new IconMultiStateFormatting(); | |||
@@ -314,7 +338,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl | |||
} | |||
public ColorGradientFormatting createColorGradientFormatting() { | |||
if (color_gradient != null) return color_gradient; | |||
// Convert, setup and return | |||
setConditionType(CONDITION_TYPE_COLOR_SCALE); | |||
color_gradient = new ColorGradientFormatting(); | |||
@@ -356,7 +380,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl | |||
*/ | |||
public void serialize(LittleEndianOutput out) { | |||
futureHeader.serialize(out); | |||
int formula1Len=getFormulaSize(getFormula1()); | |||
int formula2Len=getFormulaSize(getFormula2()); | |||
@@ -364,7 +388,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl | |||
out.writeByte(getComparisonOperation()); | |||
out.writeShort(formula1Len); | |||
out.writeShort(formula2Len); | |||
// TODO Update ext_formatting_length | |||
if (ext_formatting_length == 0) { | |||
out.writeInt(0); | |||
@@ -374,18 +398,18 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl | |||
serializeFormattingBlock(out); | |||
out.write(ext_formatting_data); | |||
} | |||
getFormula1().serializeTokens(out); | |||
getFormula2().serializeTokens(out); | |||
out.writeShort(getFormulaSize(formula_scale)); | |||
formula_scale.serializeTokens(out); | |||
out.writeByte(ext_opts); | |||
out.writeShort(priority); | |||
out.writeShort(template_type); | |||
out.writeByte(template_param_length); | |||
out.write(template_params); | |||
byte type = getConditionType(); | |||
if (type == CONDITION_TYPE_COLOR_SCALE) { | |||
color_gradient.serialize(out); | |||
@@ -409,7 +433,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl | |||
len += getFormulaSize(getFormula2()); | |||
len += 2 + getFormulaSize(formula_scale); | |||
len += 6 + template_params.length; | |||
byte type = getConditionType(); | |||
if (type == CONDITION_TYPE_COLOR_SCALE) { | |||
len += color_gradient.getDataLength(); | |||
@@ -461,44 +485,18 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public CFRule12Record clone() { | |||
CFRule12Record rec = new CFRule12Record(getConditionType(), getComparisonOperation()); | |||
rec.futureHeader.setAssociatedRange(futureHeader.getAssociatedRange().copy()); | |||
super.copyTo(rec); | |||
// use min() to gracefully handle cases where the length-property and the array-length do not match | |||
// we saw some such files in circulation | |||
rec.ext_formatting_length = Math.min(ext_formatting_length, ext_formatting_data.length); | |||
rec.ext_formatting_data = IOUtils.safelyAllocate(ext_formatting_length, MAX_RECORD_LENGTH); | |||
System.arraycopy(ext_formatting_data, 0, rec.ext_formatting_data, 0, rec.ext_formatting_length); | |||
rec.formula_scale = formula_scale.copy(); | |||
rec.ext_opts = ext_opts; | |||
rec.priority = priority; | |||
rec.template_type = template_type; | |||
rec.template_param_length = template_param_length; | |||
rec.template_params = IOUtils.safelyAllocate(template_param_length, MAX_RECORD_LENGTH); | |||
System.arraycopy(template_params, 0, rec.template_params, 0, template_param_length); | |||
return copy(); | |||
} | |||
if (color_gradient != null) { | |||
rec.color_gradient = (ColorGradientFormatting)color_gradient.clone(); | |||
} | |||
if (multistate != null) { | |||
rec.multistate = (IconMultiStateFormatting)multistate.clone(); | |||
} | |||
if (data_bar != null) { | |||
rec.data_bar = (DataBarFormatting)data_bar.clone(); | |||
} | |||
if (filter_data != null) { | |||
rec.filter_data = IOUtils.safelyAllocate(filter_data.length, MAX_RECORD_LENGTH); | |||
System.arraycopy(filter_data, 0, rec.filter_data, 0, filter_data.length); | |||
} | |||
return rec; | |||
@Override | |||
public CFRule12Record copy() { | |||
return new CFRule12Record(this); | |||
} | |||
public short getFutureRecordType() { | |||
return futureHeader.getRecordType(); | |||
} |
@@ -30,32 +30,31 @@ import org.apache.poi.util.BitFieldFactory; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.POILogFactory; | |||
import org.apache.poi.util.POILogger; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* Conditional Formatting Rules. This can hold old-style rules | |||
* | |||
* | |||
* | |||
* | |||
* <p>This is for the older-style Excel conditional formattings, | |||
* new-style (Excel 2007+) also make use of {@link CFRule12Record} | |||
* for their rules.</p> | |||
*/ | |||
public abstract class CFRuleBase extends StandardRecord implements Cloneable { | |||
public abstract class CFRuleBase extends StandardRecord { | |||
// FIXME: Merge with org.apache.poi.ss.usermodel.ComparisonOperator and rewrite as an enum | |||
public static final class ComparisonOperator { | |||
public static final byte NO_COMPARISON = 0; | |||
public static final byte BETWEEN = 1; | |||
public static final byte NOT_BETWEEN = 2; | |||
public static final byte EQUAL = 3; | |||
public static final byte NOT_EQUAL = 4; | |||
public static final byte GT = 5; | |||
public static final byte LT = 6; | |||
public static final byte GE = 7; | |||
public static final byte LE = 8; | |||
private static final byte max_operator = 8; | |||
public interface ComparisonOperator { | |||
byte NO_COMPARISON = 0; | |||
byte BETWEEN = 1; | |||
byte NOT_BETWEEN = 2; | |||
byte EQUAL = 3; | |||
byte NOT_EQUAL = 4; | |||
byte GT = 5; | |||
byte LT = 6; | |||
byte GE = 7; | |||
byte LE = 8; | |||
byte max_operator = 8; | |||
} | |||
protected static final POILogger logger = POILogFactory.getLogger(CFRuleBase.class); | |||
private byte condition_type; | |||
// The only kinds that CFRuleRecord handles | |||
public static final byte CONDITION_TYPE_CELL_VALUE_IS = 1; | |||
public static final byte CONDITION_TYPE_FORMULA = 2; | |||
@@ -65,8 +64,6 @@ public abstract class CFRuleBase extends StandardRecord implements Cloneable { | |||
public static final byte CONDITION_TYPE_FILTER = 5; | |||
public static final byte CONDITION_TYPE_ICON_SET = 6; | |||
private byte comparison_operator; | |||
public static final int TEMPLATE_CELL_VALUE = 0x0000; | |||
public static final int TEMPLATE_FORMULA = 0x0001; | |||
public static final int TEMPLATE_COLOR_SCALE_FORMATTING = 0x0002; | |||
@@ -94,7 +91,9 @@ public abstract class CFRuleBase extends StandardRecord implements Cloneable { | |||
public static final int TEMPLATE_DUPLICATE_VALUES = 0x001B; | |||
public static final int TEMPLATE_ABOVE_OR_EQUAL_TO_AVERAGE = 0x001D; | |||
public static final int TEMPLATE_BELOW_OR_EQUAL_TO_AVERAGE = 0x001E; | |||
protected static final POILogger logger = POILogFactory.getLogger(CFRuleBase.class); | |||
static final BitField modificationBits = bf(0x003FFFFF); // Bits: font,align,bord,patt,prot | |||
static final BitField alignHor = bf(0x00000001); // 0 = Horizontal alignment modified | |||
static final BitField alignVer = bf(0x00000002); // 0 = Vertical alignment modified | |||
@@ -129,19 +128,24 @@ public abstract class CFRuleBase extends StandardRecord implements Cloneable { | |||
return BitFieldFactory.getInstance(i); | |||
} | |||
private byte condition_type; | |||
private byte comparison_operator; | |||
protected int formatting_options; | |||
protected short formatting_not_used; // TODO Decode this properly | |||
// TODO Decode this properly | |||
protected short formatting_not_used; | |||
protected FontFormatting _fontFormatting; | |||
protected BorderFormatting _borderFormatting; | |||
protected PatternFormatting _patternFormatting; | |||
private Formula formula1; | |||
private Formula formula2; | |||
/** | |||
* Creates new CFRuleRecord | |||
* | |||
* | |||
* @param conditionType the condition type | |||
* @param comparisonOperation the comparison operation | |||
*/ | |||
@@ -151,19 +155,34 @@ public abstract class CFRuleBase extends StandardRecord implements Cloneable { | |||
formula1 = Formula.create(Ptg.EMPTY_PTG_ARRAY); | |||
formula2 = Formula.create(Ptg.EMPTY_PTG_ARRAY); | |||
} | |||
protected CFRuleBase(byte conditionType, byte comparisonOperation, Ptg[] formula1, Ptg[] formula2) { | |||
this(conditionType, comparisonOperation); | |||
this.formula1 = Formula.create(formula1); | |||
this.formula2 = Formula.create(formula2); | |||
} | |||
protected CFRuleBase() {} | |||
protected CFRuleBase(CFRuleBase other) { | |||
super(other); | |||
setConditionType(other.getConditionType()); | |||
setComparisonOperation(other.getComparisonOperation()); | |||
formatting_options = other.formatting_options; | |||
formatting_not_used = other.formatting_not_used; | |||
_fontFormatting = (!other.containsFontFormattingBlock()) ? null : other.getFontFormatting().copy(); | |||
_borderFormatting = (!other.containsBorderFormattingBlock()) ? null : other.getBorderFormatting().copy(); | |||
_patternFormatting = (!other.containsPatternFormattingBlock()) ? null : other.getPatternFormatting().copy(); | |||
formula1 = other.getFormula1().copy(); | |||
formula2 = other.getFormula2().copy(); | |||
} | |||
protected int readFormatOptions(RecordInputStream in) { | |||
formatting_options = in.readInt(); | |||
formatting_not_used = in.readShort(); | |||
int len = 6; | |||
if (containsFontFormattingBlock()) { | |||
_fontFormatting = new FontFormatting(in); | |||
len += _fontFormatting.getDataLength(); | |||
@@ -178,7 +197,7 @@ public abstract class CFRuleBase extends StandardRecord implements Cloneable { | |||
_patternFormatting = new PatternFormatting(in); | |||
len += _patternFormatting.getDataLength(); | |||
} | |||
return len; | |||
} | |||
@@ -187,10 +206,8 @@ public abstract class CFRuleBase extends StandardRecord implements Cloneable { | |||
} | |||
protected void setConditionType(byte condition_type) { | |||
if ((this instanceof CFRuleRecord)) { | |||
if (condition_type == CONDITION_TYPE_CELL_VALUE_IS || | |||
condition_type == CONDITION_TYPE_FORMULA) { | |||
// Good, valid combination | |||
} else { | |||
if (!(condition_type == CONDITION_TYPE_CELL_VALUE_IS || | |||
condition_type == CONDITION_TYPE_FORMULA)) { | |||
throw new IllegalArgumentException("CFRuleRecord only accepts Value-Is and Formula types"); | |||
} | |||
} | |||
@@ -201,7 +218,7 @@ public abstract class CFRuleBase extends StandardRecord implements Cloneable { | |||
if (operation < 0 || operation > ComparisonOperator.max_operator) | |||
throw new IllegalArgumentException( | |||
"Valid operators are only in the range 0 to " +ComparisonOperator.max_operator); | |||
this.comparison_operator = operation; | |||
} | |||
public byte getComparisonOperation() { | |||
@@ -351,7 +368,7 @@ public abstract class CFRuleBase extends StandardRecord implements Cloneable { | |||
private void setOptionFlag(boolean flag, BitField field) { | |||
formatting_options = field.setBoolean(formatting_options, flag); | |||
} | |||
protected int getFormattingBlockSize() { | |||
return 6 + | |||
(containsFontFormattingBlock()?_fontFormatting.getRawRecord().length:0)+ | |||
@@ -375,7 +392,7 @@ public abstract class CFRuleBase extends StandardRecord implements Cloneable { | |||
_patternFormatting.serialize(out); | |||
} | |||
} | |||
/** | |||
* get the stack of the 1st expression as a list | |||
* | |||
@@ -440,27 +457,13 @@ public abstract class CFRuleBase extends StandardRecord implements Cloneable { | |||
int sheetIndex = sheet.getWorkbook().getSheetIndex(sheet); | |||
return HSSFFormulaParser.parse(formula, sheet.getWorkbook(), FormulaType.CELL, sheetIndex); | |||
} | |||
protected void copyTo(CFRuleBase rec) { | |||
rec.condition_type = condition_type; | |||
rec.comparison_operator = comparison_operator; | |||
rec.formatting_options = formatting_options; | |||
rec.formatting_not_used = formatting_not_used; | |||
if (containsFontFormattingBlock()) { | |||
rec._fontFormatting = _fontFormatting.clone(); | |||
} | |||
if (containsBorderFormattingBlock()) { | |||
rec._borderFormatting = _borderFormatting.clone(); | |||
} | |||
if (containsPatternFormattingBlock()) { | |||
rec._patternFormatting = (PatternFormatting) _patternFormatting.clone(); | |||
} | |||
rec.setFormula1(getFormula1().copy()); | |||
rec.setFormula2(getFormula2().copy()); | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public abstract CFRuleBase clone(); | |||
@Override | |||
public abstract CFRuleBase copy(); | |||
} |
@@ -23,18 +23,22 @@ import org.apache.poi.hssf.usermodel.HSSFSheet; | |||
import org.apache.poi.ss.formula.Formula; | |||
import org.apache.poi.ss.formula.ptg.Ptg; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* Conditional Formatting Rule Record (0x01B1). | |||
* | |||
* Conditional Formatting Rule Record (0x01B1). | |||
* | |||
* <p>This is for the older-style Excel conditional formattings, | |||
* new-style (Excel 2007+) also make use of {@link CFRule12Record} | |||
* for their rules.</p> | |||
*/ | |||
public final class CFRuleRecord extends CFRuleBase implements Cloneable { | |||
public final class CFRuleRecord extends CFRuleBase { | |||
public static final short sid = 0x01B1; | |||
/** Creates new CFRuleRecord */ | |||
public CFRuleRecord(CFRuleRecord other) { | |||
super(other); | |||
} | |||
private CFRuleRecord(byte conditionType, byte comparisonOperation) { | |||
super(conditionType, comparisonOperation); | |||
setDefaults(); | |||
@@ -59,10 +63,10 @@ public final class CFRuleRecord extends CFRuleBase implements Cloneable { | |||
/** | |||
* Creates a new comparison operation rule | |||
* | |||
* | |||
* @param sheet the sheet | |||
* @param formulaText the formula text | |||
* | |||
* | |||
* @return a new comparison operation rule | |||
*/ | |||
public static CFRuleRecord create(HSSFSheet sheet, String formulaText) { | |||
@@ -72,12 +76,12 @@ public final class CFRuleRecord extends CFRuleBase implements Cloneable { | |||
} | |||
/** | |||
* Creates a new comparison operation rule | |||
* | |||
* | |||
* @param sheet the sheet | |||
* @param comparisonOperation the comparison operation | |||
* @param formulaText1 the first formula text | |||
* @param formulaText2 the second formula text | |||
* | |||
* | |||
* @return a new comparison operation rule | |||
*/ | |||
public static CFRuleRecord create(HSSFSheet sheet, byte comparisonOperation, | |||
@@ -120,7 +124,7 @@ public final class CFRuleRecord extends CFRuleBase implements Cloneable { | |||
out.writeByte(getComparisonOperation()); | |||
out.writeShort(formula1Len); | |||
out.writeShort(formula2Len); | |||
serializeFormattingBlock(out); | |||
getFormula1().serializeTokens(out); | |||
@@ -156,9 +160,15 @@ public final class CFRuleRecord extends CFRuleBase implements Cloneable { | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public CFRuleRecord clone() { | |||
CFRuleRecord rec = new CFRuleRecord(getConditionType(), getComparisonOperation()); | |||
super.copyTo(rec); | |||
return rec; | |||
return copy(); | |||
} | |||
@Override | |||
public CFRuleRecord copy() { | |||
return new CFRuleRecord(this); | |||
} | |||
} |
@@ -19,30 +19,26 @@ package org.apache.poi.hssf.record; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
/** | |||
* XCT - CRN Count <P> | |||
* | |||
* REFERENCE: 5.114<P> | |||
* | |||
* @author Josh Micich | |||
* XCT - CRN Count | |||
*/ | |||
public final class CRNCountRecord extends StandardRecord { | |||
public final static short sid = 0x59; | |||
public static final short sid = 0x59; | |||
private static final short DATA_SIZE = 4; | |||
private int field_1_number_crn_records; | |||
private int field_2_sheet_table_index; | |||
private int field_1_number_crn_records; | |||
private int field_2_sheet_table_index; | |||
public CRNCountRecord() { | |||
throw new RuntimeException("incomplete code"); | |||
private CRNCountRecord() { | |||
// incomplete code | |||
} | |||
public int getNumberOfCRNs() { | |||
return field_1_number_crn_records; | |||
public CRNCountRecord(CRNCountRecord other) { | |||
super(other); | |||
field_1_number_crn_records = other.field_1_number_crn_records; | |||
field_2_sheet_table_index = other.field_2_sheet_table_index; | |||
} | |||
public CRNCountRecord(RecordInputStream in) { | |||
field_1_number_crn_records = in.readShort(); | |||
if(field_1_number_crn_records < 0) { | |||
@@ -53,6 +49,9 @@ public final class CRNCountRecord extends StandardRecord { | |||
field_2_sheet_table_index = in.readShort(); | |||
} | |||
public int getNumberOfCRNs() { | |||
return field_1_number_crn_records; | |||
} | |||
public String toString() { | |||
StringBuilder sb = new StringBuilder(); | |||
@@ -77,4 +76,9 @@ public final class CRNCountRecord extends StandardRecord { | |||
public short getSid() { | |||
return sid; | |||
} | |||
@Override | |||
public CRNCountRecord copy() { | |||
return new CRNCountRecord(this); | |||
} | |||
} |
@@ -21,27 +21,30 @@ import org.apache.poi.ss.formula.constant.ConstantValueParser; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
/** | |||
* Title: CRN(0x005A)<p> | |||
* Description: This record stores the contents of an external cell or cell range<p> | |||
* REFERENCE: OOO 5.23 | |||
* This record stores the contents of an external cell or cell range | |||
*/ | |||
public final class CRNRecord extends StandardRecord { | |||
public final static short sid = 0x005A; | |||
public static final short sid = 0x005A; | |||
private int field_1_last_column_index; | |||
private int field_2_first_column_index; | |||
private int field_3_row_index; | |||
private int field_1_last_column_index; | |||
private int field_2_first_column_index; | |||
private int field_3_row_index; | |||
private Object[] field_4_constant_values; | |||
public CRNRecord() { | |||
throw new RuntimeException("incomplete code"); | |||
private CRNRecord() { | |||
// incomplete code | |||
} | |||
public int getNumberOfCRNs() { | |||
return field_1_last_column_index; | |||
public CRNRecord(CRNRecord other) { | |||
super(other); | |||
field_1_last_column_index = other.field_1_last_column_index; | |||
field_2_first_column_index = other.field_2_first_column_index; | |||
field_3_row_index = other.field_3_row_index; | |||
// field_4_constant_values are instances of Double, Boolean, String, ErrorCode, | |||
// i.e. they are immutable and can their references can be simply cloned | |||
field_4_constant_values = (other.field_4_constant_values == null) ? null : other.field_4_constant_values.clone(); | |||
} | |||
public CRNRecord(RecordInputStream in) { | |||
field_1_last_column_index = in.readUByte(); | |||
field_2_first_column_index = in.readUByte(); | |||
@@ -50,6 +53,9 @@ public final class CRNRecord extends StandardRecord { | |||
field_4_constant_values = ConstantValueParser.parse(in, nValues); | |||
} | |||
public int getNumberOfCRNs() { | |||
return field_1_last_column_index; | |||
} | |||
public String toString() { | |||
StringBuilder sb = new StringBuilder(); | |||
@@ -77,4 +83,9 @@ public final class CRNRecord extends StandardRecord { | |||
public short getSid() { | |||
return sid; | |||
} | |||
@Override | |||
public CRNRecord copy() { | |||
return new CRNRecord(this); | |||
} | |||
} |
@@ -15,34 +15,37 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.hssf.record; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* Title: Calc Count Record | |||
* Description: Specifies the maximum times the gui should perform a formula | |||
* recalculation. For instance: in the case a formula includes | |||
* cells that are themselves a result of a formula and a value | |||
* changes. This is essentially a failsafe against an infinate | |||
* loop in the event the formulas are not independant. <P> | |||
* REFERENCE: PG 292 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> | |||
* Specifies the maximum times the gui should perform a formula recalculation. | |||
* For instance: in the case a formula includes cells that are themselves a result of a formula and | |||
* a value changes. This is essentially a failsafe against an infinite loop in the event the formulas | |||
* are not independent. | |||
* | |||
* @version 2.0-pre | |||
* @see org.apache.poi.hssf.record.CalcModeRecord | |||
* @see CalcModeRecord | |||
*/ | |||
public final class CalcCountRecord extends StandardRecord implements Cloneable { | |||
public final static short sid = 0xC; | |||
private short field_1_iterations; | |||
public final class CalcCountRecord extends StandardRecord { | |||
public static final short sid = 0xC; | |||
public CalcCountRecord() | |||
{ | |||
private short field_1_iterations; | |||
public CalcCountRecord() {} | |||
public CalcCountRecord(CalcCountRecord other) { | |||
super(other); | |||
field_1_iterations = other.field_1_iterations; | |||
} | |||
public CalcCountRecord(RecordInputStream in) | |||
{ | |||
public CalcCountRecord(RecordInputStream in) { | |||
field_1_iterations = in.readShort(); | |||
} | |||
@@ -91,9 +94,15 @@ public final class CalcCountRecord extends StandardRecord implements Cloneable { | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public CalcCountRecord clone() { | |||
CalcCountRecord rec = new CalcCountRecord(); | |||
rec.field_1_iterations = field_1_iterations; | |||
return rec; | |||
return copy(); | |||
} | |||
@Override | |||
public CalcCountRecord copy() { | |||
return new CalcCountRecord(this); | |||
} | |||
} |
@@ -15,52 +15,42 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.hssf.record; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* Title: Calc Mode Record<P> | |||
* Description: Tells the gui whether to calculate formulas | |||
* automatically, manually or automatically | |||
* except for tables.<P> | |||
* REFERENCE: PG 292 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> | |||
* @author Andrew C. Oliver (acoliver at apache dot org) | |||
* @author Jason Height (jheight at chariot dot net dot au) | |||
* Tells the gui whether to calculate formulas automatically, manually or automatically except for tables. | |||
* | |||
* @version 2.0-pre | |||
* @see org.apache.poi.hssf.record.CalcCountRecord | |||
* @see CalcCountRecord | |||
*/ | |||
public final class CalcModeRecord extends StandardRecord implements Cloneable { | |||
public final static short sid = 0xD; | |||
public final class CalcModeRecord extends StandardRecord { | |||
public static final short sid = 0xD; | |||
/** | |||
* manually calculate formulas (0) | |||
*/ | |||
/** manually calculate formulas (0) */ | |||
public static final short MANUAL = 0; | |||
public final static short MANUAL = 0; | |||
/** automatically calculate formulas (1) */ | |||
public static final short AUTOMATIC = 1; | |||
/** | |||
* automatically calculate formulas (1) | |||
*/ | |||
/** automatically calculate formulas except for tables (-1) */ | |||
public static final short AUTOMATIC_EXCEPT_TABLES = -1; | |||
public final static short AUTOMATIC = 1; | |||
private short field_1_calcmode; | |||
/** | |||
* automatically calculate formulas except for tables (-1) | |||
*/ | |||
public CalcModeRecord() {} | |||
public final static short AUTOMATIC_EXCEPT_TABLES = -1; | |||
private short field_1_calcmode; | |||
public CalcModeRecord() | |||
{ | |||
public CalcModeRecord(CalcModeRecord other) { | |||
super(other); | |||
field_1_calcmode = other.field_1_calcmode; | |||
} | |||
public CalcModeRecord(RecordInputStream in) | |||
{ | |||
public CalcModeRecord(RecordInputStream in) { | |||
field_1_calcmode = in.readShort(); | |||
} | |||
@@ -119,9 +109,15 @@ public final class CalcModeRecord extends StandardRecord implements Cloneable { | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public CalcModeRecord clone() { | |||
CalcModeRecord rec = new CalcModeRecord(); | |||
rec.field_1_calcmode = field_1_calcmode; | |||
return rec; | |||
return copy(); | |||
} | |||
@Override | |||
public CalcModeRecord copy() { | |||
return new CalcModeRecord(this); | |||
} | |||
} |
@@ -29,8 +29,13 @@ public abstract class CellRecord extends StandardRecord implements CellValueReco | |||
private int _columnIndex; | |||
private int _formatIndex; | |||
protected CellRecord() { | |||
// fields uninitialised | |||
protected CellRecord() {} | |||
protected CellRecord(CellRecord other) { | |||
super(other); | |||
_rowIndex = other.getRow(); | |||
_columnIndex = other.getColumn(); | |||
_formatIndex = other.getXFIndex(); | |||
} | |||
protected CellRecord(RecordInputStream in) { | |||
@@ -100,21 +105,21 @@ public abstract class CellRecord extends StandardRecord implements CellValueReco | |||
* Append specific debug info (used by {@link #toString()} for the value | |||
* contained in this record. Trailing new-line should not be appended | |||
* (superclass does that). | |||
* | |||
* | |||
* @param sb the StringBuilder to write to | |||
*/ | |||
protected abstract void appendValueText(StringBuilder sb); | |||
/** | |||
* Gets the debug info BIFF record type name (used by {@link #toString()}. | |||
* | |||
* | |||
* @return the record type name | |||
*/ | |||
protected abstract String getRecordName(); | |||
/** | |||
* writes out the value data for this cell record | |||
* | |||
* | |||
* @param out the output | |||
*/ | |||
protected abstract void serializeValue(LittleEndianOutput out); | |||
@@ -137,9 +142,6 @@ public abstract class CellRecord extends StandardRecord implements CellValueReco | |||
return 6 + getValueDataSize(); | |||
} | |||
protected final void copyBaseFields(CellRecord rec) { | |||
rec._rowIndex = _rowIndex; | |||
rec._columnIndex = _columnIndex; | |||
rec._formatIndex = _formatIndex; | |||
} | |||
@Override | |||
public abstract CellRecord copy(); | |||
} |
@@ -15,7 +15,7 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.hssf.record; | |||
@@ -23,33 +23,33 @@ import org.apache.poi.util.CodePageUtil; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
/** | |||
* Title: Codepage Record | |||
* <p>Description: the default characterset. for the workbook</p> | |||
* <p>REFERENCE: PG 293 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)</p> | |||
* <p>Use {@link CodePageUtil} to turn these values into Java code pages | |||
* to encode/decode strings.</p> | |||
* The default characterset. for the workbook<p> | |||
* | |||
* Use {@link CodePageUtil} to turn these values into Java code pages to encode/decode strings. | |||
* | |||
* @version 2.0-pre | |||
*/ | |||
public final class CodepageRecord | |||
extends StandardRecord | |||
{ | |||
public final static short sid = 0x42; | |||
private short field_1_codepage; // = 0; | |||
public final class CodepageRecord extends StandardRecord { | |||
public static final short sid = 0x42; | |||
/** | |||
* Excel 97+ (Biff 8) should always store strings as UTF-16LE or | |||
* compressed versions of that. As such, this should always be | |||
* 0x4b0 = UTF_16, except for files coming from older versions. | |||
*/ | |||
public final static short CODEPAGE = ( short ) 0x4b0; | |||
public static final short CODEPAGE = ( short ) 0x4b0; | |||
public CodepageRecord() | |||
{ | |||
private short field_1_codepage; | |||
public CodepageRecord() {} | |||
public CodepageRecord(CodepageRecord other) { | |||
super(other); | |||
field_1_codepage = other.field_1_codepage; | |||
} | |||
public CodepageRecord(RecordInputStream in) | |||
{ | |||
public CodepageRecord(RecordInputStream in) { | |||
field_1_codepage = in.readShort(); | |||
} | |||
@@ -100,4 +100,9 @@ public final class CodepageRecord | |||
{ | |||
return sid; | |||
} | |||
@Override | |||
public CodepageRecord copy() { | |||
return new CodepageRecord(this); | |||
} | |||
} |
@@ -17,27 +17,27 @@ | |||
package org.apache.poi.hssf.record; | |||
import org.apache.poi.util.HexDump; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.BitField; | |||
import org.apache.poi.util.BitFieldFactory; | |||
import org.apache.poi.util.HexDump; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* Title: COLINFO Record (0x007D)<p> | |||
* Description: Defines with width and formatting for a range of columns<p> | |||
* REFERENCE: PG 293 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) | |||
* Defines with width and formatting for a range of columns | |||
*/ | |||
public final class ColumnInfoRecord extends StandardRecord implements Cloneable { | |||
public final class ColumnInfoRecord extends StandardRecord { | |||
public static final short sid = 0x007D; | |||
private static final BitField hidden = BitFieldFactory.getInstance(0x01); | |||
private static final BitField outlevel = BitFieldFactory.getInstance(0x0700); | |||
private static final BitField collapsed = BitFieldFactory.getInstance(0x1000); | |||
private int _firstCol; | |||
private int _lastCol; | |||
private int _colWidth; | |||
private int _xfIndex; | |||
private int _options; | |||
private static final BitField hidden = BitFieldFactory.getInstance(0x01); | |||
private static final BitField outlevel = BitFieldFactory.getInstance(0x0700); | |||
private static final BitField collapsed = BitFieldFactory.getInstance(0x1000); | |||
// Excel seems write values 2, 10, and 260, even though spec says "must be zero" | |||
private int field_6_reserved; | |||
@@ -51,6 +51,16 @@ public final class ColumnInfoRecord extends StandardRecord implements Cloneable | |||
field_6_reserved = 2; // seems to be the most common value | |||
} | |||
public ColumnInfoRecord(ColumnInfoRecord other) { | |||
super(other); | |||
_firstCol = other._firstCol; | |||
_lastCol = other._lastCol; | |||
_colWidth = other._colWidth; | |||
_xfIndex = other._xfIndex; | |||
_options = other._options; | |||
field_6_reserved = other.field_6_reserved; | |||
} | |||
public ColumnInfoRecord(RecordInputStream in) { | |||
_firstCol = in.readUShort(); | |||
_lastCol = in.readUShort(); | |||
@@ -196,7 +206,7 @@ public final class ColumnInfoRecord extends StandardRecord implements Cloneable | |||
/** | |||
* @param other the format to match with | |||
* | |||
* | |||
* @return {@code true} if the format, options and column width match | |||
*/ | |||
public boolean formatMatches(ColumnInfoRecord other) { | |||
@@ -246,14 +256,15 @@ public final class ColumnInfoRecord extends StandardRecord implements Cloneable | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public ColumnInfoRecord clone() { | |||
ColumnInfoRecord rec = new ColumnInfoRecord(); | |||
rec._firstCol = _firstCol; | |||
rec._lastCol = _lastCol; | |||
rec._colWidth = _colWidth; | |||
rec._xfIndex = _xfIndex; | |||
rec._options = _options; | |||
rec.field_6_reserved = field_6_reserved; | |||
return rec; | |||
return copy(); | |||
} | |||
@Override | |||
public ColumnInfoRecord copy() { | |||
return new ColumnInfoRecord(this); | |||
} | |||
} |
@@ -23,50 +23,51 @@ import org.apache.poi.util.HexDump; | |||
import org.apache.poi.util.LittleEndianInput; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.RecordFormatException; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* The common object data record is used to store all common preferences for an excel object. | |||
*/ | |||
public final class CommonObjectDataSubRecord extends SubRecord implements Cloneable { | |||
public final static short sid = 0x0015; | |||
public final class CommonObjectDataSubRecord extends SubRecord { | |||
public static final short sid = 0x0015; | |||
private static final BitField locked = BitFieldFactory.getInstance(0x0001); | |||
private static final BitField printable = BitFieldFactory.getInstance(0x0010); | |||
private static final BitField autofill = BitFieldFactory.getInstance(0x2000); | |||
private static final BitField autoline = BitFieldFactory.getInstance(0x4000); | |||
public final static short OBJECT_TYPE_GROUP = 0; | |||
public final static short OBJECT_TYPE_LINE = 1; | |||
public final static short OBJECT_TYPE_RECTANGLE = 2; | |||
public final static short OBJECT_TYPE_OVAL = 3; | |||
public final static short OBJECT_TYPE_ARC = 4; | |||
public final static short OBJECT_TYPE_CHART = 5; | |||
public final static short OBJECT_TYPE_TEXT = 6; | |||
public final static short OBJECT_TYPE_BUTTON = 7; | |||
public final static short OBJECT_TYPE_PICTURE = 8; | |||
public final static short OBJECT_TYPE_POLYGON = 9; | |||
public final static short OBJECT_TYPE_RESERVED1 = 10; | |||
public final static short OBJECT_TYPE_CHECKBOX = 11; | |||
public final static short OBJECT_TYPE_OPTION_BUTTON = 12; | |||
public final static short OBJECT_TYPE_EDIT_BOX = 13; | |||
public final static short OBJECT_TYPE_LABEL = 14; | |||
public final static short OBJECT_TYPE_DIALOG_BOX = 15; | |||
public final static short OBJECT_TYPE_SPINNER = 16; | |||
public final static short OBJECT_TYPE_SCROLL_BAR = 17; | |||
public final static short OBJECT_TYPE_LIST_BOX = 18; | |||
public final static short OBJECT_TYPE_GROUP_BOX = 19; | |||
public final static short OBJECT_TYPE_COMBO_BOX = 20; | |||
public final static short OBJECT_TYPE_RESERVED2 = 21; | |||
public final static short OBJECT_TYPE_RESERVED3 = 22; | |||
public final static short OBJECT_TYPE_RESERVED4 = 23; | |||
public final static short OBJECT_TYPE_RESERVED5 = 24; | |||
public final static short OBJECT_TYPE_COMMENT = 25; | |||
public final static short OBJECT_TYPE_RESERVED6 = 26; | |||
public final static short OBJECT_TYPE_RESERVED7 = 27; | |||
public final static short OBJECT_TYPE_RESERVED8 = 28; | |||
public final static short OBJECT_TYPE_RESERVED9 = 29; | |||
public final static short OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING = 30; | |||
public static final short OBJECT_TYPE_GROUP = 0; | |||
public static final short OBJECT_TYPE_LINE = 1; | |||
public static final short OBJECT_TYPE_RECTANGLE = 2; | |||
public static final short OBJECT_TYPE_OVAL = 3; | |||
public static final short OBJECT_TYPE_ARC = 4; | |||
public static final short OBJECT_TYPE_CHART = 5; | |||
public static final short OBJECT_TYPE_TEXT = 6; | |||
public static final short OBJECT_TYPE_BUTTON = 7; | |||
public static final short OBJECT_TYPE_PICTURE = 8; | |||
public static final short OBJECT_TYPE_POLYGON = 9; | |||
public static final short OBJECT_TYPE_RESERVED1 = 10; | |||
public static final short OBJECT_TYPE_CHECKBOX = 11; | |||
public static final short OBJECT_TYPE_OPTION_BUTTON = 12; | |||
public static final short OBJECT_TYPE_EDIT_BOX = 13; | |||
public static final short OBJECT_TYPE_LABEL = 14; | |||
public static final short OBJECT_TYPE_DIALOG_BOX = 15; | |||
public static final short OBJECT_TYPE_SPINNER = 16; | |||
public static final short OBJECT_TYPE_SCROLL_BAR = 17; | |||
public static final short OBJECT_TYPE_LIST_BOX = 18; | |||
public static final short OBJECT_TYPE_GROUP_BOX = 19; | |||
public static final short OBJECT_TYPE_COMBO_BOX = 20; | |||
public static final short OBJECT_TYPE_RESERVED2 = 21; | |||
public static final short OBJECT_TYPE_RESERVED3 = 22; | |||
public static final short OBJECT_TYPE_RESERVED4 = 23; | |||
public static final short OBJECT_TYPE_RESERVED5 = 24; | |||
public static final short OBJECT_TYPE_COMMENT = 25; | |||
public static final short OBJECT_TYPE_RESERVED6 = 26; | |||
public static final short OBJECT_TYPE_RESERVED7 = 27; | |||
public static final short OBJECT_TYPE_RESERVED8 = 28; | |||
public static final short OBJECT_TYPE_RESERVED9 = 29; | |||
public static final short OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING = 30; | |||
private short field_1_objectType; | |||
private int field_2_objectId; | |||
private short field_3_option; | |||
@@ -75,9 +76,16 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea | |||
private int field_6_reserved3; | |||
public CommonObjectDataSubRecord() | |||
{ | |||
public CommonObjectDataSubRecord() {} | |||
public CommonObjectDataSubRecord(CommonObjectDataSubRecord other) { | |||
super(other); | |||
field_1_objectType = other.field_1_objectType; | |||
field_2_objectId = other.field_2_objectId; | |||
field_3_option = other.field_3_option; | |||
field_4_reserved1 = other.field_4_reserved1; | |||
field_5_reserved2 = other.field_5_reserved2; | |||
field_6_reserved3 = other.field_6_reserved3; | |||
} | |||
public CommonObjectDataSubRecord(LittleEndianInput in, int size) { | |||
@@ -101,31 +109,31 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea | |||
buffer.append(" .objectType = ") | |||
.append("0x").append(HexDump.toHex( getObjectType ())) | |||
.append(" (").append( getObjectType() ).append(" )"); | |||
buffer.append(System.getProperty("line.separator")); | |||
buffer.append(System.getProperty("line.separator")); | |||
buffer.append(" .objectId = ") | |||
.append("0x").append(HexDump.toHex( getObjectId ())) | |||
.append(" (").append( getObjectId() ).append(" )"); | |||
buffer.append(System.getProperty("line.separator")); | |||
buffer.append(System.getProperty("line.separator")); | |||
buffer.append(" .option = ") | |||
.append("0x").append(HexDump.toHex( getOption ())) | |||
.append(" (").append( getOption() ).append(" )"); | |||
buffer.append(System.getProperty("line.separator")); | |||
buffer.append(" .locked = ").append(isLocked()).append('\n'); | |||
buffer.append(" .printable = ").append(isPrintable()).append('\n'); | |||
buffer.append(" .autofill = ").append(isAutofill()).append('\n'); | |||
buffer.append(" .autoline = ").append(isAutoline()).append('\n'); | |||
buffer.append(System.getProperty("line.separator")); | |||
buffer.append(" .locked = ").append(isLocked()).append('\n'); | |||
buffer.append(" .printable = ").append(isPrintable()).append('\n'); | |||
buffer.append(" .autofill = ").append(isAutofill()).append('\n'); | |||
buffer.append(" .autoline = ").append(isAutoline()).append('\n'); | |||
buffer.append(" .reserved1 = ") | |||
.append("0x").append(HexDump.toHex( getReserved1 ())) | |||
.append(" (").append( getReserved1() ).append(" )"); | |||
buffer.append(System.getProperty("line.separator")); | |||
buffer.append(System.getProperty("line.separator")); | |||
buffer.append(" .reserved2 = ") | |||
.append("0x").append(HexDump.toHex( getReserved2 ())) | |||
.append(" (").append( getReserved2() ).append(" )"); | |||
buffer.append(System.getProperty("line.separator")); | |||
buffer.append(System.getProperty("line.separator")); | |||
buffer.append(" .reserved3 = ") | |||
.append("0x").append(HexDump.toHex( getReserved3 ())) | |||
.append(" (").append( getReserved3() ).append(" )"); | |||
buffer.append(System.getProperty("line.separator")); | |||
buffer.append(System.getProperty("line.separator")); | |||
buffer.append("[/ftCmo]\n"); | |||
return buffer.toString(); | |||
@@ -159,23 +167,23 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public CommonObjectDataSubRecord clone() { | |||
CommonObjectDataSubRecord rec = new CommonObjectDataSubRecord(); | |||
rec.field_1_objectType = field_1_objectType; | |||
rec.field_2_objectId = field_2_objectId; | |||
rec.field_3_option = field_3_option; | |||
rec.field_4_reserved1 = field_4_reserved1; | |||
rec.field_5_reserved2 = field_5_reserved2; | |||
rec.field_6_reserved3 = field_6_reserved3; | |||
return rec; | |||
return copy(); | |||
} | |||
@Override | |||
public CommonObjectDataSubRecord copy() { | |||
return new CommonObjectDataSubRecord(this); | |||
} | |||
/** | |||
* Get the object type field for the CommonObjectData record. | |||
* | |||
* @return One of | |||
* @return One of | |||
* OBJECT_TYPE_GROUP | |||
* OBJECT_TYPE_LINE | |||
* OBJECT_TYPE_RECTANGLE | |||
@@ -217,7 +225,7 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea | |||
* Set the object type field for the CommonObjectData record. | |||
* | |||
* @param field_1_objectType | |||
* One of | |||
* One of | |||
* OBJECT_TYPE_GROUP | |||
* OBJECT_TYPE_LINE | |||
* OBJECT_TYPE_RECTANGLE | |||
@@ -257,7 +265,7 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea | |||
/** | |||
* Get the object id field for the CommonObjectData record. | |||
* | |||
* | |||
* @return the object id field | |||
*/ | |||
public int getObjectId() | |||
@@ -267,7 +275,7 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea | |||
/** | |||
* Set the object id field for the CommonObjectData record. | |||
* | |||
* | |||
* @param field_2_objectId the object id field | |||
*/ | |||
public void setObjectId(int field_2_objectId) | |||
@@ -277,7 +285,7 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea | |||
/** | |||
* Get the option field for the CommonObjectData record. | |||
* | |||
* | |||
* @return the option field | |||
*/ | |||
public short getOption() | |||
@@ -287,7 +295,7 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea | |||
/** | |||
* Set the option field for the CommonObjectData record. | |||
* | |||
* | |||
* @param field_3_option the option field | |||
*/ | |||
public void setOption(short field_3_option) | |||
@@ -297,7 +305,7 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea | |||
/** | |||
* Get the reserved1 field for the CommonObjectData record. | |||
* | |||
* | |||
* @return the reserved1 field | |||
*/ | |||
public int getReserved1() | |||
@@ -307,7 +315,7 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea | |||
/** | |||
* Set the reserved1 field for the CommonObjectData record. | |||
* | |||
* | |||
* @param field_4_reserved1 the reserved1 field | |||
*/ | |||
public void setReserved1(int field_4_reserved1) | |||
@@ -317,7 +325,7 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea | |||
/** | |||
* Get the reserved2 field for the CommonObjectData record. | |||
* | |||
* | |||
* @return the reserved2 field | |||
*/ | |||
public int getReserved2() | |||
@@ -327,7 +335,7 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea | |||
/** | |||
* Set the reserved2 field for the CommonObjectData record. | |||
* | |||
* | |||
* @param field_5_reserved2 the reserved2 field | |||
*/ | |||
public void setReserved2(int field_5_reserved2) | |||
@@ -337,7 +345,7 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea | |||
/** | |||
* Get the reserved3 field for the CommonObjectData record. | |||
* | |||
* | |||
* @return the reserved3 field | |||
*/ | |||
public int getReserved3() | |||
@@ -347,7 +355,7 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea | |||
/** | |||
* Set the reserved3 field for the CommonObjectData record. | |||
* | |||
* | |||
* @param field_6_reserved3 the reserved3 field | |||
*/ | |||
public void setReserved3(int field_6_reserved3) | |||
@@ -358,7 +366,7 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea | |||
/** | |||
* Sets the locked field value. | |||
* true if object is locked when sheet has been protected | |||
* | |||
* | |||
* @param value {@code true} if object is locked when sheet has been protected | |||
*/ | |||
public void setLocked(boolean value) | |||
@@ -378,7 +386,7 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea | |||
/** | |||
* Sets the printable field value. | |||
* object appears when printed | |||
* | |||
* | |||
* @param value {@code true} if object appears when printed | |||
*/ | |||
public void setPrintable(boolean value) | |||
@@ -398,7 +406,7 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea | |||
/** | |||
* Sets the autofill field value. | |||
* whether object uses an automatic fill style | |||
* | |||
* | |||
* @param value {@code true} if object uses an automatic fill style | |||
*/ | |||
public void setAutofill(boolean value) | |||
@@ -418,7 +426,7 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea | |||
/** | |||
* Sets the autoline field value. | |||
* whether object uses an automatic line style | |||
* | |||
* | |||
* @param value {@code true} if object uses an automatic line style | |||
*/ | |||
public void setAutoline(boolean value) |
@@ -19,23 +19,26 @@ package org.apache.poi.hssf.record; | |||
import org.apache.poi.util.HexDump; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* Title: Continue Record(0x003C) - Helper class used primarily for SST Records <P> | |||
* Description: handles overflow for prior record in the input | |||
* stream; content is tailored to that prior record<P> | |||
* @author Marc Johnson (mjohnson at apache dot org) | |||
* @author Andrew C. Oliver (acoliver at apache dot org) | |||
* @author Csaba Nagy (ncsaba at yahoo dot com) | |||
* Helper class used primarily for SST Records<p> | |||
* | |||
* handles overflow for prior record in the input stream; content is tailored to that prior record | |||
*/ | |||
public final class ContinueRecord extends StandardRecord implements Cloneable { | |||
public final static short sid = 0x003C; | |||
public final class ContinueRecord extends StandardRecord { | |||
public static final short sid = 0x003C; | |||
private byte[] _data; | |||
public ContinueRecord(byte[] data) { | |||
_data = data; | |||
} | |||
public ContinueRecord(ContinueRecord other) { | |||
super(other); | |||
_data = (other._data == null) ? null : other._data.clone(); | |||
} | |||
protected int getDataSize() { | |||
return _data.length; | |||
} | |||
@@ -70,7 +73,15 @@ public final class ContinueRecord extends StandardRecord implements Cloneable { | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public ContinueRecord clone() { | |||
return new ContinueRecord(_data); | |||
return copy(); | |||
} | |||
@Override | |||
public ContinueRecord copy() { | |||
return new ContinueRecord(this); | |||
} | |||
} |
@@ -15,37 +15,36 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.hssf.record; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
/** | |||
* Title: Country Record (aka WIN.INI country)<P> | |||
* Description: used for localization. Currently HSSF always sets this to 1 | |||
* and it seems to work fine even in Germany. (es geht's auch fuer Deutschland)<P> | |||
* Country Record (aka WIN.INI country) - used for localization<p> | |||
* | |||
* Currently HSSF always sets this to 1 and it seems to work fine even in Germany. | |||
* | |||
* REFERENCE: PG 298 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> | |||
* @author Andrew C. Oliver (acoliver at apache dot org) | |||
* @version 2.0-pre | |||
*/ | |||
public final class CountryRecord | |||
extends StandardRecord | |||
{ | |||
public final static short sid = 0x8c; | |||
public final class CountryRecord extends StandardRecord { | |||
public static final short sid = 0x8c; | |||
// 1 for US | |||
private short field_1_default_country; | |||
private short field_2_current_country; | |||
private short field_1_default_country; | |||
private short field_2_current_country; | |||
public CountryRecord() | |||
{ | |||
public CountryRecord() {} | |||
public CountryRecord(CountryRecord other) { | |||
super(other); | |||
field_1_default_country = other.field_1_default_country; | |||
field_2_current_country = other.field_2_current_country; | |||
} | |||
public CountryRecord(RecordInputStream in) | |||
{ | |||
public CountryRecord(RecordInputStream in) { | |||
field_1_default_country = in.readShort(); | |||
field_2_current_country = in.readShort(); | |||
} | |||
@@ -120,4 +119,9 @@ public final class CountryRecord | |||
{ | |||
return sid; | |||
} | |||
@Override | |||
public CountryRecord copy() { | |||
return new CountryRecord(this); | |||
} | |||
} |
@@ -19,39 +19,15 @@ package org.apache.poi.hssf.record; | |||
import org.apache.poi.util.HexDump; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* Title: DBCell Record (0x00D7)<p> | |||
* Description: Used by Excel and other MS apps to quickly find rows in the sheets.<P> | |||
* REFERENCE: PG 299/440 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) | |||
* Used by Excel and other MS apps to quickly find rows in the sheets. | |||
*/ | |||
public final class DBCellRecord extends StandardRecord implements Cloneable { | |||
public final static short sid = 0x00D7; | |||
public final static int BLOCK_SIZE = 32; | |||
public static final class Builder { | |||
private short[] _cellOffsets; | |||
private int _nCellOffsets; | |||
public Builder() { | |||
_cellOffsets = new short[4]; | |||
} | |||
public final class DBCellRecord extends StandardRecord { | |||
public static final short sid = 0x00D7; | |||
public static final int BLOCK_SIZE = 32; | |||
public void addCellOffset(int cellRefOffset) { | |||
if (_cellOffsets.length <= _nCellOffsets) { | |||
short[] temp = new short[_nCellOffsets * 2]; | |||
System.arraycopy(_cellOffsets, 0, temp, 0, _nCellOffsets); | |||
_cellOffsets = temp; | |||
} | |||
_cellOffsets[_nCellOffsets] = (short) cellRefOffset; | |||
_nCellOffsets++; | |||
} | |||
public DBCellRecord build(int rowOffset) { | |||
short[] cellOffsets = new short[_nCellOffsets]; | |||
System.arraycopy(_cellOffsets, 0, cellOffsets, 0, _nCellOffsets); | |||
return new DBCellRecord(rowOffset, cellOffsets); | |||
} | |||
} | |||
/** | |||
* offset from the start of this DBCellRecord to the start of the first cell in | |||
* the next DBCell block. | |||
@@ -59,23 +35,21 @@ public final class DBCellRecord extends StandardRecord implements Cloneable { | |||
private final int field_1_row_offset; | |||
private final short[] field_2_cell_offsets; | |||
DBCellRecord(int rowOffset, short[]cellOffsets) { | |||
public DBCellRecord(int rowOffset, short[] cellOffsets) { | |||
field_1_row_offset = rowOffset; | |||
field_2_cell_offsets = cellOffsets; | |||
} | |||
public DBCellRecord(RecordInputStream in) { | |||
field_1_row_offset = in.readUShort(); | |||
int size = in.remaining(); | |||
int size = in.remaining(); | |||
field_2_cell_offsets = new short[ size / 2 ]; | |||
for (int i=0;i<field_2_cell_offsets.length;i++) | |||
{ | |||
for (int i=0;i<field_2_cell_offsets.length;i++) { | |||
field_2_cell_offsets[ i ] = in.readShort(); | |||
} | |||
} | |||
public String toString() { | |||
StringBuilder buffer = new StringBuilder(); | |||
@@ -91,8 +65,8 @@ public final class DBCellRecord extends StandardRecord implements Cloneable { | |||
public void serialize(LittleEndianOutput out) { | |||
out.writeInt(field_1_row_offset); | |||
for (int k = 0; k < field_2_cell_offsets.length; k++) { | |||
out.writeShort(field_2_cell_offsets[ k ]); | |||
for (short field_2_cell_offset : field_2_cell_offsets) { | |||
out.writeShort(field_2_cell_offset); | |||
} | |||
} | |||
protected int getDataSize() { | |||
@@ -104,7 +78,15 @@ public final class DBCellRecord extends StandardRecord implements Cloneable { | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public DBCellRecord clone() { | |||
return copy(); | |||
} | |||
@Override | |||
public DBCellRecord copy() { | |||
// safe because immutable | |||
return this; | |||
} |
@@ -18,10 +18,10 @@ | |||
*/ | |||
package org.apache.poi.hssf.record; | |||
import java.io.ByteArrayInputStream; | |||
import java.util.Arrays; | |||
import org.apache.poi.util.IOUtils; | |||
import org.apache.poi.util.LittleEndian; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.RecordFormatException; | |||
import org.apache.poi.util.StringUtil; | |||
@@ -67,8 +67,7 @@ import org.apache.poi.util.StringUtil; | |||
* | |||
* At the moment this class is read-only. | |||
*/ | |||
public class DConRefRecord extends StandardRecord | |||
{ | |||
public class DConRefRecord extends StandardRecord { | |||
//arbitrarily selected; may need to increase | |||
private static final int MAX_RECORD_LENGTH = 100_000; | |||
@@ -108,54 +107,25 @@ public class DConRefRecord extends StandardRecord | |||
*/ | |||
private byte[] _unused; | |||
public DConRefRecord(DConRefRecord other) { | |||
super(other); | |||
firstCol = other.firstCol; | |||
firstRow = other.firstRow; | |||
lastCol = other.lastCol; | |||
lastRow = other.lastRow; | |||
charCount = other.charCount; | |||
charType = other.charType; | |||
path = (other.path == null) ? null : other.path.clone(); | |||
_unused = (other._unused == null) ? null : other._unused.clone(); | |||
} | |||
/** | |||
* Read constructor. | |||
* | |||
* @param data byte array containing a DConRef Record, including the header. | |||
*/ | |||
public DConRefRecord(byte[] data) | |||
{ | |||
int offset = 0; | |||
if (!(LittleEndian.getShort(data, offset) == DConRefRecord.sid)) | |||
throw new RecordFormatException("incompatible sid."); | |||
offset += LittleEndian.SHORT_SIZE; | |||
//length = LittleEndian.getShort(data, offset); | |||
offset += LittleEndian.SHORT_SIZE; | |||
firstRow = LittleEndian.getUShort(data, offset); | |||
offset += LittleEndian.SHORT_SIZE; | |||
lastRow = LittleEndian.getUShort(data, offset); | |||
offset += LittleEndian.SHORT_SIZE; | |||
firstCol = LittleEndian.getUByte(data, offset); | |||
offset += LittleEndian.BYTE_SIZE; | |||
lastCol = LittleEndian.getUByte(data, offset); | |||
offset += LittleEndian.BYTE_SIZE; | |||
charCount = LittleEndian.getUShort(data, offset); | |||
offset += LittleEndian.SHORT_SIZE; | |||
if (charCount < 2) | |||
throw new RecordFormatException("Character count must be >= 2"); | |||
charType = LittleEndian.getUByte(data, offset); | |||
offset += LittleEndian.BYTE_SIZE; //7 bits reserved + 1 bit type | |||
/* | |||
* bytelength is the length of the string in bytes, which depends on whether the string is | |||
* made of single- or double-byte chars. This is given by charType, which equals 0 if | |||
* single-byte, 1 if double-byte. | |||
*/ | |||
int byteLength = charCount * ((charType & 1) + 1); | |||
path = LittleEndian.getByteArray(data, offset, byteLength, MAX_RECORD_LENGTH); | |||
offset += byteLength; | |||
/* | |||
* If it's a self reference, the last one or two bytes (depending on char type) are the | |||
* unused field. Not sure If i need to bother with this... | |||
*/ | |||
if (path[0] == 0x02) | |||
_unused = LittleEndian.getByteArray(data, offset, (charType + 1), MAX_RECORD_LENGTH); | |||
public DConRefRecord(byte[] data) { | |||
this(bytesToRIStream(data)); | |||
} | |||
/** | |||
@@ -163,10 +133,10 @@ public class DConRefRecord extends StandardRecord | |||
* | |||
* @param inStream RecordInputStream containing a DConRefRecord structure. | |||
*/ | |||
public DConRefRecord(RecordInputStream inStream) | |||
{ | |||
if (inStream.getSid() != sid) | |||
public DConRefRecord(RecordInputStream inStream) { | |||
if (inStream.getSid() != sid) { | |||
throw new RecordFormatException("Wrong sid: " + inStream.getSid()); | |||
} | |||
firstRow = inStream.readUShort(); | |||
lastRow = inStream.readUShort(); | |||
@@ -174,17 +144,23 @@ public class DConRefRecord extends StandardRecord | |||
lastCol = inStream.readUByte(); | |||
charCount = inStream.readUShort(); | |||
charType = inStream.readUByte() & 0x01; //first bit only. | |||
// byteLength depends on whether we are using single- or double-byte chars. | |||
int byteLength = charCount * (charType + 1); | |||
// 7 bits reserved + 1 bit type - first bit only | |||
charType = inStream.readUByte() & 0x01; | |||
// bytelength is the length of the string in bytes, which depends on whether the string is | |||
// made of single- or double-byte chars. This is given by charType, which equals 0 if | |||
// single-byte, 1 if double-byte. | |||
final int byteLength = charCount * (charType + 1); | |||
path = IOUtils.safelyAllocate(byteLength, MAX_RECORD_LENGTH); | |||
inStream.readFully(path); | |||
if (path[0] == 0x02) | |||
// If it's a self reference, the last one or two bytes (depending on char type) are the | |||
// unused field. Not sure If i need to bother with this... | |||
if (path[0] == 0x02) { | |||
_unused = inStream.readRemainder(); | |||
} | |||
} | |||
/* | |||
@@ -291,8 +267,7 @@ public class DConRefRecord extends StandardRecord | |||
//all of the path strings start with either 0x02 or 0x01 followed by zero or | |||
//more of 0x01..0x08 | |||
int offset = 1; | |||
while (path[offset] < 0x20 && offset < path.length) | |||
{ | |||
while (offset < path.length && path[offset] < 0x20) { | |||
offset++; | |||
} | |||
String out = new String(Arrays.copyOfRange(path, offset, path.length), StringUtil.UTF8); | |||
@@ -310,8 +285,17 @@ public class DConRefRecord extends StandardRecord | |||
*/ | |||
public boolean isExternalRef() | |||
{ | |||
if (path[0] == 0x01) | |||
return true; | |||
return false; | |||
return path[0] == 0x01; | |||
} | |||
@Override | |||
public DConRefRecord copy() { | |||
return new DConRefRecord(this); | |||
} | |||
private static RecordInputStream bytesToRIStream(byte[] data) { | |||
RecordInputStream ric = new RecordInputStream(new ByteArrayInputStream(data)); | |||
ric.nextRecord(); | |||
return ric; | |||
} | |||
} |
@@ -23,21 +23,26 @@ import org.apache.poi.util.HexDump; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
/** | |||
* Title: Double Stream Flag Record (0x0161)<p> | |||
* Description: tells if this is a double stream file. (always no for HSSF generated files)<p> | |||
* Double Stream files contain both BIFF8 and BIFF7 workbooks.<p> | |||
* REFERENCE: PG 305 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) | |||
* Tells if this is a double stream file. (never applies to HSSF generated files)<p> | |||
* | |||
* Double Stream files contain both BIFF8 and BIFF7 workbooks. | |||
*/ | |||
public final class DSFRecord extends StandardRecord { | |||
public final static short sid = 0x0161; | |||
public static final short sid = 0x0161; | |||
private static final BitField biff5BookStreamFlag = BitFieldFactory.getInstance(0x0001); | |||
private int _options; | |||
private DSFRecord(DSFRecord other) { | |||
super(other); | |||
_options = other._options; | |||
} | |||
private DSFRecord(int options) { | |||
_options = options; | |||
} | |||
public DSFRecord(boolean isBiff5BookStreamPresent) { | |||
this(0); | |||
_options = biff5BookStreamFlag.setBoolean(0, isBiff5BookStreamPresent); | |||
@@ -71,4 +76,9 @@ public final class DSFRecord extends StandardRecord { | |||
public short getSid() { | |||
return sid; | |||
} | |||
@Override | |||
public DSFRecord copy() { | |||
return new DSFRecord(this); | |||
} | |||
} |
@@ -18,14 +18,13 @@ | |||
package org.apache.poi.hssf.record; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* Title: DATAVALIDATIONS Record (0x01B2)<p> | |||
* Description: used in data validation ; | |||
* This record is the list header of all data validation records (0x01BE) in the current sheet. | |||
* This record is the list header of all data validation records (0x01BE) in the current sheet. | |||
*/ | |||
public final class DVALRecord extends StandardRecord implements Cloneable { | |||
public final static short sid = 0x01B2; | |||
public final class DVALRecord extends StandardRecord { | |||
public static final short sid = 0x01B2; | |||
/** Options of the DVAL */ | |||
private short field_1_options; | |||
@@ -47,12 +46,21 @@ public final class DVALRecord extends StandardRecord implements Cloneable { | |||
field_5_dv_no = 0x00000000; | |||
} | |||
public DVALRecord(DVALRecord other) { | |||
super(other); | |||
field_1_options = other.field_1_options; | |||
field_2_horiz_pos = other.field_2_horiz_pos; | |||
field_3_vert_pos = other.field_3_vert_pos; | |||
field_cbo_id = other.field_cbo_id; | |||
field_5_dv_no = other.field_5_dv_no; | |||
} | |||
public DVALRecord(RecordInputStream in) { | |||
field_1_options = in.readShort(); | |||
field_2_horiz_pos = in.readInt(); | |||
field_3_vert_pos = in.readInt(); | |||
field_cbo_id = in.readInt(); | |||
field_5_dv_no = in.readInt(); | |||
field_cbo_id = in.readInt(); | |||
field_5_dv_no = in.readInt(); | |||
} | |||
/** | |||
@@ -142,7 +150,6 @@ public final class DVALRecord extends StandardRecord implements Cloneable { | |||
} | |||
public void serialize(LittleEndianOutput out) { | |||
out.writeShort(getOptions()); | |||
out.writeInt(getHorizontalPos()); | |||
out.writeInt(getVerticalPos()); | |||
@@ -158,14 +165,16 @@ public final class DVALRecord extends StandardRecord implements Cloneable { | |||
return sid; | |||
} | |||
@Override | |||
public DVALRecord clone() { | |||
DVALRecord rec = new DVALRecord(); | |||
rec.field_1_options = field_1_options; | |||
rec.field_2_horiz_pos = field_2_horiz_pos; | |||
rec.field_3_vert_pos = field_3_vert_pos; | |||
rec.field_cbo_id = field_cbo_id; | |||
rec.field_5_dv_no = field_5_dv_no; | |||
return rec; | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public DVALRecord clone() { | |||
return copy(); | |||
} | |||
@Override | |||
public DVALRecord copy() { | |||
return new DVALRecord(this); | |||
} | |||
} |
@@ -25,64 +25,77 @@ import org.apache.poi.ss.util.CellRangeAddress; | |||
import org.apache.poi.ss.util.CellRangeAddressList; | |||
import org.apache.poi.util.BitField; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.Removal; | |||
import org.apache.poi.util.StringUtil; | |||
/** | |||
* Title: DATAVALIDATION Record (0x01BE)<p> | |||
* Description: This record stores data validation settings and a list of cell ranges | |||
* which contain these settings. The data validation settings of a sheet | |||
* are stored in a sequential list of DV records. This list is followed by | |||
* DVAL record(s) | |||
* This record stores data validation settings and a list of cell ranges which contain these settings. | |||
* The data validation settings of a sheet are stored in a sequential list of DV records. | |||
* This list is followed by DVAL record(s) | |||
*/ | |||
public final class DVRecord extends StandardRecord implements Cloneable { | |||
public final static short sid = 0x01BE; | |||
public final class DVRecord extends StandardRecord { | |||
public static final short sid = 0x01BE; | |||
/** the unicode string used for error/prompt title/text when not present */ | |||
private static final UnicodeString NULL_TEXT_STRING = new UnicodeString("\0"); | |||
/** | |||
* Option flags field | |||
* | |||
* @see HSSFDataValidation utility class | |||
*/ | |||
private static final BitField opt_data_type = new BitField(0x0000000F); | |||
private static final BitField opt_error_style = new BitField(0x00000070); | |||
private static final BitField opt_string_list_formula = new BitField(0x00000080); | |||
private static final BitField opt_empty_cell_allowed = new BitField(0x00000100); | |||
private static final BitField opt_suppress_dropdown_arrow = new BitField(0x00000200); | |||
private static final BitField opt_show_prompt_on_cell_selected = new BitField(0x00040000); | |||
private static final BitField opt_show_error_on_invalid_value = new BitField(0x00080000); | |||
private static final BitField opt_condition_operator = new BitField(0x00700000); | |||
/** Option flags */ | |||
private int _option_flags; | |||
/** Title of the prompt box, cannot be longer than 32 chars */ | |||
private UnicodeString _promptTitle; | |||
private final UnicodeString _promptTitle; | |||
/** Title of the error box, cannot be longer than 32 chars */ | |||
private UnicodeString _errorTitle; | |||
private final UnicodeString _errorTitle; | |||
/** Text of the prompt box, cannot be longer than 255 chars */ | |||
private UnicodeString _promptText; | |||
private final UnicodeString _promptText; | |||
/** Text of the error box, cannot be longer than 255 chars */ | |||
private UnicodeString _errorText; | |||
private final UnicodeString _errorText; | |||
/** Not used - Excel seems to always write 0x3FE0 */ | |||
private short _not_used_1 = 0x3FE0; | |||
/** Formula data for first condition (RPN token array without size field) */ | |||
private Formula _formula1; | |||
private final Formula _formula1; | |||
/** Not used - Excel seems to always write 0x0000 */ | |||
@SuppressWarnings("RedundantFieldInitialization") | |||
private short _not_used_2 = 0x0000; | |||
/** Formula data for second condition (RPN token array without size field) */ | |||
private Formula _formula2; | |||
private final Formula _formula2; | |||
/** Cell range address list with all affected ranges */ | |||
private CellRangeAddressList _regions; | |||
/** | |||
* Option flags field | |||
* | |||
* @see HSSFDataValidation utility class | |||
*/ | |||
private static final BitField opt_data_type = new BitField(0x0000000F); | |||
private static final BitField opt_error_style = new BitField(0x00000070); | |||
private static final BitField opt_string_list_formula = new BitField(0x00000080); | |||
private static final BitField opt_empty_cell_allowed = new BitField(0x00000100); | |||
private static final BitField opt_suppress_dropdown_arrow = new BitField(0x00000200); | |||
private static final BitField opt_show_prompt_on_cell_selected = new BitField(0x00040000); | |||
private static final BitField opt_show_error_on_invalid_value = new BitField(0x00080000); | |||
private static final BitField opt_condition_operator = new BitField(0x00700000); | |||
private final CellRangeAddressList _regions; | |||
public DVRecord(DVRecord other) { | |||
super(other); | |||
_option_flags = other._option_flags; | |||
_promptTitle = other._promptTitle.copy(); | |||
_errorTitle = other._errorTitle.copy(); | |||
_promptText = other._promptText.copy(); | |||
_errorText = other._errorText.copy(); | |||
_not_used_1 = other._not_used_1; | |||
_formula1 = (other._formula1 == null) ? null : other._formula1.copy(); | |||
_not_used_2 = other._not_used_2; | |||
_formula2 = (other._formula2 == null) ? null : other._formula2.copy(); | |||
_regions = (other._regions == null) ? null : other._regions.copy(); | |||
} | |||
public DVRecord(int validationType, int operator, int errorStyle, boolean emptyCellAllowed, | |||
boolean suppressDropDownArrow, boolean isExplicitList, | |||
boolean showPromptBox, String promptTitle, String promptText, | |||
boolean showPromptBox, String promptTitle, String promptText, | |||
boolean showErrorBox, String errorTitle, String errorText, | |||
Ptg[] formula1, Ptg[] formula2, | |||
CellRangeAddressList regions) { | |||
// check length-limits | |||
if(promptTitle != null && promptTitle.length() > 32) { | |||
throw new IllegalStateException("Prompt-title cannot be longer than 32 characters, but had: " + promptTitle); | |||
@@ -118,7 +131,6 @@ public final class DVRecord extends StandardRecord implements Cloneable { | |||
} | |||
public DVRecord(RecordInputStream in) { | |||
_option_flags = in.readInt(); | |||
_promptTitle = readUnicodeString(in); | |||
@@ -144,7 +156,6 @@ public final class DVRecord extends StandardRecord implements Cloneable { | |||
_regions = new CellRangeAddressList(in); | |||
} | |||
// --> start option flags | |||
/** | |||
* @return the condition data type | |||
* @see org.apache.poi.ss.usermodel.DataValidationConstraint.ValidationType | |||
@@ -276,7 +287,7 @@ public final class DVRecord extends StandardRecord implements Cloneable { | |||
private static void appendFormula(StringBuilder sb, String label, Formula f) { | |||
sb.append(label); | |||
if (f == null) { | |||
sb.append("<empty>\n"); | |||
return; | |||
@@ -291,7 +302,7 @@ public final class DVRecord extends StandardRecord implements Cloneable { | |||
public void serialize(LittleEndianOutput out) { | |||
out.writeInt(_option_flags); | |||
serializeUnicodeString(_promptTitle, out); | |||
serializeUnicodeString(_errorTitle, out); | |||
serializeUnicodeString(_promptText, out); | |||
@@ -299,19 +310,19 @@ public final class DVRecord extends StandardRecord implements Cloneable { | |||
out.writeShort(_formula1.getEncodedTokenSize()); | |||
out.writeShort(_not_used_1); | |||
_formula1.serializeTokens(out); | |||
out.writeShort(_formula2.getEncodedTokenSize()); | |||
out.writeShort(_not_used_2); | |||
_formula2.serializeTokens(out); | |||
_regions.serialize(out); | |||
} | |||
/** | |||
* When entered via the UI, Excel translates empty string into "\0" | |||
* While it is possible to encode the title/text as empty string (Excel doesn't exactly crash), | |||
* the resulting tool-tip text / message box looks wrong. It is best to do the same as the | |||
* Excel UI and encode 'not present' as "\0". | |||
* the resulting tool-tip text / message box looks wrong. It is best to do the same as the | |||
* Excel UI and encode 'not present' as "\0". | |||
*/ | |||
private static UnicodeString resolveTitleText(String str) { | |||
if (str == null || str.length() < 1) { | |||
@@ -354,13 +365,18 @@ public final class DVRecord extends StandardRecord implements Cloneable { | |||
public short getSid() { | |||
return sid; | |||
} | |||
/** | |||
* Clones the object. Uses serialisation, as the | |||
* contents are somewhat complex | |||
*/ | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public DVRecord clone() { | |||
return (DVRecord)cloneViaReserialise(); | |||
return copy(); | |||
} | |||
/** Clones the object. */ | |||
@Override | |||
public DVRecord copy() { | |||
return new DVRecord(this); | |||
} | |||
} |
@@ -15,33 +15,31 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.hssf.record; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
/** | |||
* Title: Date Window 1904 Flag record <P> | |||
* Description: Flag specifying whether 1904 date windowing is used. | |||
* (tick toc tick toc...BOOM!) <P> | |||
* REFERENCE: PG 280 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> | |||
* @author Andrew C. Oliver (acoliver at apache dot org) | |||
* Flag specifying whether 1904 date windowing is used. | |||
* | |||
* @version 2.0-pre | |||
*/ | |||
public final class DateWindow1904Record | |||
extends StandardRecord | |||
{ | |||
public final static short sid = 0x22; | |||
private short field_1_window; | |||
public final class DateWindow1904Record extends StandardRecord { | |||
public static final short sid = 0x22; | |||
public DateWindow1904Record() | |||
{ | |||
private short field_1_window; | |||
public DateWindow1904Record() {} | |||
public DateWindow1904Record(DateWindow1904Record other) { | |||
super(other); | |||
field_1_window = other.field_1_window; | |||
} | |||
public DateWindow1904Record(RecordInputStream in) | |||
{ | |||
public DateWindow1904Record(RecordInputStream in) { | |||
field_1_window = in.readShort(); | |||
} | |||
@@ -88,4 +86,9 @@ public final class DateWindow1904Record | |||
{ | |||
return sid; | |||
} | |||
@Override | |||
public DateWindow1904Record copy() { | |||
return new DateWindow1904Record(this); | |||
} | |||
} |
@@ -18,30 +18,32 @@ | |||
package org.apache.poi.hssf.record; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* Title: Default Column Width Record (0x0055) <P> | |||
* Description: Specifies the default width for columns that have no specific | |||
* width set.<P> | |||
* REFERENCE: PG 302 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> | |||
* @author Andrew C. Oliver (acoliver at apache dot org) | |||
* @author Jason Height (jheight at chariot dot net dot au) | |||
* Specifies the default width for columns that have no specific width set. | |||
* | |||
* @version 2.0-pre | |||
*/ | |||
public final class DefaultColWidthRecord extends StandardRecord implements Cloneable { | |||
public final static short sid = 0x0055; | |||
private int field_1_col_width; | |||
public final class DefaultColWidthRecord extends StandardRecord { | |||
public static final short sid = 0x0055; | |||
/** | |||
* The default column width is 8 characters | |||
*/ | |||
public final static int DEFAULT_COLUMN_WIDTH = 0x0008; | |||
public static final int DEFAULT_COLUMN_WIDTH = 0x0008; | |||
public DefaultColWidthRecord() | |||
{ | |||
private int field_1_col_width; | |||
public DefaultColWidthRecord() { | |||
field_1_col_width = DEFAULT_COLUMN_WIDTH; | |||
} | |||
public DefaultColWidthRecord(DefaultColWidthRecord other) { | |||
super(other); | |||
field_1_col_width = other.field_1_col_width; | |||
} | |||
public DefaultColWidthRecord(RecordInputStream in) | |||
{ | |||
field_1_col_width = in.readUShort(); | |||
@@ -92,9 +94,15 @@ public final class DefaultColWidthRecord extends StandardRecord implements Clone | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public DefaultColWidthRecord clone() { | |||
DefaultColWidthRecord rec = new DefaultColWidthRecord(); | |||
rec.field_1_col_width = field_1_col_width; | |||
return rec; | |||
return copy(); | |||
} | |||
@Override | |||
public DefaultColWidthRecord copy() { | |||
return new DefaultColWidthRecord(this); | |||
} | |||
} |
@@ -1,4 +1,3 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
@@ -20,35 +19,35 @@ | |||
package org.apache.poi.hssf.record; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* Title: Default Row Height Record | |||
* Description: Row height for rows with undefined or not explicitly defined | |||
* heights. | |||
* REFERENCE: PG 301 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> | |||
* @author Andrew C. Oliver (acoliver at apache dot org) | |||
* @author Jason Height (jheight at chariot dot net dot au) | |||
* Row height for rows with undefined or not explicitly defined heights. | |||
* | |||
* @version 2.0-pre | |||
*/ | |||
public final class DefaultRowHeightRecord extends StandardRecord implements Cloneable { | |||
public final static short sid = 0x225; | |||
private short field_1_option_flags; | |||
private short field_2_row_height; | |||
public final class DefaultRowHeightRecord extends StandardRecord { | |||
public static final short sid = 0x225; | |||
/** | |||
* The default row height for empty rows is 255 twips (255 / 20 == 12.75 points) | |||
*/ | |||
/** The default row height for empty rows is 255 twips (255 / 20 == 12.75 points) */ | |||
public static final short DEFAULT_ROW_HEIGHT = 0xFF; | |||
public DefaultRowHeightRecord() | |||
{ | |||
private short field_1_option_flags; | |||
private short field_2_row_height; | |||
public DefaultRowHeightRecord() { | |||
field_1_option_flags = 0x0000; | |||
field_2_row_height = DEFAULT_ROW_HEIGHT; | |||
} | |||
public DefaultRowHeightRecord(RecordInputStream in) | |||
{ | |||
public DefaultRowHeightRecord(DefaultRowHeightRecord other) { | |||
super(other); | |||
field_1_option_flags = other.field_1_option_flags; | |||
field_2_row_height = other.field_2_row_height; | |||
} | |||
public DefaultRowHeightRecord(RecordInputStream in) { | |||
field_1_option_flags = in.readShort(); | |||
field_2_row_height = in.readShort(); | |||
} | |||
@@ -121,10 +120,15 @@ public final class DefaultRowHeightRecord extends StandardRecord implements Clon | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public DefaultRowHeightRecord clone() { | |||
DefaultRowHeightRecord rec = new DefaultRowHeightRecord(); | |||
rec.field_1_option_flags = field_1_option_flags; | |||
rec.field_2_row_height = field_2_row_height; | |||
return rec; | |||
return copy(); | |||
} | |||
@Override | |||
public DefaultRowHeightRecord copy() { | |||
return new DefaultRowHeightRecord(this); | |||
} | |||
} |
@@ -18,15 +18,12 @@ | |||
package org.apache.poi.hssf.record; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* Title: Delta Record (0x0010)<p> | |||
* Description: controls the accuracy of the calculations<p> | |||
* REFERENCE: PG 303 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) | |||
*/ | |||
public final class DeltaRecord extends StandardRecord implements Cloneable { | |||
public final static short sid = 0x0010; | |||
public final static double DEFAULT_VALUE = 0.0010; // should be .001 | |||
/** Controls the accuracy of the calculations */ | |||
public final class DeltaRecord extends StandardRecord { | |||
public static final short sid = 0x0010; | |||
public static final double DEFAULT_VALUE = 0.0010; | |||
// a double is an IEEE 8-byte float...damn IEEE and their goofy standards an | |||
// ambiguous numeric identifiers | |||
@@ -36,6 +33,11 @@ public final class DeltaRecord extends StandardRecord implements Cloneable { | |||
field_1_max_change = maxChange; | |||
} | |||
public DeltaRecord(DeltaRecord other) { | |||
super(other); | |||
field_1_max_change = other.field_1_max_change; | |||
} | |||
public DeltaRecord(RecordInputStream in) { | |||
field_1_max_change = in.readDouble(); | |||
} | |||
@@ -70,7 +72,15 @@ public final class DeltaRecord extends StandardRecord implements Cloneable { | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public DeltaRecord clone() { | |||
return copy(); | |||
} | |||
@Override | |||
public DeltaRecord copy() { | |||
// immutable | |||
return this; | |||
} |
@@ -15,41 +15,44 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.hssf.record; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.POILogFactory; | |||
import org.apache.poi.util.POILogger; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* Title: Dimensions Record<P> | |||
* Description: provides the minumum and maximum bounds | |||
* of a sheet.<P> | |||
* REFERENCE: PG 303 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> | |||
* @author Andrew C. Oliver (acoliver at apache dot org) | |||
* @author Jason Height (jheight at chariot dot net dot au) | |||
* Provides the minumum and maximum bounds of a sheet. | |||
* | |||
* @version 2.0-pre | |||
*/ | |||
public final class DimensionsRecord extends StandardRecord implements Cloneable { | |||
public final class DimensionsRecord extends StandardRecord { | |||
private static final POILogger logger = POILogFactory.getLogger(DimensionsRecord.class); | |||
public final static short sid = 0x200; | |||
public static final short sid = 0x200; | |||
private int field_1_first_row; | |||
private int field_2_last_row; // plus 1 | |||
private short field_3_first_col; | |||
private short field_4_last_col; | |||
private short field_5_zero; // must be 0 (reserved) | |||
public DimensionsRecord() | |||
{ | |||
public DimensionsRecord() {} | |||
public DimensionsRecord(DimensionsRecord other) { | |||
super(other); | |||
field_1_first_row = other.field_1_first_row; | |||
field_2_last_row = other.field_2_last_row; | |||
field_3_first_col = other.field_3_first_col; | |||
field_4_last_col = other.field_4_last_col; | |||
field_5_zero = other.field_5_zero; | |||
} | |||
public DimensionsRecord(RecordInputStream in) | |||
{ | |||
public DimensionsRecord(RecordInputStream in) { | |||
field_1_first_row = in.readInt(); | |||
field_2_last_row = in.readInt(); | |||
field_3_first_col = in.readShort(); | |||
@@ -179,13 +182,15 @@ public final class DimensionsRecord extends StandardRecord implements Cloneable | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public DimensionsRecord clone() { | |||
DimensionsRecord rec = new DimensionsRecord(); | |||
rec.field_1_first_row = field_1_first_row; | |||
rec.field_2_last_row = field_2_last_row; | |||
rec.field_3_first_col = field_3_first_col; | |||
rec.field_4_last_col = field_4_last_col; | |||
rec.field_5_zero = field_5_zero; | |||
return rec; | |||
return copy(); | |||
} | |||
@Override | |||
public DimensionsRecord copy() { | |||
return new DimensionsRecord(this); | |||
} | |||
} |
@@ -17,13 +17,13 @@ | |||
package org.apache.poi.hssf.record; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import org.apache.poi.ddf.EscherRecord; | |||
import org.apache.poi.ddf.NullEscherSerializationListener; | |||
import org.apache.poi.util.LittleEndian; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
public final class DrawingGroupRecord extends AbstractEscherHolderRecord { | |||
public static final short sid = 0xEB; | |||
@@ -31,12 +31,13 @@ public final class DrawingGroupRecord extends AbstractEscherHolderRecord { | |||
static final int MAX_RECORD_SIZE = 8228; | |||
private static final int MAX_DATA_SIZE = MAX_RECORD_SIZE - 4; | |||
public DrawingGroupRecord() | |||
{ | |||
public DrawingGroupRecord() {} | |||
public DrawingGroupRecord(DrawingGroupRecord other) { | |||
super(other); | |||
} | |||
public DrawingGroupRecord( RecordInputStream in ) | |||
{ | |||
public DrawingGroupRecord( RecordInputStream in ) { | |||
super( in ); | |||
} | |||
@@ -136,4 +137,9 @@ public final class DrawingGroupRecord extends AbstractEscherHolderRecord { | |||
LittleEndian.putShort(data, 0 + offset, ContinueRecord.sid); | |||
LittleEndian.putShort(data, 2 + offset, (short) sizeExcludingHeader); | |||
} | |||
@Override | |||
public DrawingGroupRecord copy() { | |||
return new DrawingGroupRecord(this); | |||
} | |||
} |
@@ -18,10 +18,9 @@ | |||
package org.apache.poi.hssf.record; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
/** | |||
* DrawingRecord (0x00EC) | |||
*/ | |||
public final class DrawingRecord extends StandardRecord implements Cloneable { | |||
import org.apache.poi.util.Removal; | |||
public final class DrawingRecord extends StandardRecord { | |||
public static final short sid = 0x00EC; | |||
private static final byte[] EMPTY_BYTE_ARRAY = {}; | |||
@@ -33,6 +32,13 @@ public final class DrawingRecord extends StandardRecord implements Cloneable { | |||
recordData = EMPTY_BYTE_ARRAY; | |||
} | |||
public DrawingRecord(DrawingRecord other) { | |||
super(other); | |||
recordData = (other.recordData == null) ? null : other.recordData.clone(); | |||
// TODO - this code probably never copies a contd array ... | |||
contd = (other.contd == null) ? null : other.contd.clone(); | |||
} | |||
public DrawingRecord(RecordInputStream in) { | |||
recordData = in.readRemainder(); | |||
} | |||
@@ -69,20 +75,21 @@ public final class DrawingRecord extends StandardRecord implements Cloneable { | |||
recordData = thedata; | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public DrawingRecord clone() { | |||
return copy(); | |||
} | |||
/** | |||
* Cloning of drawing records must be executed through HSSFPatriarch, because all id's must be changed | |||
* @return cloned drawing records | |||
*/ | |||
@Override | |||
public DrawingRecord clone() { | |||
DrawingRecord rec = new DrawingRecord(); | |||
rec.recordData = recordData.clone(); | |||
if (contd != null) { | |||
// TODO - this code probably never executes | |||
rec.contd = contd.clone(); | |||
} | |||
return rec; | |||
public DrawingRecord copy() { | |||
return new DrawingRecord(this); | |||
} | |||
@Override |
@@ -26,8 +26,10 @@ import java.io.ByteArrayInputStream; | |||
public final class DrawingRecordForBiffViewer extends AbstractEscherHolderRecord { | |||
public static final short sid = 0xEC; | |||
public DrawingRecordForBiffViewer() | |||
{ | |||
public DrawingRecordForBiffViewer() {} | |||
public DrawingRecordForBiffViewer(DrawingRecordForBiffViewer other) { | |||
super(other); | |||
} | |||
public DrawingRecordForBiffViewer( RecordInputStream in) | |||
@@ -59,4 +61,9 @@ public final class DrawingRecordForBiffViewer extends AbstractEscherHolderRecord | |||
{ | |||
return sid; | |||
} | |||
@Override | |||
public DrawingRecordForBiffViewer copy() { | |||
return new DrawingRecordForBiffViewer(this); | |||
} | |||
} |
@@ -20,13 +20,14 @@ package org.apache.poi.hssf.record; | |||
import org.apache.poi.util.HexDump; | |||
import org.apache.poi.util.LittleEndianInput; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* MsoDrawingSelection (0x00ED)<p> | |||
* Reference: | |||
* [MS-OGRAPH].pdf sec 2.4.69 | |||
*/ | |||
public final class DrawingSelectionRecord extends StandardRecord implements Cloneable { | |||
public final class DrawingSelectionRecord extends StandardRecord { | |||
public static final short sid = 0x00ED; | |||
/** | |||
@@ -44,6 +45,12 @@ public final class DrawingSelectionRecord extends StandardRecord implements Clon | |||
private final int _type; | |||
private final int _length; | |||
public OfficeArtRecordHeader(OfficeArtRecordHeader other) { | |||
_verAndInstance = other._verAndInstance; | |||
_type = other._type; | |||
_length = other._length; | |||
} | |||
public OfficeArtRecordHeader(LittleEndianInput in) { | |||
_verAndInstance = in.readUShort(); | |||
_type = in.readUShort(); | |||
@@ -57,11 +64,10 @@ public final class DrawingSelectionRecord extends StandardRecord implements Clon | |||
} | |||
public String debugFormatAsString() { | |||
StringBuilder sb = new StringBuilder(32); | |||
sb.append("ver+inst=").append(HexDump.shortToHex(_verAndInstance)); | |||
sb.append(" type=").append(HexDump.shortToHex(_type)); | |||
sb.append(" len=").append(HexDump.intToHex(_length)); | |||
return sb.toString(); | |||
return | |||
"ver+inst=" + HexDump.shortToHex(_verAndInstance) + | |||
" type=" + HexDump.shortToHex(_type) + | |||
" len=" + HexDump.intToHex(_length); | |||
} | |||
} | |||
@@ -93,7 +99,7 @@ public final class DrawingSelectionRecord extends StandardRecord implements Clon | |||
} | |||
protected int getDataSize() { | |||
return OfficeArtRecordHeader.ENCODED_SIZE | |||
return OfficeArtRecordHeader.ENCODED_SIZE | |||
+ 12 // 3 int fields | |||
+ _shapeIds.length * 4; | |||
} | |||
@@ -109,7 +115,15 @@ public final class DrawingSelectionRecord extends StandardRecord implements Clon | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public DrawingSelectionRecord clone() { | |||
return copy(); | |||
} | |||
@Override | |||
public DrawingSelectionRecord copy() { | |||
// currently immutable | |||
return this; | |||
} |
@@ -18,33 +18,25 @@ | |||
package org.apache.poi.hssf.record; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* End Of File record. | |||
* <P> | |||
* Description: Marks the end of records belonging to a particular object in the | |||
* HSSF File<P> | |||
* REFERENCE: PG 307 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> | |||
* @author Andrew C. Oliver (acoliver at apache dot org) | |||
* @author Jason Height (jheight at chariot dot net dot au) | |||
* Marks the end of records belonging to a particular object in the HSSF File | |||
* | |||
* @version 2.0-pre | |||
*/ | |||
public final class EOFRecord extends StandardRecord implements Cloneable { | |||
public final static short sid = 0x0A; | |||
public final class EOFRecord extends StandardRecord { | |||
public static final short sid = 0x0A; | |||
public static final int ENCODED_SIZE = 4; | |||
public static final EOFRecord instance = new EOFRecord(); | |||
private EOFRecord() { | |||
// no data fields | |||
} | |||
private EOFRecord() {} | |||
/** | |||
* @param in unused (since this record has no data) | |||
*/ | |||
public EOFRecord(RecordInputStream in) | |||
{ | |||
} | |||
public EOFRecord(RecordInputStream in) {} | |||
public String toString() | |||
{ | |||
@@ -68,7 +60,15 @@ public final class EOFRecord extends StandardRecord implements Cloneable { | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public EOFRecord clone() { | |||
return copy(); | |||
} | |||
@Override | |||
public EOFRecord copy() { | |||
return instance; | |||
} | |||
} |
@@ -33,6 +33,7 @@ import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.POILogFactory; | |||
import org.apache.poi.util.POILogger; | |||
import org.apache.poi.util.RecordFormatException; | |||
import org.apache.poi.util.Removal; | |||
import org.apache.poi.util.StringUtil; | |||
/** | |||
@@ -40,7 +41,7 @@ import org.apache.poi.util.StringUtil; | |||
* A sub-record within the OBJ record which stores a reference to an object | |||
* stored in a separate entry within the OLE2 compound file. | |||
*/ | |||
public final class EmbeddedObjectRefSubRecord extends SubRecord implements Cloneable { | |||
public final class EmbeddedObjectRefSubRecord extends SubRecord { | |||
private static POILogger logger = POILogFactory.getLogger(EmbeddedObjectRefSubRecord.class); | |||
//arbitrarily selected; may need to increase | |||
private static final int MAX_RECORD_LENGTH = 100_000; | |||
@@ -73,8 +74,16 @@ public final class EmbeddedObjectRefSubRecord extends SubRecord implements Clone | |||
field_4_ole_classname = null; | |||
} | |||
public short getSid() { | |||
return sid; | |||
public EmbeddedObjectRefSubRecord(EmbeddedObjectRefSubRecord other) { | |||
super(other); | |||
field_1_unknown_int = other.field_1_unknown_int; | |||
field_2_refPtg = (other.field_2_refPtg == null) ? null : other.field_2_refPtg.copy(); | |||
field_2_unknownFormulaData = (other.field_2_unknownFormulaData == null) ? null : other.field_2_unknownFormulaData.clone(); | |||
field_3_unicode_flag = other.field_3_unicode_flag; | |||
field_4_ole_classname = other.field_4_ole_classname; | |||
field_4_unknownByte = other.field_4_unknownByte; | |||
field_5_stream_id = other.field_5_stream_id; | |||
field_6_unknown = (other.field_6_unknown == null) ? null : other.field_6_unknown.clone(); | |||
} | |||
public EmbeddedObjectRefSubRecord(LittleEndianInput in, int size) { | |||
@@ -158,6 +167,10 @@ public final class EmbeddedObjectRefSubRecord extends SubRecord implements Clone | |||
field_6_unknown = readRawData(in, remaining); | |||
} | |||
public short getSid() { | |||
return sid; | |||
} | |||
private static Ptg readRefPtg(byte[] formulaRawBytes) { | |||
LittleEndianInput in = new LittleEndianInputStream(new ByteArrayInputStream(formulaRawBytes)); | |||
byte ptgSid = in.readByte(); | |||
@@ -310,8 +323,16 @@ public final class EmbeddedObjectRefSubRecord extends SubRecord implements Clone | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public EmbeddedObjectRefSubRecord clone() { | |||
return this; // TODO proper clone | |||
return copy(); | |||
} | |||
@Override | |||
public EmbeddedObjectRefSubRecord copy() { | |||
return new EmbeddedObjectRefSubRecord(this); | |||
} | |||
public String toString() { | |||
@@ -339,15 +360,15 @@ public final class EmbeddedObjectRefSubRecord extends SubRecord implements Clone | |||
sb.append("[/ftPictFmla]"); | |||
return sb.toString(); | |||
} | |||
public void setUnknownFormulaData(byte[] formularData) { | |||
field_2_unknownFormulaData = formularData; | |||
} | |||
public void setOleClassname(String oleClassname) { | |||
field_4_ole_classname = oleClassname; | |||
} | |||
public void setStorageId(int storageId) { | |||
field_5_stream_id = storageId; | |||
} |
@@ -14,27 +14,25 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.hssf.record; | |||
import org.apache.poi.util.LittleEndianInput; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.RecordFormatException; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* ftEnd (0x0000)<p> | |||
* | |||
* | |||
* The end data record is used to denote the end of the subrecords. | |||
*/ | |||
public final class EndSubRecord extends SubRecord implements Cloneable { | |||
public final class EndSubRecord extends SubRecord { | |||
// Note - zero sid is somewhat unusual (compared to plain Records) | |||
public final static short sid = 0x0000; | |||
public static final short sid = 0x0000; | |||
private static final int ENCODED_SIZE = 0; | |||
public EndSubRecord() | |||
{ | |||
} | |||
public EndSubRecord() {} | |||
/** | |||
* @param in unused (since this record has no data) | |||
@@ -76,8 +74,15 @@ public final class EndSubRecord extends SubRecord implements Cloneable { | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public EndSubRecord clone() { | |||
return copy(); | |||
} | |||
@Override | |||
public EndSubRecord copy() { | |||
return new EndSubRecord(); | |||
} | |||
} |
@@ -85,7 +85,7 @@ import org.apache.poi.util.RecordFormatException; | |||
public final class EscherAggregate extends AbstractEscherHolderRecord { | |||
public static final short sid = 9876; // not a real sid - dummy value | |||
private static POILogger log = POILogFactory.getLogger(EscherAggregate.class); | |||
private static final POILogger log = POILogFactory.getLogger(EscherAggregate.class); | |||
//arbitrarily selected; may need to increase | |||
private static final int MAX_RECORD_LENGTH = 100_000_000; | |||
@@ -317,6 +317,13 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { | |||
} | |||
} | |||
public EscherAggregate(EscherAggregate other) { | |||
super(other); | |||
// shallow copy, because the aggregates doesn't own the records | |||
shapeToObj.putAll(other.shapeToObj); | |||
tailRec.putAll(other.tailRec); | |||
} | |||
/** | |||
* @return Returns the current sid. | |||
*/ | |||
@@ -814,4 +821,9 @@ public final class EscherAggregate extends AbstractEscherHolderRecord { | |||
public void removeTailRecord(NoteRecord note) { | |||
tailRec.remove(note.getShapeId()); | |||
} | |||
@Override | |||
public EscherAggregate copy() { | |||
return new EscherAggregate(this); | |||
} | |||
} |
@@ -17,28 +17,27 @@ | |||
package org.apache.poi.hssf.record; | |||
import java.util.ArrayList; | |||
import java.util.stream.Stream; | |||
import org.apache.poi.hssf.record.cont.ContinuableRecord; | |||
import org.apache.poi.hssf.record.cont.ContinuableRecordOutput; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import java.util.ArrayList; | |||
/** | |||
* Title: Extended Static String Table (0x00FF)<p> | |||
* Description: This record is used for a quick lookup into the SST record. This | |||
* record breaks the SST table into a set of buckets. The offsets | |||
* to these buckets within the SST record are kept as well as the | |||
* position relative to the start of the SST record.<p> | |||
* REFERENCE: PG 313 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) | |||
* Extended Static String Table (0x00FF)<p> | |||
* This record is used for a quick lookup into the SST record. This record breaks the SST table | |||
* into a set of buckets. The offsets to these buckets within the SST record are kept as well as | |||
* the position relative to the start of the SST record. | |||
*/ | |||
public final class ExtSSTRecord extends ContinuableRecord { | |||
public final static short sid = 0x00FF; | |||
public static final short sid = 0x00FF; | |||
public static final int DEFAULT_BUCKET_SIZE = 8; | |||
//Can't seem to find this documented but from the biffviewer it is clear that | |||
//Excel only records the indexes for the first 128 buckets. | |||
public static final int MAX_BUCKETS = 128; | |||
public static final class InfoSubRecord { | |||
public static final int ENCODED_SIZE = 8; | |||
private int field_1_stream_pos; // stream pointer to the SST record | |||
@@ -48,7 +47,7 @@ public final class ExtSSTRecord extends ContinuableRecord { | |||
/** | |||
* Creates new ExtSSTInfoSubRecord | |||
* | |||
* | |||
* @param streamPos stream pointer to the SST record | |||
* @param bucketSstOffset ... don't really understand this yet | |||
*/ | |||
@@ -57,6 +56,12 @@ public final class ExtSSTRecord extends ContinuableRecord { | |||
field_2_bucket_sst_offset = bucketSstOffset; | |||
} | |||
public InfoSubRecord(InfoSubRecord other) { | |||
field_1_stream_pos = other.field_1_stream_pos; | |||
field_2_bucket_sst_offset = other.field_2_bucket_sst_offset; | |||
field_3_zero = other.field_3_zero; | |||
} | |||
public InfoSubRecord(RecordInputStream in) | |||
{ | |||
field_1_stream_pos = in.readInt(); | |||
@@ -78,8 +83,8 @@ public final class ExtSSTRecord extends ContinuableRecord { | |||
out.writeShort(field_3_zero); | |||
} | |||
} | |||
private short _stringsPerBucket; | |||
private InfoSubRecord[] _sstInfos; | |||
@@ -89,6 +94,12 @@ public final class ExtSSTRecord extends ContinuableRecord { | |||
_sstInfos = new InfoSubRecord[0]; | |||
} | |||
public ExtSSTRecord(ExtSSTRecord other) { | |||
_stringsPerBucket = other._stringsPerBucket; | |||
_sstInfos = (other._sstInfos == null) ? null | |||
: Stream.of(other._sstInfos).map(InfoSubRecord::new).toArray(InfoSubRecord[]::new); | |||
} | |||
public ExtSSTRecord(RecordInputStream in) { | |||
_stringsPerBucket = in.readShort(); | |||
@@ -161,9 +172,9 @@ public final class ExtSSTRecord extends ContinuableRecord { | |||
/** | |||
* Given a number of strings (in the sst), returns the size of the extsst record | |||
* | |||
* | |||
* @param numStrings the number of strings | |||
* | |||
* | |||
* @return the size of the extsst record | |||
*/ | |||
public static int getRecordSizeForStrings(int numStrings) { | |||
@@ -181,4 +192,9 @@ public final class ExtSSTRecord extends ContinuableRecord { | |||
_sstInfos[i] = new InfoSubRecord(bucketAbsoluteOffsets[i], bucketRelativeOffsets[i]); | |||
} | |||
} | |||
@Override | |||
public ExtSSTRecord copy() { | |||
return new ExtSSTRecord(this); | |||
} | |||
} |
@@ -14,7 +14,7 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.hssf.record; | |||
@@ -23,179 +23,164 @@ import org.apache.poi.util.BitFieldFactory; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
/** | |||
* Title: Extended Format Record | |||
* Description: Probably one of the more complex records. There are two breeds: | |||
* Style and Cell. | |||
*<P> | |||
* It should be noted that fields in the extended format record are | |||
* somewhat arbitrary. Almost all of the fields are bit-level, but | |||
* we name them as best as possible by functional group. In some | |||
* places this is better than others. | |||
*<P> | |||
* Probably one of the more complex records.<p> | |||
* There are two breeds: Style and Cell.<p> | |||
* It should be noted that fields in the extended format record are somewhat arbitrary. | |||
* Almost all of the fields are bit-level, but we name them as best as possible by functional group. | |||
* In some places this is better than others. | |||
* | |||
* REFERENCE: PG 426 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) | |||
* @since 2.0-pre | |||
*/ | |||
public final class ExtendedFormatRecord | |||
extends StandardRecord | |||
{ | |||
public static final short sid = 0xE0; | |||
public final class ExtendedFormatRecord extends StandardRecord { | |||
public static final short sid = 0xE0; | |||
// null constant | |||
public static final short NULL = (short)0xfff0; | |||
public static final short NULL = (short)0xfff0; | |||
// xf type | |||
public static final short XF_STYLE = 1; | |||
public static final short XF_CELL = 0; | |||
public static final short XF_STYLE = 1; | |||
public static final short XF_CELL = 0; | |||
// borders | |||
public static final short NONE = 0x0; | |||
public static final short THIN = 0x1; | |||
public static final short MEDIUM = 0x2; | |||
public static final short DASHED = 0x3; | |||
public static final short DOTTED = 0x4; | |||
public static final short THICK = 0x5; | |||
public static final short DOUBLE = 0x6; | |||
public static final short HAIR = 0x7; | |||
public static final short MEDIUM_DASHED = 0x8; | |||
public static final short DASH_DOT = 0x9; | |||
public static final short MEDIUM_DASH_DOT = 0xA; | |||
public static final short DASH_DOT_DOT = 0xB; | |||
public static final short MEDIUM_DASH_DOT_DOT = 0xC; | |||
public static final short SLANTED_DASH_DOT = 0xD; | |||
public static final short NONE = 0x0; | |||
public static final short THIN = 0x1; | |||
public static final short MEDIUM = 0x2; | |||
public static final short DASHED = 0x3; | |||
public static final short DOTTED = 0x4; | |||
public static final short THICK = 0x5; | |||
public static final short DOUBLE = 0x6; | |||
public static final short HAIR = 0x7; | |||
public static final short MEDIUM_DASHED = 0x8; | |||
public static final short DASH_DOT = 0x9; | |||
public static final short MEDIUM_DASH_DOT = 0xA; | |||
public static final short DASH_DOT_DOT = 0xB; | |||
public static final short MEDIUM_DASH_DOT_DOT = 0xC; | |||
public static final short SLANTED_DASH_DOT = 0xD; | |||
// alignment | |||
public static final short GENERAL = 0x0; | |||
public static final short LEFT = 0x1; | |||
public static final short CENTER = 0x2; | |||
public static final short RIGHT = 0x3; | |||
public static final short FILL = 0x4; | |||
public static final short JUSTIFY = 0x5; | |||
public static final short CENTER_SELECTION = 0x6; | |||
public static final short GENERAL = 0x0; | |||
public static final short LEFT = 0x1; | |||
public static final short CENTER = 0x2; | |||
public static final short RIGHT = 0x3; | |||
public static final short FILL = 0x4; | |||
public static final short JUSTIFY = 0x5; | |||
public static final short CENTER_SELECTION = 0x6; | |||
// vertical alignment | |||
public static final short VERTICAL_TOP = 0x0; | |||
public static final short VERTICAL_CENTER = 0x1; | |||
public static final short VERTICAL_BOTTOM = 0x2; | |||
public static final short VERTICAL_JUSTIFY = 0x3; | |||
public static final short VERTICAL_TOP = 0x0; | |||
public static final short VERTICAL_CENTER = 0x1; | |||
public static final short VERTICAL_BOTTOM = 0x2; | |||
public static final short VERTICAL_JUSTIFY = 0x3; | |||
// fill | |||
public static final short NO_FILL = 0 ; | |||
public static final short SOLID_FILL = 1 ; | |||
public static final short FINE_DOTS = 2 ; | |||
public static final short ALT_BARS = 3 ; | |||
public static final short SPARSE_DOTS = 4 ; | |||
public static final short THICK_HORZ_BANDS = 5 ; | |||
public static final short THICK_VERT_BANDS = 6 ; | |||
public static final short THICK_BACKWARD_DIAG = 7 ; | |||
public static final short THICK_FORWARD_DIAG = 8 ; | |||
public static final short BIG_SPOTS = 9 ; | |||
public static final short BRICKS = 10 ; | |||
public static final short THIN_HORZ_BANDS = 11 ; | |||
public static final short THIN_VERT_BANDS = 12 ; | |||
public static final short THIN_BACKWARD_DIAG = 13 ; | |||
public static final short THIN_FORWARD_DIAG = 14 ; | |||
public static final short SQUARES = 15 ; | |||
public static final short DIAMONDS = 16 ; | |||
// fields in BOTH style and Cell XF records | |||
private short field_1_font_index; // not bit-mapped | |||
private short field_2_format_index; // not bit-mapped | |||
public static final short NO_FILL = 0; | |||
public static final short SOLID_FILL = 1; | |||
public static final short FINE_DOTS = 2; | |||
public static final short ALT_BARS = 3; | |||
public static final short SPARSE_DOTS = 4; | |||
public static final short THICK_HORZ_BANDS = 5; | |||
public static final short THICK_VERT_BANDS = 6; | |||
public static final short THICK_BACKWARD_DIAG = 7; | |||
public static final short THICK_FORWARD_DIAG = 8; | |||
public static final short BIG_SPOTS = 9; | |||
public static final short BRICKS = 10; | |||
public static final short THIN_HORZ_BANDS = 11; | |||
public static final short THIN_VERT_BANDS = 12; | |||
public static final short THIN_BACKWARD_DIAG = 13; | |||
public static final short THIN_FORWARD_DIAG = 14; | |||
public static final short SQUARES = 15; | |||
public static final short DIAMONDS = 16; | |||
// field_3_cell_options bit map | |||
private static final BitField _locked = BitFieldFactory.getInstance(0x0001); | |||
private static final BitField _hidden = BitFieldFactory.getInstance(0x0002); | |||
private static final BitField _xf_type = BitFieldFactory.getInstance(0x0004); | |||
private static final BitField _123_prefix = BitFieldFactory.getInstance(0x0008); | |||
private static final BitField _parent_index = BitFieldFactory.getInstance(0xFFF0); | |||
private short field_3_cell_options; | |||
private static final BitField _locked = bf(0x0001); | |||
private static final BitField _hidden = bf(0x0002); | |||
private static final BitField _xf_type = bf(0x0004); | |||
private static final BitField _123_prefix = bf(0x0008); | |||
private static final BitField _parent_index = bf(0xFFF0); | |||
// field_4_alignment_options bit map | |||
private static final BitField _alignment = BitFieldFactory.getInstance(0x0007); | |||
private static final BitField _wrap_text = BitFieldFactory.getInstance(0x0008); | |||
private static final BitField _vertical_alignment = BitFieldFactory.getInstance(0x0070); | |||
private static final BitField _justify_last = BitFieldFactory.getInstance(0x0080); | |||
private static final BitField _rotation = BitFieldFactory.getInstance(0xFF00); | |||
private short field_4_alignment_options; | |||
private static final BitField _alignment = bf(0x0007); | |||
private static final BitField _wrap_text = bf(0x0008); | |||
private static final BitField _vertical_alignment = bf(0x0070); | |||
private static final BitField _justify_last = bf(0x0080); | |||
private static final BitField _rotation = bf(0xFF00); | |||
// field_5_indention_options | |||
private static final BitField _indent = | |||
BitFieldFactory.getInstance(0x000F); | |||
private static final BitField _shrink_to_fit = | |||
BitFieldFactory.getInstance(0x0010); | |||
private static final BitField _merge_cells = | |||
BitFieldFactory.getInstance(0x0020); | |||
private static final BitField _reading_order = | |||
BitFieldFactory.getInstance(0x00C0); | |||
private static final BitField _indent = bf(0x000F); | |||
private static final BitField _shrink_to_fit = bf(0x0010); | |||
private static final BitField _merge_cells = bf(0x0020); | |||
private static final BitField _reading_order = bf(0x00C0); | |||
// apparently bits 8 and 9 are unused | |||
private static final BitField _indent_not_parent_format = | |||
BitFieldFactory.getInstance(0x0400); | |||
private static final BitField _indent_not_parent_font = | |||
BitFieldFactory.getInstance(0x0800); | |||
private static final BitField _indent_not_parent_alignment = | |||
BitFieldFactory.getInstance(0x1000); | |||
private static final BitField _indent_not_parent_border = | |||
BitFieldFactory.getInstance(0x2000); | |||
private static final BitField _indent_not_parent_pattern = | |||
BitFieldFactory.getInstance(0x4000); | |||
private static final BitField _indent_not_parent_cell_options = | |||
BitFieldFactory.getInstance(0x8000); | |||
private short field_5_indention_options; | |||
private static final BitField _indent_not_parent_format = bf(0x0400); | |||
private static final BitField _indent_not_parent_font = bf(0x0800); | |||
private static final BitField _indent_not_parent_alignment = bf(0x1000); | |||
private static final BitField _indent_not_parent_border = bf(0x2000); | |||
private static final BitField _indent_not_parent_pattern = bf(0x4000); | |||
private static final BitField _indent_not_parent_cell_options = bf(0x8000); | |||
// field_6_border_options bit map | |||
private static final BitField _border_left = BitFieldFactory.getInstance(0x000F); | |||
private static final BitField _border_right = BitFieldFactory.getInstance(0x00F0); | |||
private static final BitField _border_top = BitFieldFactory.getInstance(0x0F00); | |||
private static final BitField _border_bottom = BitFieldFactory.getInstance(0xF000); | |||
private short field_6_border_options; | |||
private static final BitField _border_left = bf(0x000F); | |||
private static final BitField _border_right = bf(0x00F0); | |||
private static final BitField _border_top = bf(0x0F00); | |||
private static final BitField _border_bottom = bf(0xF000); | |||
// all three of the following attributes are palette options | |||
// field_7_palette_options bit map | |||
private static final BitField _left_border_palette_idx = | |||
BitFieldFactory.getInstance(0x007F); | |||
private static final BitField _right_border_palette_idx = | |||
BitFieldFactory.getInstance(0x3F80); | |||
private static final BitField _diag = | |||
BitFieldFactory.getInstance(0xC000); | |||
private short field_7_palette_options; | |||
private static final BitField _left_border_palette_idx = bf(0x007F); | |||
private static final BitField _right_border_palette_idx = bf(0x3F80); | |||
private static final BitField _diag = bf(0xC000); | |||
// field_8_adtl_palette_options bit map | |||
private static final BitField _top_border_palette_idx = | |||
BitFieldFactory.getInstance(0x0000007F); | |||
private static final BitField _bottom_border_palette_idx = | |||
BitFieldFactory.getInstance(0x00003F80); | |||
private static final BitField _adtl_diag = | |||
BitFieldFactory.getInstance(0x001fc000); | |||
private static final BitField _adtl_diag_line_style = | |||
BitFieldFactory.getInstance(0x01e00000); | |||
private static final BitField _top_border_palette_idx = bf(0x0000007F); | |||
private static final BitField _bottom_border_palette_idx = bf(0x00003F80); | |||
private static final BitField _adtl_diag = bf(0x001fc000); | |||
private static final BitField _adtl_diag_line_style = bf(0x01e00000); | |||
// apparently bit 25 is unused | |||
private static final BitField _adtl_fill_pattern = | |||
BitFieldFactory.getInstance(0xfc000000); | |||
private int field_8_adtl_palette_options; // additional to avoid 2 | |||
private static final BitField _adtl_fill_pattern = bf(0xfc000000); | |||
// field_9_fill_palette_options bit map | |||
private static final BitField _fill_foreground = BitFieldFactory.getInstance(0x007F); | |||
private static final BitField _fill_background = BitFieldFactory.getInstance(0x3f80); | |||
private static final BitField _fill_foreground = bf(0x007F); | |||
private static final BitField _fill_background = bf(0x3f80); | |||
private static BitField bf(int i) { | |||
return BitFieldFactory.getInstance(i); | |||
} | |||
// fields in BOTH style and Cell XF records | |||
private short field_1_font_index; // not bit-mapped | |||
private short field_2_format_index; // not bit-mapped | |||
private short field_3_cell_options; | |||
private short field_4_alignment_options; | |||
private short field_5_indention_options; | |||
private short field_6_border_options; | |||
private short field_7_palette_options; | |||
private int field_8_adtl_palette_options; // additional to avoid 2 | |||
// apparently bits 15 and 14 are unused | |||
private short field_9_fill_palette_options; | |||
private short field_9_fill_palette_options; | |||
/** | |||
* Constructor ExtendedFormatRecord | |||
* | |||
* | |||
*/ | |||
public ExtendedFormatRecord() {} | |||
public ExtendedFormatRecord() | |||
{ | |||
public ExtendedFormatRecord(ExtendedFormatRecord other) { | |||
super(other); | |||
field_1_font_index = other.field_1_font_index; | |||
field_2_format_index = other.field_2_format_index; | |||
field_3_cell_options = other.field_3_cell_options; | |||
field_4_alignment_options = other.field_4_alignment_options; | |||
field_5_indention_options = other.field_5_indention_options; | |||
field_6_border_options = other.field_6_border_options; | |||
field_7_palette_options = other.field_7_palette_options; | |||
field_8_adtl_palette_options = other.field_8_adtl_palette_options; | |||
field_9_fill_palette_options = other.field_9_fill_palette_options; | |||
} | |||
public ExtendedFormatRecord(RecordInputStream in) | |||
{ | |||
public ExtendedFormatRecord(RecordInputStream in) { | |||
field_1_font_index = in.readShort(); | |||
field_2_format_index = in.readShort(); | |||
field_3_cell_options = in.readShort(); | |||
@@ -560,7 +545,7 @@ public final class ExtendedFormatRecord | |||
/** | |||
* <p>Sets whether or not to use the pattern in this XF instead of the | |||
* parent XF (foreground/background).</p> | |||
* | |||
* | |||
* @param pattern {@code true} if this XF has a different pattern | |||
* value than its parent, {@code false} otherwise. | |||
* @see #setIndentionOptions(short) | |||
@@ -1788,16 +1773,16 @@ public final class ExtendedFormatRecord | |||
{ | |||
return sid; | |||
} | |||
/** | |||
* Clones all the style information from another | |||
* ExtendedFormatRecord, onto this one. This | |||
* ExtendedFormatRecord, onto this one. This | |||
* will then hold all the same style options. | |||
* | |||
* | |||
* If The source ExtendedFormatRecord comes from | |||
* a different Workbook, you will need to sort | |||
* out the font and format indices yourself! | |||
* | |||
* | |||
* @param source the ExtendedFormatRecord to copy from | |||
*/ | |||
public void cloneStyleFrom(ExtendedFormatRecord source) { | |||
@@ -1863,11 +1848,15 @@ public final class ExtendedFormatRecord | |||
} | |||
return false; | |||
} | |||
public int[] stateSummary() { | |||
return new int[] { field_1_font_index, field_2_format_index, field_3_cell_options, field_4_alignment_options, | |||
field_5_indention_options, field_6_border_options, field_7_palette_options, field_8_adtl_palette_options, field_9_fill_palette_options }; | |||
} | |||
@Override | |||
public ExtendedFormatRecord copy() { | |||
return new ExtendedFormatRecord(this); | |||
} | |||
} |
@@ -28,9 +28,9 @@ import org.apache.poi.util.LittleEndianOutput; | |||
*/ | |||
public class ExternSheetRecord extends StandardRecord { | |||
public final static short sid = 0x0017; | |||
private final List<RefSubRecord> _list; | |||
public static final short sid = 0x0017; | |||
private final List<RefSubRecord> _list = new ArrayList<>(); | |||
private static final class RefSubRecord { | |||
public static final int ENCODED_SIZE = 6; | |||
@@ -38,26 +38,31 @@ public class ExternSheetRecord extends StandardRecord { | |||
private final int _extBookIndex; | |||
private int _firstSheetIndex; // may be -1 (0xFFFF) | |||
private int _lastSheetIndex; // may be -1 (0xFFFF) | |||
public void adjustIndex(int offset) { | |||
_firstSheetIndex += offset; | |||
_lastSheetIndex += offset; | |||
} | |||
/** a Constructor for making new sub record | |||
*/ | |||
public RefSubRecord(int extBookIndex, int firstSheetIndex, int lastSheetIndex) { | |||
_extBookIndex = extBookIndex; | |||
_firstSheetIndex = firstSheetIndex; | |||
_lastSheetIndex = lastSheetIndex; | |||
} | |||
public RefSubRecord(RefSubRecord other) { | |||
_extBookIndex = other._extBookIndex; | |||
_firstSheetIndex = other._firstSheetIndex; | |||
_lastSheetIndex = other._lastSheetIndex; | |||
} | |||
/** | |||
* @param in the RecordInputstream to read the record from | |||
*/ | |||
public RefSubRecord(RecordInputStream in) { | |||
this(in.readShort(), in.readShort(), in.readShort()); | |||
} | |||
public void adjustIndex(int offset) { | |||
_firstSheetIndex += offset; | |||
_lastSheetIndex += offset; | |||
} | |||
public int getExtBookIndex(){ | |||
return _extBookIndex; | |||
} | |||
@@ -67,7 +72,7 @@ public class ExternSheetRecord extends StandardRecord { | |||
public int getLastSheetIndex(){ | |||
return _lastSheetIndex; | |||
} | |||
@Override | |||
public String toString() { | |||
StringBuilder buffer = new StringBuilder(); | |||
@@ -76,55 +81,53 @@ public class ExternSheetRecord extends StandardRecord { | |||
buffer.append(" lastSheet=").append(_lastSheetIndex); | |||
return buffer.toString(); | |||
} | |||
public void serialize(LittleEndianOutput out) { | |||
out.writeShort(_extBookIndex); | |||
out.writeShort(_firstSheetIndex); | |||
out.writeShort(_lastSheetIndex); | |||
} | |||
} | |||
public ExternSheetRecord() { | |||
_list = new ArrayList<>(); | |||
} | |||
public ExternSheetRecord() {} | |||
public ExternSheetRecord(ExternSheetRecord other) { | |||
other._list.stream().map(RefSubRecord::new).forEach(_list::add); | |||
} | |||
public ExternSheetRecord(RecordInputStream in) { | |||
_list = new ArrayList<>(); | |||
int nItems = in.readShort(); | |||
for (int i = 0 ; i < nItems ; ++i) { | |||
RefSubRecord rec = new RefSubRecord(in); | |||
_list.add(rec); | |||
} | |||
} | |||
/** | |||
/** | |||
* @return number of REF structures | |||
*/ | |||
public int getNumOfRefs() { | |||
return _list.size(); | |||
} | |||
/** | |||
/** | |||
* adds REF struct (ExternSheetSubRecord) | |||
* @param rec REF struct | |||
*/ | |||
public void addREFRecord(RefSubRecord rec) { | |||
_list.add(rec); | |||
} | |||
/** returns the number of REF Records, which is in model | |||
* @return number of REF records | |||
*/ | |||
public int getNumOfREFRecords() { | |||
return _list.size(); | |||
} | |||
@Override | |||
public String toString() { | |||
StringBuilder sb = new StringBuilder(); | |||
@@ -137,22 +140,22 @@ public class ExternSheetRecord extends StandardRecord { | |||
sb.append('\n'); | |||
} | |||
sb.append("[/EXTERNSHEET]\n"); | |||
return sb.toString(); | |||
} | |||
@Override | |||
protected int getDataSize() { | |||
return 2 + _list.size() * RefSubRecord.ENCODED_SIZE; | |||
} | |||
@Override | |||
public void serialize(LittleEndianOutput out) { | |||
int nItems = _list.size(); | |||
out.writeShort(nItems); | |||
for (int i = 0; i < nItems; i++) { | |||
getRef(i).serialize(out); | |||
} | |||
@@ -161,22 +164,22 @@ public class ExternSheetRecord extends StandardRecord { | |||
private RefSubRecord getRef(int i) { | |||
return _list.get(i); | |||
} | |||
public void removeSheet(int sheetIdx) { | |||
int nItems = _list.size(); | |||
for (int i = 0; i < nItems; i++) { | |||
RefSubRecord refSubRecord = _list.get(i); | |||
if(refSubRecord.getFirstSheetIndex() == sheetIdx && | |||
if(refSubRecord.getFirstSheetIndex() == sheetIdx && | |||
refSubRecord.getLastSheetIndex() == sheetIdx) { | |||
// removing the entry would mess up the sheet index in Formula of NameRecord | |||
_list.set(i, new RefSubRecord(refSubRecord.getExtBookIndex(), -1, -1)); | |||
} else if (refSubRecord.getFirstSheetIndex() > sheetIdx && | |||
} else if (refSubRecord.getFirstSheetIndex() > sheetIdx && | |||
refSubRecord.getLastSheetIndex() > sheetIdx) { | |||
_list.set(i, new RefSubRecord(refSubRecord.getExtBookIndex(), refSubRecord.getFirstSheetIndex()-1, refSubRecord.getLastSheetIndex()-1)); | |||
} | |||
} | |||
} | |||
/** | |||
* return the non static version of the id for this record. | |||
*/ | |||
@@ -187,7 +190,7 @@ public class ExternSheetRecord extends StandardRecord { | |||
/** | |||
* @param refIndex specifies the n-th refIndex | |||
* | |||
* | |||
* @return the index of the SupBookRecord for this index | |||
*/ | |||
public int getExtbookIndexFromRefIndex(int refIndex) { | |||
@@ -197,7 +200,7 @@ public class ExternSheetRecord extends StandardRecord { | |||
/** | |||
* @param extBookIndex external sheet reference index | |||
* | |||
* | |||
* @return -1 if not found | |||
*/ | |||
public int findRefIndexFromExtBookIndex(int extBookIndex) { | |||
@@ -214,9 +217,9 @@ public class ExternSheetRecord extends StandardRecord { | |||
* Returns the first sheet that the reference applies to, or | |||
* -1 if the referenced sheet can't be found, or -2 if the | |||
* reference is workbook scoped. | |||
* | |||
* | |||
* @param extRefIndex external sheet reference index | |||
* | |||
* | |||
* @return the first sheet that the reference applies to, or | |||
* -1 if the referenced sheet can't be found, or -2 if the | |||
* reference is workbook scoped | |||
@@ -231,9 +234,9 @@ public class ExternSheetRecord extends StandardRecord { | |||
* reference is workbook scoped. | |||
* For a single sheet reference, the first and last should be | |||
* the same. | |||
* | |||
* | |||
* @param extRefIndex external sheet reference index | |||
* | |||
* | |||
* @return the last sheet that the reference applies to, or | |||
* -1 if the referenced sheet can't be found, or -2 if the | |||
* reference is workbook scoped. | |||
@@ -258,7 +261,7 @@ public class ExternSheetRecord extends StandardRecord { | |||
* see {@link org.apache.poi.hssf.record.SupBookRecord#getSheetNames()}. | |||
* This referenced string specifies the name of the first sheet within the external workbook that is in scope. | |||
* This sheet MUST be a worksheet or macro sheet.</p> | |||
* | |||
* | |||
* <p>If the supporting link type is self-referencing, then this value specifies the zero-based index of a | |||
* {@link org.apache.poi.hssf.record.BoundSheetRecord} record in the workbook stream that specifies | |||
* the first sheet within the scope of this reference. This sheet MUST be a worksheet or a macro sheet. | |||
@@ -283,7 +286,7 @@ public class ExternSheetRecord extends StandardRecord { | |||
if (ref.getExtBookIndex() != externalBookIndex) { | |||
continue; | |||
} | |||
if (ref.getFirstSheetIndex() == firstSheetIndex && | |||
if (ref.getFirstSheetIndex() == firstSheetIndex && | |||
ref.getLastSheetIndex() == lastSheetIndex) { | |||
return i; | |||
} | |||
@@ -301,4 +304,9 @@ public class ExternSheetRecord extends StandardRecord { | |||
} | |||
return result; | |||
} | |||
@Override | |||
public ExternSheetRecord copy() { | |||
return new ExternSheetRecord(this); | |||
} | |||
} |
@@ -28,7 +28,7 @@ import org.apache.poi.util.StringUtil; | |||
*/ | |||
public final class ExternalNameRecord extends StandardRecord { | |||
public final static short sid = 0x0023; // as per BIFF8. (some old versions used 0x223) | |||
public static final short sid = 0x0023; // as per BIFF8. (some old versions used 0x223) | |||
private static final int OPT_BUILTIN_NAME = 0x0001; | |||
private static final int OPT_AUTOMATIC_LINK = 0x0002; // m$ doc calls this fWantAdvise | |||
@@ -39,11 +39,11 @@ public final class ExternalNameRecord extends StandardRecord { | |||
private static final int OPT_ICONIFIED_PICTURE_LINK= 0x8000; | |||
private short field_1_option_flag; | |||
private short field_2_ixals; | |||
private short field_3_not_used; | |||
private short field_1_option_flag; | |||
private short field_2_ixals; | |||
private short field_3_not_used; | |||
private String field_4_name; | |||
private Formula field_5_name_definition; | |||
private Formula field_5_name_definition; | |||
/** | |||
* 'rgoper' / 'Last received results of the DDE link' | |||
@@ -60,6 +60,54 @@ public final class ExternalNameRecord extends StandardRecord { | |||
*/ | |||
private int _nRows; | |||
public ExternalNameRecord() { | |||
field_2_ixals = 0; | |||
} | |||
public ExternalNameRecord(ExternalNameRecord other) { | |||
super(other); | |||
field_1_option_flag = other.field_1_option_flag; | |||
field_2_ixals = other.field_2_ixals; | |||
field_3_not_used = other.field_3_not_used; | |||
field_4_name = other.field_4_name; | |||
field_5_name_definition = (other.field_5_name_definition == null) ? null : other.field_5_name_definition.copy(); | |||
_ddeValues = (other._ddeValues == null) ? null : other._ddeValues.clone(); | |||
_nColumns = other._nColumns; | |||
_nRows = other._nRows; | |||
} | |||
public ExternalNameRecord(RecordInputStream in) { | |||
field_1_option_flag = in.readShort(); | |||
field_2_ixals = in.readShort(); | |||
field_3_not_used = in.readShort(); | |||
int numChars = in.readUByte(); | |||
field_4_name = StringUtil.readUnicodeString(in, numChars); | |||
// the record body can take different forms. | |||
// The form is dictated by the values of 3-th and 4-th bits in field_1_option_flag | |||
if(!isOLELink() && !isStdDocumentNameIdentifier()){ | |||
// another switch: the fWantAdvise bit specifies whether the body describes | |||
// an external defined name or a DDE data item | |||
if(isAutomaticLink()){ | |||
if(in.available() > 0) { | |||
//body specifies DDE data item | |||
int nColumns = in.readUByte() + 1; | |||
int nRows = in.readShort() + 1; | |||
int totalCount = nRows * nColumns; | |||
_ddeValues = ConstantValueParser.parse(in, totalCount); | |||
_nColumns = nColumns; | |||
_nRows = nRows; | |||
} | |||
} else { | |||
//body specifies an external defined name | |||
int formulaLen = in.readUShort(); | |||
field_5_name_definition = Formula.read(formulaLen, in); | |||
} | |||
} | |||
} | |||
/** | |||
* @return {@code true} if the name is a built-in name | |||
*/ | |||
@@ -68,7 +116,7 @@ public final class ExternalNameRecord extends StandardRecord { | |||
} | |||
/** | |||
* For OLE and DDE, links can be either 'automatic' or 'manual' | |||
* | |||
* | |||
* @return {@code true} if this is a automatic link | |||
*/ | |||
public boolean isAutomaticLink() { | |||
@@ -76,7 +124,7 @@ public final class ExternalNameRecord extends StandardRecord { | |||
} | |||
/** | |||
* only for OLE and DDE | |||
* | |||
* | |||
* @return {@code true} if this is a picture link | |||
*/ | |||
public boolean isPicureLink() { | |||
@@ -84,7 +132,7 @@ public final class ExternalNameRecord extends StandardRecord { | |||
} | |||
/** | |||
* DDE links only. If <code>true</code>, this denotes the 'StdDocumentName' | |||
* | |||
* | |||
* @return {@code true} if this denotes the 'StdDocumentName' | |||
*/ | |||
public boolean isStdDocumentNameIdentifier() { | |||
@@ -102,7 +150,7 @@ public final class ExternalNameRecord extends StandardRecord { | |||
public String getText() { | |||
return field_4_name; | |||
} | |||
public void setText(String str) { | |||
field_4_name = str; | |||
} | |||
@@ -112,13 +160,13 @@ public final class ExternalNameRecord extends StandardRecord { | |||
* index of the name of the Sheet this refers to, as | |||
* defined in the preceding {@link SupBookRecord}. | |||
* If it isn't a local name, then it must be zero. | |||
* | |||
* | |||
* @return the index of the name of the Sheet this refers to | |||
*/ | |||
public short getIx() { | |||
return field_2_ixals; | |||
} | |||
public void setIx(short ix) { | |||
field_2_ixals = ix; | |||
} | |||
@@ -134,7 +182,7 @@ public final class ExternalNameRecord extends StandardRecord { | |||
@Override | |||
protected int getDataSize(){ | |||
int result = 2 + 4; // short and int | |||
result += StringUtil.getEncodedSize(field_4_name) - 1; //size is byte, not short | |||
result += StringUtil.getEncodedSize(field_4_name) - 1; //size is byte, not short | |||
if(!isOLELink() && !isStdDocumentNameIdentifier()){ | |||
if(isAutomaticLink()){ | |||
@@ -171,42 +219,6 @@ public final class ExternalNameRecord extends StandardRecord { | |||
} | |||
} | |||
public ExternalNameRecord() { | |||
field_2_ixals = 0; | |||
} | |||
public ExternalNameRecord(RecordInputStream in) { | |||
field_1_option_flag = in.readShort(); | |||
field_2_ixals = in.readShort(); | |||
field_3_not_used = in.readShort(); | |||
int numChars = in.readUByte(); | |||
field_4_name = StringUtil.readUnicodeString(in, numChars); | |||
// the record body can take different forms. | |||
// The form is dictated by the values of 3-th and 4-th bits in field_1_option_flag | |||
if(!isOLELink() && !isStdDocumentNameIdentifier()){ | |||
// another switch: the fWantAdvise bit specifies whether the body describes | |||
// an external defined name or a DDE data item | |||
if(isAutomaticLink()){ | |||
if(in.available() > 0) { | |||
//body specifies DDE data item | |||
int nColumns = in.readUByte() + 1; | |||
int nRows = in.readShort() + 1; | |||
int totalCount = nRows * nColumns; | |||
_ddeValues = ConstantValueParser.parse(in, totalCount); | |||
_nColumns = nColumns; | |||
_nRows = nRows; | |||
} | |||
} else { | |||
//body specifies an external defined name | |||
int formulaLen = in.readUShort(); | |||
field_5_name_definition = Formula.read(formulaLen, in); | |||
} | |||
} | |||
} | |||
@Override | |||
public short getSid() { | |||
return sid; | |||
@@ -228,4 +240,9 @@ public final class ExternalNameRecord extends StandardRecord { | |||
sb.append("[/EXTERNALNAME]\n"); | |||
return sb.toString(); | |||
} | |||
@Override | |||
public ExternalNameRecord copy() { | |||
return new ExternalNameRecord(this); | |||
} | |||
} |
@@ -19,29 +19,30 @@ package org.apache.poi.hssf.record; | |||
import org.apache.poi.hssf.record.common.FtrHeader; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* Title: FeatHdr (Feature Header) Record | |||
* <P> | |||
* This record specifies common information for Shared Features, and | |||
* specifies the beginning of a collection of records to define them. | |||
* The collection of data (Globals Substream ABNF, macro sheet substream | |||
* This record specifies common information for Shared Features, and | |||
* specifies the beginning of a collection of records to define them. | |||
* The collection of data (Globals Substream ABNF, macro sheet substream | |||
* ABNF or worksheet substream ABNF) specifies Shared Feature data. | |||
*/ | |||
public final class FeatHdrRecord extends StandardRecord implements Cloneable { | |||
public final class FeatHdrRecord extends StandardRecord { | |||
/** | |||
* Specifies the enhanced protection type. Used to protect a | |||
* shared workbook by restricting access to some areas of it | |||
* Specifies the enhanced protection type. Used to protect a | |||
* shared workbook by restricting access to some areas of it | |||
*/ | |||
public static final int SHAREDFEATURES_ISFPROTECTION = 0x02; | |||
/** | |||
* Specifies that formula errors should be ignored | |||
* Specifies that formula errors should be ignored | |||
*/ | |||
public static final int SHAREDFEATURES_ISFFEC2 = 0x03; | |||
/** | |||
* Specifies the smart tag type. Recognises certain | |||
* types of entries (proper names, dates/times etc) and | |||
* flags them for action | |||
* flags them for action | |||
*/ | |||
public static final int SHAREDFEATURES_ISFFACTOID = 0x04; | |||
/** | |||
@@ -50,13 +51,13 @@ public final class FeatHdrRecord extends StandardRecord implements Cloneable { | |||
*/ | |||
public static final int SHAREDFEATURES_ISFLIST = 0x05; | |||
public final static short sid = 0x0867; | |||
private FtrHeader futureHeader; | |||
public static final short sid = 0x0867; | |||
private final FtrHeader futureHeader; | |||
private int isf_sharedFeatureType; // See SHAREDFEATURES_ | |||
private byte reserved; // Should always be one | |||
/** | |||
/** | |||
* 0x00000000 = rgbHdrData not present | |||
* 0xffffffff = rgbHdrData present | |||
*/ | |||
@@ -69,13 +70,18 @@ public final class FeatHdrRecord extends StandardRecord implements Cloneable { | |||
futureHeader.setRecordType(sid); | |||
} | |||
public short getSid() { | |||
return sid; | |||
public FeatHdrRecord(FeatHdrRecord other) { | |||
super(other); | |||
futureHeader = other.futureHeader.copy(); | |||
isf_sharedFeatureType = other.isf_sharedFeatureType; | |||
reserved = other.reserved; | |||
cbHdrData = other.cbHdrData; | |||
rgbHdrData = (other.rgbHdrData == null) ? null : other.rgbHdrData.clone(); | |||
} | |||
public FeatHdrRecord(RecordInputStream in) { | |||
futureHeader = new FtrHeader(in); | |||
isf_sharedFeatureType = in.readShort(); | |||
reserved = in.readByte(); | |||
cbHdrData = in.readInt(); | |||
@@ -83,19 +89,23 @@ public final class FeatHdrRecord extends StandardRecord implements Cloneable { | |||
rgbHdrData = in.readRemainder(); | |||
} | |||
public short getSid() { | |||
return sid; | |||
} | |||
public String toString() { | |||
StringBuilder buffer = new StringBuilder(); | |||
buffer.append("[FEATURE HEADER]\n"); | |||
// TODO ... | |||
buffer.append("[/FEATURE HEADER]\n"); | |||
return buffer.toString(); | |||
} | |||
public void serialize(LittleEndianOutput out) { | |||
futureHeader.serialize(out); | |||
out.writeShort(isf_sharedFeatureType); | |||
out.writeByte(reserved); | |||
out.writeInt((int)cbHdrData); | |||
@@ -105,12 +115,20 @@ public final class FeatHdrRecord extends StandardRecord implements Cloneable { | |||
protected int getDataSize() { | |||
return 12 + 2+1+4+rgbHdrData.length; | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public FeatHdrRecord clone() { | |||
return copy(); | |||
} | |||
@Override | |||
public FeatHdrRecord clone() { | |||
public FeatHdrRecord copy() { | |||
//HACK: do a "cheat" clone, see Record.java for more information | |||
return (FeatHdrRecord)cloneViaReserialise(); | |||
return new FeatHdrRecord(this); | |||
} | |||
} |
@@ -17,6 +17,8 @@ | |||
package org.apache.poi.hssf.record; | |||
import java.util.stream.Stream; | |||
import org.apache.poi.hssf.record.common.FeatFormulaErr2; | |||
import org.apache.poi.hssf.record.common.FeatProtection; | |||
import org.apache.poi.hssf.record.common.FeatSmartTag; | |||
@@ -26,6 +28,7 @@ import org.apache.poi.ss.util.CellRangeAddress; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.POILogFactory; | |||
import org.apache.poi.util.POILogger; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* Title: Feat (Feature) Record | |||
@@ -33,19 +36,17 @@ import org.apache.poi.util.POILogger; | |||
* This record specifies Shared Features data. It is normally paired | |||
* up with a {@link FeatHdrRecord}. | |||
*/ | |||
public final class FeatRecord extends StandardRecord implements Cloneable { | |||
private static POILogger logger = POILogFactory.getLogger(FeatRecord.class); | |||
public final static short sid = 0x0868; | |||
public final class FeatRecord extends StandardRecord { | |||
private static final POILogger logger = POILogFactory.getLogger(FeatRecord.class); | |||
public static final short sid = 0x0868; | |||
// SIDs from newer versions | |||
public final static short v11_sid = 0x0872; | |||
public final static short v12_sid = 0x0878; | |||
private FtrHeader futureHeader; | |||
/** | |||
* See SHAREDFEATURES_* on {@link FeatHdrRecord} | |||
*/ | |||
private int isf_sharedFeatureType; | |||
public static final short v11_sid = 0x0872; | |||
public static final short v12_sid = 0x0878; | |||
private final FtrHeader futureHeader; | |||
/** See SHAREDFEATURES_* on {@link FeatHdrRecord} */ | |||
private int isf_sharedFeatureType; | |||
private byte reserved1; // Should always be zero | |||
private long reserved2; // Should always be zero | |||
/** Only matters if type is ISFFEC2 */ | |||
@@ -55,24 +56,33 @@ public final class FeatRecord extends StandardRecord implements Cloneable { | |||
/** | |||
* Contents depends on isf_sharedFeatureType : | |||
* ISFPROTECTION -> FeatProtection | |||
* ISFPROTECTION -> FeatProtection | |||
* ISFFEC2 -> FeatFormulaErr2 | |||
* ISFFACTOID -> FeatSmartTag | |||
*/ | |||
private SharedFeature sharedFeature; | |||
private SharedFeature sharedFeature; | |||
public FeatRecord() { | |||
futureHeader = new FtrHeader(); | |||
futureHeader.setRecordType(sid); | |||
} | |||
public short getSid() { | |||
return sid; | |||
public FeatRecord(FeatRecord other) { | |||
super(other); | |||
futureHeader = other.futureHeader.copy(); | |||
isf_sharedFeatureType = other.isf_sharedFeatureType; | |||
reserved1 = other.reserved1; | |||
reserved2 = other.reserved2; | |||
cbFeatData = other.cbFeatData; | |||
reserved3 = other.reserved3; | |||
cellRefs = (other.cellRefs == null) ? null : | |||
Stream.of(other.cellRefs).map(CellRangeAddress::copy).toArray(CellRangeAddress[]::new); | |||
sharedFeature = (other.sharedFeature == null) ? null : other.sharedFeature.copy(); | |||
} | |||
public FeatRecord(RecordInputStream in) { | |||
futureHeader = new FtrHeader(in); | |||
isf_sharedFeatureType = in.readShort(); | |||
reserved1 = in.readByte(); | |||
reserved2 = in.readInt(); | |||
@@ -84,7 +94,7 @@ public final class FeatRecord extends StandardRecord implements Cloneable { | |||
for(int i=0; i<cellRefs.length; i++) { | |||
cellRefs[i] = new CellRangeAddress(in); | |||
} | |||
switch(isf_sharedFeatureType) { | |||
case FeatHdrRecord.SHAREDFEATURES_ISFPROTECTION: | |||
sharedFeature = new FeatProtection(in); | |||
@@ -100,30 +110,34 @@ public final class FeatRecord extends StandardRecord implements Cloneable { | |||
} | |||
} | |||
public short getSid() { | |||
return sid; | |||
} | |||
public String toString() { | |||
StringBuilder buffer = new StringBuilder(); | |||
buffer.append("[SHARED FEATURE]\n"); | |||
// TODO ... | |||
buffer.append("[/SHARED FEATURE]\n"); | |||
return buffer.toString(); | |||
} | |||
public void serialize(LittleEndianOutput out) { | |||
futureHeader.serialize(out); | |||
out.writeShort(isf_sharedFeatureType); | |||
out.writeByte(reserved1); | |||
out.writeInt((int)reserved2); | |||
out.writeShort(cellRefs.length); | |||
out.writeInt((int)cbFeatData); | |||
out.writeShort(reserved3); | |||
for(int i=0; i<cellRefs.length; i++) { | |||
cellRefs[i].serialize(out); | |||
} | |||
sharedFeature.serialize(out); | |||
} | |||
@@ -156,7 +170,7 @@ public final class FeatRecord extends StandardRecord implements Cloneable { | |||
} | |||
public void setSharedFeature(SharedFeature feature) { | |||
this.sharedFeature = feature; | |||
if(feature instanceof FeatProtection) { | |||
isf_sharedFeatureType = FeatHdrRecord.SHAREDFEATURES_ISFPROTECTION; | |||
} | |||
@@ -166,7 +180,7 @@ public final class FeatRecord extends StandardRecord implements Cloneable { | |||
if(feature instanceof FeatSmartTag) { | |||
isf_sharedFeatureType = FeatHdrRecord.SHAREDFEATURES_ISFFACTOID; | |||
} | |||
if(isf_sharedFeatureType == FeatHdrRecord.SHAREDFEATURES_ISFFEC2) { | |||
cbFeatData = sharedFeature.getDataSize(); | |||
} else { | |||
@@ -174,12 +188,16 @@ public final class FeatRecord extends StandardRecord implements Cloneable { | |||
} | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public FeatRecord clone() { | |||
//HACK: do a "cheat" clone, see Record.java for more information | |||
return (FeatRecord)cloneViaReserialise(); | |||
} | |||
return copy(); | |||
} | |||
@Override | |||
public FeatRecord copy() { | |||
return new FeatRecord(this); | |||
} | |||
} |
@@ -33,13 +33,14 @@ import org.apache.poi.util.HexDump; | |||
import org.apache.poi.util.LittleEndianByteArrayOutputStream; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.LittleEndianOutputStream; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* Title: File Pass Record (0x002F) <p> | |||
* File Pass Record (0x002F) <p> | |||
* | |||
* Description: Indicates that the record after this record are encrypted. | |||
* Indicates that the record after this record are encrypted. | |||
*/ | |||
public final class FilePassRecord extends StandardRecord implements Cloneable { | |||
public final class FilePassRecord extends StandardRecord { | |||
public static final short sid = 0x002F; | |||
private static final int ENCRYPTION_XOR = 0; | |||
private static final int ENCRYPTION_OTHER = 1; | |||
@@ -48,12 +49,9 @@ public final class FilePassRecord extends StandardRecord implements Cloneable { | |||
private EncryptionInfo encryptionInfo; | |||
private FilePassRecord(FilePassRecord other) { | |||
super(other); | |||
encryptionType = other.encryptionType; | |||
try { | |||
encryptionInfo = other.encryptionInfo.clone(); | |||
} catch (CloneNotSupportedException e) { | |||
throw new EncryptedDocumentException(e); | |||
} | |||
encryptionInfo = other.encryptionInfo.copy(); | |||
} | |||
public FilePassRecord(EncryptionMode encryptionMode) { | |||
@@ -138,8 +136,16 @@ public final class FilePassRecord extends StandardRecord implements Cloneable { | |||
return sid; | |||
} | |||
@Override | |||
public FilePassRecord clone() { | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public FilePassRecord clone() { | |||
return copy(); | |||
} | |||
@Override | |||
public FilePassRecord copy() { | |||
return new FilePassRecord(this); | |||
} | |||
@@ -18,17 +18,16 @@ | |||
package org.apache.poi.hssf.record; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.Removal; | |||
import org.apache.poi.util.StringUtil; | |||
/** | |||
* Title: FILESHARING (0x005B) <p> | |||
* Description: stores the encrypted readonly for a workbook (write protect) | |||
* This functionality is accessed from the options dialog box available when performing 'Save As'.<p> | |||
* REFERENCE: PG 314 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) | |||
* Stores the encrypted readonly for a workbook (write protect).<p> | |||
* This functionality is accessed from the options dialog box available when performing 'Save As'. | |||
*/ | |||
public final class FileSharingRecord extends StandardRecord implements Cloneable { | |||
public final class FileSharingRecord extends StandardRecord { | |||
public final static short sid = 0x005B; | |||
public static final short sid = 0x005B; | |||
private short field_1_readonly; | |||
private short field_2_password; | |||
private byte field_3_username_unicode_options; | |||
@@ -36,14 +35,22 @@ public final class FileSharingRecord extends StandardRecord implements Cloneable | |||
public FileSharingRecord() {} | |||
public FileSharingRecord(FileSharingRecord other) { | |||
super(other); | |||
field_1_readonly = other.field_1_readonly; | |||
field_2_password = other.field_2_password; | |||
field_3_username_unicode_options = other.field_3_username_unicode_options; | |||
field_3_username_value = other.field_3_username_value; | |||
} | |||
public FileSharingRecord(RecordInputStream in) { | |||
field_1_readonly = in.readShort(); | |||
field_2_password = in.readShort(); | |||
int nameLen = in.readShort(); | |||
if(nameLen > 0) { | |||
// TODO - Current examples(3) from junits only have zero length username. | |||
// TODO - Current examples(3) from junits only have zero length username. | |||
field_3_username_unicode_options = in.readByte(); | |||
field_3_username_value = in.readCompressedUnicode(nameLen); | |||
} else { | |||
@@ -137,11 +144,15 @@ public final class FileSharingRecord extends StandardRecord implements Cloneable | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public FileSharingRecord clone() { | |||
FileSharingRecord clone = new FileSharingRecord(); | |||
clone.setReadOnly(field_1_readonly); | |||
clone.setPassword(field_2_password); | |||
clone.setUsername(field_3_username_value); | |||
return clone; | |||
return copy(); | |||
} | |||
@Override | |||
public FileSharingRecord copy() { | |||
return new FileSharingRecord(this); | |||
} | |||
} |
@@ -15,35 +15,32 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.hssf.record; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
/** | |||
* Title: Function Group Count Record<P> | |||
* Description: Number of built in function groups in the current version of the | |||
* Spreadsheet (probably only used on Windoze)<P> | |||
* REFERENCE: PG 315 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> | |||
* @author Andrew C. Oliver (acoliver at apache dot org) | |||
* umber of built in function groups in the current version of the Spreadsheet (probably only used on Windows) | |||
* | |||
* @version 2.0-pre | |||
*/ | |||
public final class FnGroupCountRecord | |||
extends StandardRecord | |||
{ | |||
public final static short sid = 0x9c; | |||
public final class FnGroupCountRecord extends StandardRecord { | |||
public static final short sid = 0x9c; | |||
/** | |||
* suggested default (14 dec) | |||
*/ | |||
public final static short COUNT = 14; | |||
public static final short COUNT = 14; | |||
private short field_1_count; | |||
public FnGroupCountRecord() | |||
{ | |||
public FnGroupCountRecord() {} | |||
public FnGroupCountRecord(FnGroupCountRecord other) { | |||
super(other); | |||
field_1_count = other.field_1_count; | |||
} | |||
public FnGroupCountRecord(RecordInputStream in) | |||
@@ -96,4 +93,9 @@ public final class FnGroupCountRecord | |||
{ | |||
return sid; | |||
} | |||
@Override | |||
public FnGroupCountRecord copy() { | |||
return new FnGroupCountRecord(this); | |||
} | |||
} |
@@ -25,50 +25,68 @@ import org.apache.poi.util.HexDump; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.StringUtil; | |||
/** | |||
* Title: Font Record (0x0031) <p> | |||
* - describes a font in the workbook (index = 0-3,5-infinity - skip 4)<P> | |||
* Description: An element in the Font Table<p> | |||
* REFERENCE: PG 315 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) | |||
*/ | |||
/** Describes a font in the workbook */ | |||
public final class FontRecord extends StandardRecord { | |||
// docs are wrong (0x231 Microsoft Support site article Q184647) | |||
public final static short sid = 0x0031; | |||
public final static short SS_NONE = 0; | |||
public final static short SS_SUPER = 1; | |||
public final static short SS_SUB = 2; | |||
public final static byte U_NONE = 0; | |||
public final static byte U_SINGLE = 1; | |||
public final static byte U_DOUBLE = 2; | |||
public final static byte U_SINGLE_ACCOUNTING = 0x21; | |||
public final static byte U_DOUBLE_ACCOUNTING = 0x22; | |||
// in units of .05 of a point | |||
private short field_1_font_height; | |||
private short field_2_attributes; | |||
public static final short sid = 0x0031; | |||
public static final short SS_NONE = 0; | |||
public static final short SS_SUPER = 1; | |||
public static final short SS_SUB = 2; | |||
public static final byte U_NONE = 0; | |||
public static final byte U_SINGLE = 1; | |||
public static final byte U_DOUBLE = 2; | |||
public static final byte U_SINGLE_ACCOUNTING = 0x21; | |||
public static final byte U_DOUBLE_ACCOUNTING = 0x22; | |||
// 0 0x01 - Reserved bit must be 0 | |||
private static final BitField italic = BitFieldFactory.getInstance(0x02); // is this font in italics | |||
// is this font in italics | |||
private static final BitField italic = BitFieldFactory.getInstance(0x02); | |||
// 2 0x04 - reserved bit must be 0 | |||
private static final BitField strikeout =BitFieldFactory.getInstance(0x08); // is this font has a line through the center | |||
private static final BitField macoutline = BitFieldFactory.getInstance(0x10); // some weird macintosh thing....but who understands those mac people anyhow | |||
private static final BitField macshadow = BitFieldFactory.getInstance(0x20); // some weird macintosh thing....but who understands those mac people anyhow | |||
// is this font has a line through the center | |||
private static final BitField strikeout = BitFieldFactory.getInstance(0x08); | |||
// some weird macintosh thing....but who understands those mac people anyhow | |||
private static final BitField macoutline = BitFieldFactory.getInstance(0x10); | |||
private static final BitField macshadow = BitFieldFactory.getInstance(0x20); | |||
// in units of .05 of a point | |||
private short field_1_font_height; | |||
private short field_2_attributes; | |||
// 7-6 - reserved bits must be 0 | |||
// the rest is unused | |||
private short field_3_color_palette_index; | |||
private short field_4_bold_weight; | |||
private short field_5_super_sub_script; // 00none/01super/02sub | |||
private byte field_6_underline; // 00none/01single/02double/21singleaccounting/22doubleaccounting | |||
private byte field_7_family; // ?? defined by windows api logfont structure? | |||
private byte field_8_charset; // ?? defined by windows api logfont structure? | |||
private byte field_9_zero; // must be 0 | |||
private short field_3_color_palette_index; | |||
private short field_4_bold_weight; | |||
// 00none/01super/02sub | |||
private short field_5_super_sub_script; | |||
// 00none/01single/02double/21singleaccounting/22doubleaccounting | |||
private byte field_6_underline; | |||
// ?? defined by windows api logfont structure? | |||
private byte field_7_family; | |||
// ?? defined by windows api logfont structure? | |||
private byte field_8_charset; | |||
// must be 0 | |||
private byte field_9_zero; | |||
/** possibly empty string never <code>null</code> */ | |||
private String field_11_font_name; | |||
private String field_11_font_name; | |||
public FontRecord() { | |||
} | |||
public FontRecord(FontRecord other) { | |||
super(other); | |||
field_1_font_height = other.field_1_font_height; | |||
field_2_attributes = other.field_2_attributes; | |||
field_3_color_palette_index = other.field_3_color_palette_index; | |||
field_4_bold_weight = other.field_4_bold_weight; | |||
field_5_super_sub_script = other.field_5_super_sub_script; | |||
field_6_underline = other.field_6_underline; | |||
field_7_family = other.field_7_family; | |||
field_8_charset = other.field_8_charset; | |||
field_9_zero = other.field_9_zero; | |||
field_11_font_name = other.field_11_font_name; | |||
} | |||
public FontRecord(RecordInputStream in) { | |||
field_1_font_height = in.readShort(); | |||
field_2_attributes = in.readShort(); | |||
@@ -490,4 +508,9 @@ public final class FontRecord extends StandardRecord { | |||
public boolean equals(Object o) { | |||
return (o instanceof FontRecord) && sameProperties((FontRecord) o); | |||
} | |||
@Override | |||
public FontRecord copy() { | |||
return new FontRecord(this); | |||
} | |||
} |
@@ -17,18 +17,22 @@ | |||
package org.apache.poi.hssf.record; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* Title: Footer Record (0x0015)<p> | |||
* Description: Specifies the footer for a sheet<p> | |||
* REFERENCE: PG 317 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) | |||
* Specifies the footer for a sheet | |||
*/ | |||
public final class FooterRecord extends HeaderFooterBase implements Cloneable { | |||
public final static short sid = 0x0015; | |||
public final class FooterRecord extends HeaderFooterBase { | |||
public static final short sid = 0x0015; | |||
public FooterRecord(String text) { | |||
super(text); | |||
} | |||
public FooterRecord(FooterRecord other) { | |||
super(other); | |||
} | |||
public FooterRecord(RecordInputStream in) { | |||
super(in); | |||
} | |||
@@ -47,7 +51,15 @@ public final class FooterRecord extends HeaderFooterBase implements Cloneable { | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public FooterRecord clone() { | |||
return new FooterRecord(getText()); | |||
return copy(); | |||
} | |||
@Override | |||
public FooterRecord copy() { | |||
return new FooterRecord(this); | |||
} | |||
} |
@@ -22,30 +22,29 @@ import org.apache.poi.util.LittleEndianConsts; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.POILogFactory; | |||
import org.apache.poi.util.POILogger; | |||
import org.apache.poi.util.Removal; | |||
import org.apache.poi.util.StringUtil; | |||
/** | |||
* Title: Format Record (0x041E)<p> | |||
* Description: describes a number format -- those goofy strings like $(#,###)<p> | |||
* | |||
* REFERENCE: PG 317 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) | |||
* Describes a number format -- those goofy strings like $(#,###) | |||
*/ | |||
public final class FormatRecord extends StandardRecord implements Cloneable { | |||
public final class FormatRecord extends StandardRecord { | |||
private static final POILogger logger = POILogFactory.getLogger(FormatRecord.class); | |||
public final static short sid = 0x041E; | |||
public static final short sid = 0x041E; | |||
private final int field_1_index_code; | |||
private final boolean field_3_hasMultibyte; | |||
private final String field_4_formatstring; | |||
private FormatRecord(FormatRecord other) { | |||
super(other); | |||
field_1_index_code = other.field_1_index_code; | |||
field_3_hasMultibyte = other.field_3_hasMultibyte; | |||
field_4_formatstring = other.field_4_formatstring; | |||
} | |||
public FormatRecord(int indexCode, String fs) { | |||
field_1_index_code = indexCode; | |||
field_4_formatstring = fs; | |||
@@ -114,9 +113,17 @@ public final class FormatRecord extends StandardRecord implements Cloneable { | |||
public short getSid() { | |||
return sid; | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public FormatRecord clone() { | |||
return copy(); | |||
} | |||
@Override | |||
public FormatRecord copy() { | |||
return new FormatRecord(this); | |||
} | |||
@@ -18,168 +18,28 @@ | |||
package org.apache.poi.hssf.record; | |||
import org.apache.poi.ss.formula.Formula; | |||
import org.apache.poi.ss.formula.eval.ErrorEval; | |||
import org.apache.poi.ss.formula.ptg.Ptg; | |||
import org.apache.poi.ss.usermodel.CellType; | |||
import org.apache.poi.util.*; | |||
import org.apache.poi.util.BitField; | |||
import org.apache.poi.util.BitFieldFactory; | |||
import org.apache.poi.util.HexDump; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* Formula Record (0x0006). | |||
* REFERENCE: PG 317/444 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> | |||
* @author Andrew C. Oliver (acoliver at apache dot org) | |||
* @author Jason Height (jheight at chariot dot net dot au) | |||
*/ | |||
public final class FormulaRecord extends CellRecord implements Cloneable { | |||
public final class FormulaRecord extends CellRecord { | |||
public static final short sid = 0x0006; // docs say 406...because of a bug Microsoft support site article #Q184647) | |||
private static int FIXED_SIZE = 14; // double + short + int | |||
// docs say 406...because of a bug Microsoft support site article #Q184647) | |||
public static final short sid = 0x0006; | |||
// double + short + int | |||
private static final int FIXED_SIZE = 14; | |||
private static final BitField alwaysCalc = BitFieldFactory.getInstance(0x0001); | |||
private static final BitField calcOnLoad = BitFieldFactory.getInstance(0x0002); | |||
private static final BitField sharedFormula = BitFieldFactory.getInstance(0x0008); | |||
/** | |||
* Manages the cached formula result values of other types besides numeric. | |||
* Excel encodes the same 8 bytes that would be field_4_value with various NaN | |||
* values that are decoded/encoded by this class. | |||
*/ | |||
static final class SpecialCachedValue { | |||
/** deliberately chosen by Excel in order to encode other values within Double NaNs */ | |||
private static final long BIT_MARKER = 0xFFFF000000000000L; | |||
private static final int VARIABLE_DATA_LENGTH = 6; | |||
private static final int DATA_INDEX = 2; | |||
// FIXME: can these be merged with {@link CellType}? | |||
// are the numbers specific to the HSSF formula record format or just a poor-man's enum? | |||
public static final int STRING = 0; | |||
public static final int BOOLEAN = 1; | |||
public static final int ERROR_CODE = 2; | |||
public static final int EMPTY = 3; | |||
private final byte[] _variableData; | |||
private SpecialCachedValue(byte[] data) { | |||
_variableData = data; | |||
} | |||
public int getTypeCode() { | |||
return _variableData[0]; | |||
} | |||
/** | |||
* @return <code>null</code> if the double value encoded by <tt>valueLongBits</tt> | |||
* is a normal (non NaN) double value. | |||
*/ | |||
public static SpecialCachedValue create(long valueLongBits) { | |||
if ((BIT_MARKER & valueLongBits) != BIT_MARKER) { | |||
return null; | |||
} | |||
byte[] result = new byte[VARIABLE_DATA_LENGTH]; | |||
long x = valueLongBits; | |||
for (int i=0; i<VARIABLE_DATA_LENGTH; i++) { | |||
result[i] = (byte) x; | |||
x >>= 8; | |||
} | |||
switch (result[0]) { | |||
case STRING: | |||
case BOOLEAN: | |||
case ERROR_CODE: | |||
case EMPTY: | |||
break; | |||
default: | |||
throw new org.apache.poi.util.RecordFormatException("Bad special value code (" + result[0] + ")"); | |||
} | |||
return new SpecialCachedValue(result); | |||
} | |||
public void serialize(LittleEndianOutput out) { | |||
out.write(_variableData); | |||
out.writeShort(0xFFFF); | |||
} | |||
public String formatDebugString() { | |||
return formatValue() + ' ' + HexDump.toHex(_variableData); | |||
} | |||
private String formatValue() { | |||
int typeCode = getTypeCode(); | |||
switch (typeCode) { | |||
case STRING: | |||
return "<string>"; | |||
case BOOLEAN: | |||
return getDataValue() == 0 ? "FALSE" : "TRUE"; | |||
case ERROR_CODE: | |||
return ErrorEval.getText(getDataValue()); | |||
case EMPTY: | |||
return "<empty>"; | |||
} | |||
return "#error(type=" + typeCode + ")#"; | |||
} | |||
private int getDataValue() { | |||
return _variableData[DATA_INDEX]; | |||
} | |||
public static SpecialCachedValue createCachedEmptyValue() { | |||
return create(EMPTY, 0); | |||
} | |||
public static SpecialCachedValue createForString() { | |||
return create(STRING, 0); | |||
} | |||
public static SpecialCachedValue createCachedBoolean(boolean b) { | |||
return create(BOOLEAN, b ? 1 : 0); | |||
} | |||
public static SpecialCachedValue createCachedErrorCode(int errorCode) { | |||
return create(ERROR_CODE, errorCode); | |||
} | |||
private static SpecialCachedValue create(int code, int data) { | |||
byte[] vd = { | |||
(byte) code, | |||
0, | |||
(byte) data, | |||
0, | |||
0, | |||
0, | |||
}; | |||
return new SpecialCachedValue(vd); | |||
} | |||
@Override | |||
public String toString() { | |||
return getClass().getName() + '[' + formatValue() + ']'; | |||
} | |||
public int getValueType() { | |||
int typeCode = getTypeCode(); | |||
switch (typeCode) { | |||
case STRING: return CellType.STRING.getCode(); | |||
case BOOLEAN: return CellType.BOOLEAN.getCode(); | |||
case ERROR_CODE: return CellType.ERROR.getCode(); | |||
case EMPTY: return CellType.STRING.getCode(); // is this correct? | |||
} | |||
throw new IllegalStateException("Unexpected type id (" + typeCode + ")"); | |||
} | |||
public boolean getBooleanValue() { | |||
if (getTypeCode() != BOOLEAN) { | |||
throw new IllegalStateException("Not a boolean cached value - " + formatValue()); | |||
} | |||
return getDataValue() != 0; | |||
} | |||
public int getErrorValue() { | |||
if (getTypeCode() != ERROR_CODE) { | |||
throw new IllegalStateException("Not an error cached value - " + formatValue()); | |||
} | |||
return getDataValue(); | |||
} | |||
} | |||
private double field_4_value; | |||
private short field_5_options; | |||
/** | |||
@@ -193,19 +53,27 @@ public final class FormulaRecord extends CellRecord implements Cloneable { | |||
/** | |||
* Since the NaN support seems sketchy (different constants) we'll store and spit it out directly | |||
*/ | |||
private SpecialCachedValue specialCachedValue; | |||
private FormulaSpecialCachedValue specialCachedValue; | |||
/** Creates new FormulaRecord */ | |||
public FormulaRecord() { | |||
field_8_parsed_expr = Formula.create(Ptg.EMPTY_PTG_ARRAY); | |||
} | |||
public FormulaRecord(FormulaRecord other) { | |||
super(other); | |||
field_4_value = other.field_4_value; | |||
field_5_options = other.field_5_options; | |||
field_6_zero = other.field_6_zero; | |||
field_8_parsed_expr = (other.field_8_parsed_expr == null) ? null : new Formula(other.field_8_parsed_expr); | |||
specialCachedValue = (other.specialCachedValue == null) ? null : new FormulaSpecialCachedValue(other.specialCachedValue); | |||
} | |||
public FormulaRecord(RecordInputStream ris) { | |||
super(ris); | |||
long valueLongBits = ris.readLong(); | |||
field_5_options = ris.readShort(); | |||
specialCachedValue = SpecialCachedValue.create(valueLongBits); | |||
specialCachedValue = FormulaSpecialCachedValue.create(valueLongBits); | |||
if (specialCachedValue == null) { | |||
field_4_value = Double.longBitsToDouble(valueLongBits); | |||
} | |||
@@ -228,16 +96,16 @@ public final class FormulaRecord extends CellRecord implements Cloneable { | |||
} | |||
public void setCachedResultTypeEmptyString() { | |||
specialCachedValue = SpecialCachedValue.createCachedEmptyValue(); | |||
specialCachedValue = FormulaSpecialCachedValue.createCachedEmptyValue(); | |||
} | |||
public void setCachedResultTypeString() { | |||
specialCachedValue = SpecialCachedValue.createForString(); | |||
specialCachedValue = FormulaSpecialCachedValue.createForString(); | |||
} | |||
public void setCachedResultErrorCode(int errorCode) { | |||
specialCachedValue = SpecialCachedValue.createCachedErrorCode(errorCode); | |||
specialCachedValue = FormulaSpecialCachedValue.createCachedErrorCode(errorCode); | |||
} | |||
public void setCachedResultBoolean(boolean value) { | |||
specialCachedValue = SpecialCachedValue.createCachedBoolean(value); | |||
specialCachedValue = FormulaSpecialCachedValue.createCachedBoolean(value); | |||
} | |||
/** | |||
* @return <code>true</code> if this {@link FormulaRecord} is followed by a | |||
@@ -246,7 +114,7 @@ public final class FormulaRecord extends CellRecord implements Cloneable { | |||
*/ | |||
public boolean hasCachedResultString() { | |||
return specialCachedValue != null && | |||
specialCachedValue.getTypeCode() == SpecialCachedValue.STRING; | |||
specialCachedValue.getTypeCode() == FormulaSpecialCachedValue.STRING; | |||
} | |||
public int getCachedResultType() { | |||
@@ -353,12 +221,12 @@ public final class FormulaRecord extends CellRecord implements Cloneable { | |||
out.writeInt(field_6_zero); // may as well write original data back so as to minimise differences from original | |||
field_8_parsed_expr.serialize(out); | |||
} | |||
@Override | |||
protected String getRecordName() { | |||
return "FORMULA"; | |||
} | |||
@Override | |||
protected void appendValueText(StringBuilder sb) { | |||
sb.append(" .value = "); | |||
@@ -385,15 +253,16 @@ public final class FormulaRecord extends CellRecord implements Cloneable { | |||
} | |||
@Override | |||
public FormulaRecord clone() { | |||
FormulaRecord rec = new FormulaRecord(); | |||
copyBaseFields(rec); | |||
rec.field_4_value = field_4_value; | |||
rec.field_5_options = field_5_options; | |||
rec.field_6_zero = field_6_zero; | |||
rec.field_8_parsed_expr = field_8_parsed_expr; | |||
rec.specialCachedValue = specialCachedValue; | |||
return rec; | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public FormulaRecord clone() { | |||
return copy(); | |||
} | |||
@Override | |||
public FormulaRecord copy() { | |||
return new FormulaRecord(this); | |||
} | |||
} | |||
@@ -0,0 +1,167 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
this work for additional information regarding copyright ownership. | |||
The ASF licenses this file to You under the Apache License, Version 2.0 | |||
(the "License"); you may not use this file except in compliance with | |||
the License. You may obtain a copy of the License at | |||
http://www.apache.org/licenses/LICENSE-2.0 | |||
Unless required by applicable law or agreed to in writing, software | |||
distributed under the License is distributed on an "AS IS" BASIS, | |||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.hssf.record; | |||
import org.apache.poi.ss.formula.eval.ErrorEval; | |||
import org.apache.poi.ss.usermodel.CellType; | |||
import org.apache.poi.util.HexDump; | |||
import org.apache.poi.util.Internal; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
/** | |||
* Manages the cached formula result values of other types besides numeric. | |||
* Excel encodes the same 8 bytes that would be field_4_value with various NaN | |||
* values that are decoded/encoded by this class. | |||
*/ | |||
@Internal | |||
public final class FormulaSpecialCachedValue { | |||
/** deliberately chosen by Excel in order to encode other values within Double NaNs */ | |||
private static final long BIT_MARKER = 0xFFFF000000000000L; | |||
private static final int VARIABLE_DATA_LENGTH = 6; | |||
private static final int DATA_INDEX = 2; | |||
// FIXME: can these be merged with {@link CellType}? | |||
// are the numbers specific to the HSSF formula record format or just a poor-man's enum? | |||
public static final int STRING = 0; | |||
public static final int BOOLEAN = 1; | |||
public static final int ERROR_CODE = 2; | |||
public static final int EMPTY = 3; | |||
private final byte[] _variableData; | |||
FormulaSpecialCachedValue(FormulaSpecialCachedValue other) { | |||
_variableData = (other._variableData == null) ? null : other._variableData.clone(); | |||
} | |||
private FormulaSpecialCachedValue(byte[] data) { | |||
_variableData = data; | |||
} | |||
public int getTypeCode() { | |||
return _variableData[0]; | |||
} | |||
/** | |||
* @return <code>null</code> if the double value encoded by <tt>valueLongBits</tt> | |||
* is a normal (non NaN) double value. | |||
*/ | |||
public static FormulaSpecialCachedValue create(long valueLongBits) { | |||
if ((BIT_MARKER & valueLongBits) != BIT_MARKER) { | |||
return null; | |||
} | |||
byte[] result = new byte[VARIABLE_DATA_LENGTH]; | |||
long x = valueLongBits; | |||
for (int i=0; i<VARIABLE_DATA_LENGTH; i++) { | |||
result[i] = (byte) x; | |||
x >>= 8; | |||
} | |||
switch (result[0]) { | |||
case STRING: | |||
case BOOLEAN: | |||
case ERROR_CODE: | |||
case EMPTY: | |||
break; | |||
default: | |||
throw new org.apache.poi.util.RecordFormatException("Bad special value code (" + result[0] + ")"); | |||
} | |||
return new FormulaSpecialCachedValue(result); | |||
} | |||
public void serialize(LittleEndianOutput out) { | |||
out.write(_variableData); | |||
out.writeShort(0xFFFF); | |||
} | |||
public String formatDebugString() { | |||
return formatValue() + ' ' + HexDump.toHex(_variableData); | |||
} | |||
private String formatValue() { | |||
int typeCode = getTypeCode(); | |||
switch (typeCode) { | |||
case STRING: | |||
return "<string>"; | |||
case BOOLEAN: | |||
return getDataValue() == 0 ? "FALSE" : "TRUE"; | |||
case ERROR_CODE: | |||
return ErrorEval.getText(getDataValue()); | |||
case EMPTY: | |||
return "<empty>"; | |||
} | |||
return "#error(type=" + typeCode + ")#"; | |||
} | |||
private int getDataValue() { | |||
return _variableData[DATA_INDEX]; | |||
} | |||
public static FormulaSpecialCachedValue createCachedEmptyValue() { | |||
return create(EMPTY, 0); | |||
} | |||
public static FormulaSpecialCachedValue createForString() { | |||
return create(STRING, 0); | |||
} | |||
public static FormulaSpecialCachedValue createCachedBoolean(boolean b) { | |||
return create(BOOLEAN, b ? 1 : 0); | |||
} | |||
public static FormulaSpecialCachedValue createCachedErrorCode(int errorCode) { | |||
return create(ERROR_CODE, errorCode); | |||
} | |||
private static FormulaSpecialCachedValue create(int code, int data) { | |||
byte[] vd = { (byte) code, 0, (byte) data, 0, 0, 0, }; | |||
return new FormulaSpecialCachedValue(vd); | |||
} | |||
@Override | |||
public String toString() { | |||
return getClass().getName() + '[' + formatValue() + ']'; | |||
} | |||
public int getValueType() { | |||
int typeCode = getTypeCode(); | |||
switch (typeCode) { | |||
case EMPTY: // is this correct? | |||
case STRING: | |||
return CellType.STRING.getCode(); | |||
case BOOLEAN: | |||
return CellType.BOOLEAN.getCode(); | |||
case ERROR_CODE: | |||
return CellType.ERROR.getCode(); | |||
} | |||
throw new IllegalStateException("Unexpected type id (" + typeCode + ")"); | |||
} | |||
public boolean getBooleanValue() { | |||
if (getTypeCode() != BOOLEAN) { | |||
throw new IllegalStateException("Not a boolean cached value - " + formatValue()); | |||
} | |||
return getDataValue() != 0; | |||
} | |||
public int getErrorValue() { | |||
if (getTypeCode() != ERROR_CODE) { | |||
throw new IllegalStateException("Not an error cached value - " + formatValue()); | |||
} | |||
return getDataValue(); | |||
} | |||
} |
@@ -22,28 +22,31 @@ import org.apache.poi.util.IOUtils; | |||
import org.apache.poi.util.LittleEndianInput; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.RecordFormatException; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* This structure appears as part of an Obj record that represents a checkbox or radio button. | |||
* | |||
* @author Yegor Kozlov | |||
*/ | |||
public final class FtCblsSubRecord extends SubRecord implements Cloneable { | |||
public final static short sid = 0x0C; | |||
public final class FtCblsSubRecord extends SubRecord { | |||
public static final short sid = 0x0C; | |||
private static final int ENCODED_SIZE = 20; | |||
private byte[] reserved; | |||
private final byte[] reserved; | |||
/** | |||
* Construct a new <code>FtCblsSubRecord</code> and | |||
* fill its data with the default values | |||
*/ | |||
public FtCblsSubRecord() | |||
{ | |||
public FtCblsSubRecord() { | |||
reserved = new byte[ENCODED_SIZE]; | |||
} | |||
public FtCblsSubRecord(FtCblsSubRecord other) { | |||
super(other); | |||
reserved = other.reserved.clone(); | |||
} | |||
public FtCblsSubRecord(LittleEndianInput in, int size) { | |||
if (size != ENCODED_SIZE) { | |||
throw new RecordFormatException("Unexpected size (" + size + ")"); | |||
@@ -93,12 +96,16 @@ public final class FtCblsSubRecord extends SubRecord implements Cloneable { | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public FtCblsSubRecord clone() { | |||
FtCblsSubRecord rec = new FtCblsSubRecord(); | |||
byte[] recdata = new byte[reserved.length]; | |||
System.arraycopy(reserved, 0, recdata, 0, recdata.length); | |||
rec.reserved = recdata; | |||
return rec; | |||
return copy(); | |||
} | |||
@Override | |||
public FtCblsSubRecord copy() { | |||
return new FtCblsSubRecord(this); | |||
} | |||
} |
@@ -21,15 +21,16 @@ import org.apache.poi.util.HexDump; | |||
import org.apache.poi.util.LittleEndianInput; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.RecordFormatException; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* The FtCf structure specifies the clipboard format of the picture-type Obj record containing this FtCf. | |||
*/ | |||
public final class FtCfSubRecord extends SubRecord implements Cloneable { | |||
public final static short sid = 0x07; | |||
public final static short length = 0x02; | |||
public final class FtCfSubRecord extends SubRecord { | |||
public static final short sid = 0x07; | |||
public static final short length = 0x02; | |||
/** | |||
* Specifies the format of the picture is an enhanced metafile. | |||
*/ | |||
@@ -39,20 +40,24 @@ public final class FtCfSubRecord extends SubRecord implements Cloneable { | |||
* Specifies the format of the picture is a bitmap. | |||
*/ | |||
public static final short BITMAP_BIT = (short)0x0009; | |||
/** | |||
* Specifies the picture is in an unspecified format that is | |||
* neither and enhanced metafile nor a bitmap. | |||
*/ | |||
public static final short UNSPECIFIED_BIT = (short)0xFFFF; | |||
private short flags; | |||
/** | |||
* Construct a new <code>FtPioGrbitSubRecord</code> and | |||
* fill its data with the default values | |||
*/ | |||
public FtCfSubRecord() { | |||
public FtCfSubRecord() {} | |||
public FtCfSubRecord(FtCfSubRecord other) { | |||
super(other); | |||
flags = other.flags; | |||
} | |||
public FtCfSubRecord(LittleEndianInput in, int size) { | |||
@@ -99,10 +104,16 @@ public final class FtCfSubRecord extends SubRecord implements Cloneable { | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public FtCfSubRecord clone() { | |||
FtCfSubRecord rec = new FtCfSubRecord(); | |||
rec.flags = this.flags; | |||
return rec; | |||
return copy(); | |||
} | |||
@Override | |||
public FtCfSubRecord copy() { | |||
return new FtCfSubRecord(this); | |||
} | |||
public short getFlags() { |
@@ -21,27 +21,28 @@ import org.apache.poi.util.HexDump; | |||
import org.apache.poi.util.LittleEndianInput; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.RecordFormatException; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* This structure appears as part of an Obj record that represents image display properties. | |||
*/ | |||
public final class FtPioGrbitSubRecord extends SubRecord implements Cloneable { | |||
public final static short sid = 0x08; | |||
public final static short length = 0x02; | |||
public final class FtPioGrbitSubRecord extends SubRecord { | |||
public static final short sid = 0x08; | |||
public static final short length = 0x02; | |||
/** | |||
* A bit that specifies whether the picture's aspect ratio is preserved when rendered in | |||
* A bit that specifies whether the picture's aspect ratio is preserved when rendered in | |||
* different views (Normal view, Page Break Preview view, Page Layout view and printing). | |||
*/ | |||
public static final int AUTO_PICT_BIT = 1 << 0; | |||
/** | |||
* A bit that specifies whether the pictFmla field of the Obj record that contains | |||
* A bit that specifies whether the pictFmla field of the Obj record that contains | |||
* this FtPioGrbit specifies a DDE reference. | |||
*/ | |||
public static final int DDE_BIT = 1 << 1; | |||
/** | |||
* A bit that specifies whether this object is expected to be updated on print to | |||
* reflect the values in the cell associated with the object. | |||
@@ -52,44 +53,48 @@ public final class FtPioGrbitSubRecord extends SubRecord implements Cloneable { | |||
* A bit that specifies whether the picture is displayed as an icon. | |||
*/ | |||
public static final int ICON_BIT = 1 << 3; | |||
/** | |||
* A bit that specifies whether this object is an ActiveX control. | |||
* It MUST NOT be the case that both fCtl and fDde are equal to 1. | |||
*/ | |||
public static final int CTL_BIT = 1 << 4; | |||
/** | |||
* A bit that specifies whether the object data are stored in an | |||
* embedding storage (= 0) or in the controls stream (ctls) (= 1). | |||
*/ | |||
public static final int PRSTM_BIT = 1 << 5; | |||
/** | |||
* A bit that specifies whether this is a camera picture. | |||
*/ | |||
public static final int CAMERA_BIT = 1 << 7; | |||
/** | |||
* A bit that specifies whether this picture's size has been explicitly set. | |||
* 0 = picture size has been explicitly set, 1 = has not been set | |||
*/ | |||
public static final int DEFAULT_SIZE_BIT = 1 << 8; | |||
/** | |||
* A bit that specifies whether the OLE server for the object is called | |||
* to load the object's data automatically when the parent workbook is opened. | |||
*/ | |||
public static final int AUTO_LOAD_BIT = 1 << 9; | |||
private short flags; | |||
/** | |||
* Construct a new <code>FtPioGrbitSubRecord</code> and | |||
* fill its data with the default values | |||
*/ | |||
public FtPioGrbitSubRecord() { | |||
public FtPioGrbitSubRecord() {} | |||
public FtPioGrbitSubRecord(FtPioGrbitSubRecord other) { | |||
super(other); | |||
flags = other.flags; | |||
} | |||
public FtPioGrbitSubRecord(LittleEndianInput in, int size) { | |||
@@ -110,12 +115,12 @@ public final class FtPioGrbitSubRecord extends SubRecord implements Cloneable { | |||
} else { | |||
flags &= (0xFFFF ^ bitmask); | |||
} | |||
} | |||
} | |||
public boolean getFlagByBit(int bitmask) { | |||
return ((flags & bitmask) != 0); | |||
} | |||
/** | |||
* Convert this record to string. | |||
* Used by BiffViewer and other utilities. | |||
@@ -153,10 +158,16 @@ public final class FtPioGrbitSubRecord extends SubRecord implements Cloneable { | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public FtPioGrbitSubRecord clone() { | |||
FtPioGrbitSubRecord rec = new FtPioGrbitSubRecord(); | |||
rec.flags = this.flags; | |||
return rec; | |||
return copy(); | |||
} | |||
@Override | |||
public FtPioGrbitSubRecord copy() { | |||
return new FtPioGrbitSubRecord(this); | |||
} | |||
public short getFlags() { |
@@ -18,28 +18,25 @@ | |||
package org.apache.poi.hssf.record; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* Title: Gridset Record.<P> | |||
* Description: flag denoting whether the user specified that gridlines are used when | |||
* printing.<P> | |||
* REFERENCE: PG 320 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> | |||
* | |||
* @author Andrew C. Oliver (acoliver at apache dot org) | |||
* @author Glen Stampoultzis (glens at apache.org) | |||
* @author Jason Height (jheight at chariot dot net dot au) | |||
* Flag denoting whether the user specified that gridlines are used when printing. | |||
* | |||
* @version 2.0-pre | |||
*/ | |||
public final class GridsetRecord extends StandardRecord implements Cloneable { | |||
public final static short sid = 0x82; | |||
public final class GridsetRecord extends StandardRecord { | |||
public static final short sid = 0x82; | |||
public short field_1_gridset_flag; | |||
public GridsetRecord() { | |||
public GridsetRecord() {} | |||
public GridsetRecord(GridsetRecord other) { | |||
super(other); | |||
field_1_gridset_flag = other.field_1_gridset_flag; | |||
} | |||
public GridsetRecord(RecordInputStream in) | |||
{ | |||
public GridsetRecord(RecordInputStream in) { | |||
field_1_gridset_flag = in.readShort(); | |||
} | |||
@@ -87,9 +84,15 @@ public final class GridsetRecord extends StandardRecord implements Cloneable { | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public GridsetRecord clone() { | |||
GridsetRecord rec = new GridsetRecord(); | |||
rec.field_1_gridset_flag = field_1_gridset_flag; | |||
return rec; | |||
return copy(); | |||
} | |||
@Override | |||
public GridsetRecord copy() { | |||
return new GridsetRecord(this); | |||
} | |||
} |
@@ -21,13 +21,14 @@ import org.apache.poi.util.HexDump; | |||
import org.apache.poi.util.IOUtils; | |||
import org.apache.poi.util.LittleEndianInput; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* ftGmo (0x0006)<p> | |||
* The group marker record is used as a position holder for groups. | |||
*/ | |||
public final class GroupMarkerSubRecord extends SubRecord implements Cloneable { | |||
public final static short sid = 0x0006; | |||
public final class GroupMarkerSubRecord extends SubRecord { | |||
public static final short sid = 0x0006; | |||
//arbitrarily selected; may need to increase | |||
private static final int MAX_RECORD_LENGTH = 100_000; | |||
@@ -41,6 +42,11 @@ public final class GroupMarkerSubRecord extends SubRecord implements Cloneable { | |||
reserved = EMPTY_BYTE_ARRAY; | |||
} | |||
public GroupMarkerSubRecord(GroupMarkerSubRecord other) { | |||
super(other); | |||
reserved = other.reserved.clone(); | |||
} | |||
public GroupMarkerSubRecord(LittleEndianInput in, int size) { | |||
byte[] buf = IOUtils.safelyAllocate(size, MAX_RECORD_LENGTH); | |||
in.readFully(buf); | |||
@@ -74,10 +80,15 @@ public final class GroupMarkerSubRecord extends SubRecord implements Cloneable { | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public GroupMarkerSubRecord clone() { | |||
GroupMarkerSubRecord rec = new GroupMarkerSubRecord(); | |||
rec.reserved = new byte[reserved.length]; | |||
System.arraycopy(reserved, 0, rec.reserved, 0, reserved.length); | |||
return rec; | |||
return copy(); | |||
} | |||
@Override | |||
public GroupMarkerSubRecord copy() { | |||
return new GroupMarkerSubRecord(this); | |||
} | |||
} |
@@ -15,34 +15,41 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.hssf.record; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* Title: Guts Record <P> | |||
* Description: Row/column gutter sizes <P> | |||
* REFERENCE: PG 320 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> | |||
* @author Andrew C. Oliver (acoliver at apache dot org) | |||
* @author Jason Height (jheight at chariot dot net dot au) | |||
* Row/column gutter sizes | |||
* | |||
* @version 2.0-pre | |||
*/ | |||
public final class GutsRecord extends StandardRecord implements Cloneable { | |||
public final static short sid = 0x80; | |||
private short field_1_left_row_gutter; // size of the row gutter to the left of the rows | |||
private short field_2_top_col_gutter; // size of the column gutter above the columns | |||
private short field_3_row_level_max; // maximum outline level for row gutters | |||
private short field_4_col_level_max; // maximum outline level for column gutters | |||
public GutsRecord() | |||
{ | |||
public final class GutsRecord extends StandardRecord { | |||
public static final short sid = 0x80; | |||
/** size of the row gutter to the left of the rows */ | |||
private short field_1_left_row_gutter; | |||
/** size of the column gutter above the columns */ | |||
private short field_2_top_col_gutter; | |||
/** maximum outline level for row gutters */ | |||
private short field_3_row_level_max; | |||
/** maximum outline level for column gutters */ | |||
private short field_4_col_level_max; | |||
public GutsRecord() {} | |||
public GutsRecord(GutsRecord other) { | |||
super(other); | |||
field_1_left_row_gutter = other.field_1_left_row_gutter; | |||
field_2_top_col_gutter = other.field_2_top_col_gutter; | |||
field_3_row_level_max = other.field_3_row_level_max; | |||
field_4_col_level_max = other.field_4_col_level_max; | |||
} | |||
public GutsRecord(RecordInputStream in) | |||
{ | |||
public GutsRecord(RecordInputStream in) { | |||
field_1_left_row_gutter = in.readShort(); | |||
field_2_top_col_gutter = in.readShort(); | |||
field_3_row_level_max = in.readShort(); | |||
@@ -171,12 +178,15 @@ public final class GutsRecord extends StandardRecord implements Cloneable { | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public GutsRecord clone() { | |||
GutsRecord rec = new GutsRecord(); | |||
rec.field_1_left_row_gutter = field_1_left_row_gutter; | |||
rec.field_2_top_col_gutter = field_2_top_col_gutter; | |||
rec.field_3_row_level_max = field_3_row_level_max; | |||
rec.field_4_col_level_max = field_4_col_level_max; | |||
return rec; | |||
return copy(); | |||
} | |||
@Override | |||
public GutsRecord copy() { | |||
return new GutsRecord(this); | |||
} | |||
} |
@@ -17,24 +17,25 @@ | |||
package org.apache.poi.hssf.record; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* Title: HCenter record (0x0083)<P> | |||
* Description: whether to center between horizontal margins<P> | |||
* REFERENCE: PG 320 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> | |||
* @author Andrew C. Oliver (acoliver at apache dot org) | |||
* @author Jason Height (jheight at chariot dot net dot au) | |||
* Whether to center between horizontal margins | |||
* | |||
* @version 2.0-pre | |||
*/ | |||
public final class HCenterRecord extends StandardRecord implements Cloneable { | |||
public final static short sid = 0x0083; | |||
private short field_1_hcenter; | |||
public final class HCenterRecord extends StandardRecord { | |||
public static final short sid = 0x0083; | |||
private short field_1_hcenter; | |||
public HCenterRecord() { | |||
public HCenterRecord() {} | |||
public HCenterRecord(HCenterRecord other) { | |||
super(other); | |||
field_1_hcenter = other.field_1_hcenter; | |||
} | |||
public HCenterRecord(RecordInputStream in) | |||
{ | |||
public HCenterRecord(RecordInputStream in) { | |||
field_1_hcenter = in.readShort(); | |||
} | |||
@@ -43,11 +44,7 @@ public final class HCenterRecord extends StandardRecord implements Cloneable { | |||
* @param hc center - t/f | |||
*/ | |||
public void setHCenter(boolean hc) { | |||
if (hc) { | |||
field_1_hcenter = 1; | |||
} else { | |||
field_1_hcenter = 0; | |||
} | |||
field_1_hcenter = (short)(hc ? 1 : 0); | |||
} | |||
/** | |||
@@ -80,9 +77,15 @@ public final class HCenterRecord extends StandardRecord implements Cloneable { | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public HCenterRecord clone() { | |||
HCenterRecord rec = new HCenterRecord(); | |||
rec.field_1_hcenter = field_1_hcenter; | |||
return rec; | |||
return copy(); | |||
} | |||
@Override | |||
public HCenterRecord copy() { | |||
return new HCenterRecord(this); | |||
} | |||
} |
@@ -22,8 +22,6 @@ import org.apache.poi.util.StringUtil; | |||
/** | |||
* Common header/footer base class | |||
* | |||
* @author Josh Micich | |||
*/ | |||
public abstract class HeaderFooterBase extends StandardRecord { | |||
private boolean field_2_hasMultibyte; | |||
@@ -33,6 +31,12 @@ public abstract class HeaderFooterBase extends StandardRecord { | |||
setText(text); | |||
} | |||
protected HeaderFooterBase(HeaderFooterBase other) { | |||
super(other); | |||
field_2_hasMultibyte = other.field_2_hasMultibyte; | |||
field_3_text = other.field_3_text; | |||
} | |||
protected HeaderFooterBase(RecordInputStream in) { | |||
if (in.remaining() > 0) { | |||
int field_1_footer_len = in.readShort(); | |||
@@ -107,4 +111,7 @@ public abstract class HeaderFooterBase extends StandardRecord { | |||
} | |||
return 3 + getTextLength() * (field_2_hasMultibyte ? 2 : 1); | |||
} | |||
@Override | |||
public abstract HeaderFooterBase copy(); | |||
} |
@@ -17,28 +17,31 @@ | |||
package org.apache.poi.hssf.record; | |||
import org.apache.poi.util.HexDump; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import java.util.Arrays; | |||
import java.util.Locale; | |||
import org.apache.poi.util.HexDump; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* The HEADERFOOTER record stores information added in Office Excel 2007 for headers/footers. | |||
* | |||
* @author Yegor Kozlov | |||
*/ | |||
public final class HeaderFooterRecord extends StandardRecord implements Cloneable { | |||
public final class HeaderFooterRecord extends StandardRecord { | |||
public static final short sid = 0x089C; | |||
private static final byte[] BLANK_GUID = new byte[16]; | |||
public final static short sid = 0x089C; | |||
private byte[] _rawData; | |||
public HeaderFooterRecord(byte[] data) { | |||
_rawData = data; | |||
} | |||
public HeaderFooterRecord(HeaderFooterRecord other) { | |||
super(other); | |||
_rawData = (other._rawData == null) ? null : other._rawData.clone(); | |||
} | |||
/** | |||
* construct a HeaderFooterRecord record. No fields are interpreted and the record will | |||
* be serialized in its original form more or less | |||
@@ -58,7 +61,7 @@ public final class HeaderFooterRecord extends StandardRecord implements Cloneabl | |||
protected int getDataSize() { | |||
return _rawData.length; | |||
} | |||
public short getSid() | |||
{ | |||
return sid; | |||
@@ -79,7 +82,7 @@ public final class HeaderFooterRecord extends StandardRecord implements Cloneabl | |||
} | |||
/** | |||
* @return whether this record belongs to the current sheet | |||
* @return whether this record belongs to the current sheet | |||
*/ | |||
public boolean isCurrentSheet(){ | |||
return Arrays.equals(getGuid(), BLANK_GUID); | |||
@@ -96,10 +99,17 @@ public final class HeaderFooterRecord extends StandardRecord implements Cloneabl | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public HeaderFooterRecord clone() { | |||
//HACK: do a "cheat" clone, see Record.java for more information | |||
return (HeaderFooterRecord)cloneViaReserialise(); | |||
return copy(); | |||
} | |||
@Override | |||
public HeaderFooterRecord copy() { | |||
return new HeaderFooterRecord(this); | |||
} | |||
} |
@@ -17,21 +17,22 @@ | |||
package org.apache.poi.hssf.record; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* Title: Header Record<P> | |||
* Description: Specifies a header for a sheet<P> | |||
* REFERENCE: PG 321 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> | |||
* @author Andrew C. Oliver (acoliver at apache dot org) | |||
* @author Shawn Laubach (slaubach at apache dot org) Modified 3/14/02 | |||
* @author Jason Height (jheight at chariot dot net dot au) | |||
* Specifies a header for a sheet | |||
*/ | |||
public final class HeaderRecord extends HeaderFooterBase implements Cloneable { | |||
public final static short sid = 0x0014; | |||
public final class HeaderRecord extends HeaderFooterBase { | |||
public static final short sid = 0x0014; | |||
public HeaderRecord(String text) { | |||
super(text); | |||
} | |||
public HeaderRecord(HeaderRecord other) { | |||
super(other); | |||
} | |||
public HeaderRecord(RecordInputStream in) { | |||
super(in); | |||
} | |||
@@ -50,7 +51,15 @@ public final class HeaderRecord extends HeaderFooterBase implements Cloneable { | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public HeaderRecord clone() { | |||
return new HeaderRecord(getText()); | |||
return copy(); | |||
} | |||
@Override | |||
public HeaderRecord copy() { | |||
return new HeaderRecord(this); | |||
} | |||
} |
@@ -15,35 +15,33 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.hssf.record; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
/** | |||
* Title: Hide Object Record<P> | |||
* Description: flag defines whether to hide placeholders and object<P> | |||
* REFERENCE: PG 321 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> | |||
* @author Andrew C. Oliver (acoliver at apache dot org) | |||
* Flag defines whether to hide placeholders and object | |||
* | |||
* @version 2.0-pre | |||
*/ | |||
public final class HideObjRecord extends StandardRecord { | |||
public static final short sid = 0x8d; | |||
public static final short HIDE_ALL = 2; | |||
public static final short SHOW_PLACEHOLDERS = 1; | |||
public static final short SHOW_ALL = 0; | |||
public final class HideObjRecord | |||
extends StandardRecord | |||
{ | |||
public final static short sid = 0x8d; | |||
public final static short HIDE_ALL = 2; | |||
public final static short SHOW_PLACEHOLDERS = 1; | |||
public final static short SHOW_ALL = 0; | |||
private short field_1_hide_obj; | |||
private short field_1_hide_obj; | |||
public HideObjRecord() | |||
{ | |||
public HideObjRecord() {} | |||
public HideObjRecord(HideObjRecord other) { | |||
super(other); | |||
field_1_hide_obj = other.field_1_hide_obj; | |||
} | |||
public HideObjRecord(RecordInputStream in) | |||
{ | |||
public HideObjRecord(RecordInputStream in) { | |||
field_1_hide_obj = in.readShort(); | |||
} | |||
@@ -98,4 +96,9 @@ public final class HideObjRecord | |||
{ | |||
return sid; | |||
} | |||
@Override | |||
public HideObjRecord copy() { | |||
return new HideObjRecord(this); | |||
} | |||
} |
@@ -17,21 +17,24 @@ | |||
package org.apache.poi.hssf.record; | |||
import java.util.Iterator; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* HorizontalPageBreak (0x001B) record that stores page breaks at rows | |||
* | |||
* | |||
* @see PageBreakRecord | |||
*/ | |||
public final class HorizontalPageBreakRecord extends PageBreakRecord implements Cloneable { | |||
public final class HorizontalPageBreakRecord extends PageBreakRecord { | |||
public static final short sid = 0x001B; | |||
/** | |||
* Creates an empty horizontal page break record | |||
*/ | |||
public HorizontalPageBreakRecord() { | |||
public HorizontalPageBreakRecord() {} | |||
public HorizontalPageBreakRecord(HorizontalPageBreakRecord other) { | |||
super(other); | |||
} | |||
/** | |||
@@ -46,13 +49,15 @@ public final class HorizontalPageBreakRecord extends PageBreakRecord implements | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public PageBreakRecord clone() { | |||
PageBreakRecord result = new HorizontalPageBreakRecord(); | |||
Iterator<Break> iterator = getBreaksIterator(); | |||
while (iterator.hasNext()) { | |||
Break original = iterator.next(); | |||
result.addBreak(original.main, original.subFrom, original.subTo); | |||
} | |||
return result; | |||
return copy(); | |||
} | |||
@Override | |||
public HorizontalPageBreakRecord copy() { | |||
return new HorizontalPageBreakRecord(this); | |||
} | |||
} |
@@ -27,6 +27,7 @@ import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.POILogFactory; | |||
import org.apache.poi.util.POILogger; | |||
import org.apache.poi.util.RecordFormatException; | |||
import org.apache.poi.util.Removal; | |||
import org.apache.poi.util.StringUtil; | |||
/** | |||
@@ -34,13 +35,14 @@ import org.apache.poi.util.StringUtil; | |||
* from the Excel-97 format. | |||
* Supports only external links for now (eg http://) | |||
*/ | |||
public final class HyperlinkRecord extends StandardRecord implements Cloneable { | |||
public final static short sid = 0x01B8; | |||
public final class HyperlinkRecord extends StandardRecord { | |||
public static final short sid = 0x01B8; | |||
private static POILogger logger = POILogFactory.getLogger(HyperlinkRecord.class); | |||
//arbitrarily selected; may need to increase | |||
private static final int MAX_RECORD_LENGTH = 100_000; | |||
// TODO: replace with ClassID | |||
static final class GUID { | |||
/* | |||
* this class is currently only used here, but could be moved to a | |||
@@ -61,6 +63,13 @@ public final class HyperlinkRecord extends StandardRecord implements Cloneable { | |||
*/ | |||
private final long _d4; | |||
public GUID(GUID other) { | |||
_d1 = other._d1; | |||
_d2 = other._d2; | |||
_d3 = other._d3; | |||
_d4 = other._d4; | |||
} | |||
public GUID(LittleEndianInput in) { | |||
this(in.readInt(), in.readUShort(), in.readUShort(), in.readLong()); | |||
} | |||
@@ -199,24 +208,24 @@ public final class HyperlinkRecord extends StandardRecord implements Cloneable { | |||
} | |||
} | |||
/** | |||
/* | |||
* Link flags | |||
*/ | |||
static final int HLINK_URL = 0x01; // File link or URL. | |||
static final int HLINK_ABS = 0x02; // Absolute path. | |||
static final int HLINK_LABEL = 0x14; // Has label/description. | |||
static final int HLINK_URL = 0x01; // File link or URL. | |||
static final int HLINK_ABS = 0x02; // Absolute path. | |||
static final int HLINK_LABEL = 0x14; // Has label/description. | |||
/** Place in worksheet. If set, the {@link #_textMark} field will be present */ | |||
static final int HLINK_PLACE = 0x08; | |||
static final int HLINK_PLACE = 0x08; | |||
private static final int HLINK_TARGET_FRAME = 0x80; // has 'target frame' | |||
private static final int HLINK_UNC_PATH = 0x100; // has UNC path | |||
final static GUID STD_MONIKER = GUID.parse("79EAC9D0-BAF9-11CE-8C82-00AA004BA90B"); | |||
final static GUID URL_MONIKER = GUID.parse("79EAC9E0-BAF9-11CE-8C82-00AA004BA90B"); | |||
final static GUID FILE_MONIKER = GUID.parse("00000303-0000-0000-C000-000000000046"); | |||
static final GUID STD_MONIKER = GUID.parse("79EAC9D0-BAF9-11CE-8C82-00AA004BA90B"); | |||
static final GUID URL_MONIKER = GUID.parse("79EAC9E0-BAF9-11CE-8C82-00AA004BA90B"); | |||
static final GUID FILE_MONIKER = GUID.parse("00000303-0000-0000-C000-000000000046"); | |||
/** expected Tail of a URL link */ | |||
private final static byte[] URL_TAIL = HexRead.readFromString("79 58 81 F4 3B 1D 7F 48 AF 2C 82 5D C4 85 27 63 00 00 00 00 A5 AB 00 00"); | |||
private static final byte[] URL_TAIL = HexRead.readFromString("79 58 81 F4 3B 1D 7F 48 AF 2C 82 5D C4 85 27 63 00 00 00 00 A5 AB 00 00"); | |||
/** expected Tail of a file link */ | |||
private final static byte[] FILE_TAIL = HexRead.readFromString("FF FF AD DE 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"); | |||
private static final byte[] FILE_TAIL = HexRead.readFromString("FF FF AD DE 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"); | |||
private static final int TAIL_SIZE = FILE_TAIL.length; | |||
@@ -246,17 +255,31 @@ public final class HyperlinkRecord extends StandardRecord implements Cloneable { | |||
* This field is optional. If present, the {@link #HLINK_PLACE} must be set. | |||
*/ | |||
private String _textMark; | |||
private byte[] _uninterpretedTail; | |||
/** | |||
* Create a new hyperlink | |||
*/ | |||
public HyperlinkRecord() | |||
{ | |||
public HyperlinkRecord() {} | |||
public HyperlinkRecord(HyperlinkRecord other) { | |||
super(other); | |||
_range = (other._range == null) ? null : other._range.copy(); | |||
_guid = (other._guid == null) ? null : new GUID(other._guid); | |||
_fileOpts = other._fileOpts; | |||
_linkOpts = other._linkOpts; | |||
_label = other._label; | |||
_targetFrame = other._targetFrame; | |||
_moniker = (other._moniker == null) ? null : new GUID(other._moniker); | |||
_shortFilename = other._shortFilename; | |||
_address = other._address; | |||
_textMark = other._textMark; | |||
_uninterpretedTail = (other._uninterpretedTail == null) ? null : other._uninterpretedTail.clone(); | |||
} | |||
/** | |||
* @return the 0-based column of the first cell that contains this hyperlink | |||
*/ | |||
@@ -266,7 +289,7 @@ public final class HyperlinkRecord extends StandardRecord implements Cloneable { | |||
/** | |||
* Set the first column (zero-based) of the range that contains this hyperlink | |||
* | |||
* | |||
* @param firstCol the first column (zero-based) | |||
*/ | |||
public void setFirstColumn(int firstCol) { | |||
@@ -282,7 +305,7 @@ public final class HyperlinkRecord extends StandardRecord implements Cloneable { | |||
/** | |||
* Set the last column (zero-based) of the range that contains this hyperlink | |||
* | |||
* | |||
* @param lastCol the last column (zero-based) | |||
*/ | |||
public void setLastColumn(int lastCol) { | |||
@@ -298,7 +321,7 @@ public final class HyperlinkRecord extends StandardRecord implements Cloneable { | |||
/** | |||
* Set the first row (zero-based) of the range that contains this hyperlink | |||
* | |||
* | |||
* @param firstRow the first row (zero-based) | |||
*/ | |||
public void setFirstRow(int firstRow) { | |||
@@ -314,7 +337,7 @@ public final class HyperlinkRecord extends StandardRecord implements Cloneable { | |||
/** | |||
* Set the last row (zero-based) of the range that contains this hyperlink | |||
* | |||
* | |||
* @param lastRow the last row (zero-based) | |||
*/ | |||
public void setLastRow(int lastRow) { | |||
@@ -423,7 +446,7 @@ public final class HyperlinkRecord extends StandardRecord implements Cloneable { | |||
/** | |||
* Link options. Must be a combination of HLINK_* constants. | |||
* For testing only | |||
* | |||
* | |||
* @return Link options | |||
*/ | |||
int getLinkOptions(){ | |||
@@ -541,7 +564,7 @@ public final class HyperlinkRecord extends StandardRecord implements Cloneable { | |||
} | |||
if (in.remaining() > 0) { | |||
logger.log(POILogger.WARN, | |||
logger.log(POILogger.WARN, | |||
"Hyperlink data remains: " + in.remaining() + | |||
" : " +HexDump.toHex(in.readRemainder()) | |||
); | |||
@@ -699,31 +722,31 @@ public final class HyperlinkRecord extends StandardRecord implements Cloneable { | |||
/** | |||
* Based on the link options, is this a url? | |||
* | |||
* | |||
* @return true, if this is a url link | |||
*/ | |||
public boolean isUrlLink() { | |||
return (_linkOpts & HLINK_URL) > 0 | |||
return (_linkOpts & HLINK_URL) > 0 | |||
&& (_linkOpts & HLINK_ABS) > 0; | |||
} | |||
/** | |||
* Based on the link options, is this a file? | |||
* | |||
* | |||
* @return true, if this is a file link | |||
*/ | |||
public boolean isFileLink() { | |||
return (_linkOpts & HLINK_URL) > 0 | |||
return (_linkOpts & HLINK_URL) > 0 | |||
&& (_linkOpts & HLINK_ABS) == 0; | |||
} | |||
/** | |||
* Based on the link options, is this a document? | |||
* | |||
* | |||
* @return true, if this is a docment link | |||
*/ | |||
public boolean isDocumentLink() { | |||
return (_linkOpts & HLINK_PLACE) > 0; | |||
return (_linkOpts & HLINK_PLACE) > 0; | |||
} | |||
/** | |||
* Initialize a new url link | |||
*/ | |||
@@ -766,19 +789,15 @@ public final class HyperlinkRecord extends StandardRecord implements Cloneable { | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public HyperlinkRecord clone() { | |||
HyperlinkRecord rec = new HyperlinkRecord(); | |||
rec._range = _range.copy(); | |||
rec._guid = _guid; | |||
rec._linkOpts = _linkOpts; | |||
rec._fileOpts = _fileOpts; | |||
rec._label = _label; | |||
rec._address = _address; | |||
rec._moniker = _moniker; | |||
rec._shortFilename = _shortFilename; | |||
rec._targetFrame = _targetFrame; | |||
rec._textMark = _textMark; | |||
rec._uninterpretedTail = _uninterpretedTail; | |||
return rec; | |||
return copy(); | |||
} | |||
@Override | |||
public HyperlinkRecord copy() { | |||
return new HyperlinkRecord(this); | |||
} | |||
} |
@@ -20,27 +20,29 @@ package org.apache.poi.hssf.record; | |||
import org.apache.poi.util.IntList; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.RecordFormatException; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* Title: Index Record (0x020B)<p> | |||
* Description: Occurs right after BOF, tells you where the DBCELL records are for a sheet | |||
* Important for locating cells<p> | |||
* | |||
* REFERENCE: PG 323 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) | |||
* Occurs right after BOF, tells you where the DBCELL records are for a sheet Important for locating cells | |||
*/ | |||
public final class IndexRecord extends StandardRecord implements Cloneable { | |||
public final static short sid = 0x020B; | |||
public final class IndexRecord extends StandardRecord { | |||
public static final short sid = 0x020B; | |||
private int field_2_first_row; // first row on the sheet | |||
private int field_3_last_row_add1; // last row | |||
private int field_4_zero; // supposed to be zero | |||
private IntList field_5_dbcells; // array of offsets to DBCELL records | |||
public IndexRecord() | |||
{ | |||
public IndexRecord() {} | |||
public IndexRecord(IndexRecord other) { | |||
super(other); | |||
field_2_first_row = other.field_2_first_row; | |||
field_3_last_row_add1 = other.field_3_last_row_add1; | |||
field_4_zero = other.field_4_zero; | |||
field_5_dbcells = (other.field_5_dbcells == null) ? null : new IntList(other.field_5_dbcells); | |||
} | |||
public IndexRecord(RecordInputStream in) | |||
{ | |||
public IndexRecord(RecordInputStream in) { | |||
int field_1_zero = in.readInt(); | |||
if (field_1_zero != 0) { | |||
throw new RecordFormatException("Expected zero for field 1 but got " + field_1_zero); | |||
@@ -48,7 +50,7 @@ public final class IndexRecord extends StandardRecord implements Cloneable { | |||
field_2_first_row = in.readInt(); | |||
field_3_last_row_add1 = in.readInt(); | |||
field_4_zero = in.readInt(); | |||
int nCells = in.remaining() / 4; | |||
field_5_dbcells = new IntList(nCells); | |||
for(int i=0; i<nCells; i++) { | |||
@@ -139,14 +141,14 @@ public final class IndexRecord extends StandardRecord implements Cloneable { | |||
return 16 // 4 ints | |||
+ getNumDbcells() * 4; | |||
} | |||
/** | |||
/** | |||
* @param blockCount the number of blocks to be indexed | |||
* @return the size of an IndexRecord when it needs to index the specified number of blocks | |||
*/ | |||
public static int getRecordSizeForBlockCount(int blockCount) { | |||
return 20 + 4 * blockCount; | |||
} | |||
} | |||
@Override | |||
public short getSid() { | |||
@@ -154,13 +156,15 @@ public final class IndexRecord extends StandardRecord implements Cloneable { | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public IndexRecord clone() { | |||
IndexRecord rec = new IndexRecord(); | |||
rec.field_2_first_row = field_2_first_row; | |||
rec.field_3_last_row_add1 = field_3_last_row_add1; | |||
rec.field_4_zero = field_4_zero; | |||
rec.field_5_dbcells = new IntList(); | |||
rec.field_5_dbcells.addAll(field_5_dbcells); | |||
return rec; | |||
return copy(); | |||
} | |||
@Override | |||
public IndexRecord copy() { | |||
return new IndexRecord(this); | |||
} | |||
} |
@@ -21,11 +21,7 @@ import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.RecordFormatException; | |||
/** | |||
* Title: Interface End Record (0x00E2)<P> | |||
* Description: Shows where the Interface Records end (MMS) | |||
* (has no fields)<P> | |||
* REFERENCE: PG 324 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> | |||
* @author Andrew C. Oliver (acoliver at apache dot org) | |||
* Shows where the Interface Records ends (MMS) | |||
*/ | |||
public final class InterfaceEndRecord extends StandardRecord { | |||
@@ -61,4 +57,9 @@ public final class InterfaceEndRecord extends StandardRecord { | |||
public short getSid() { | |||
return sid; | |||
} | |||
@Override | |||
public InterfaceEndRecord copy() { | |||
return instance; | |||
} | |||
} |
@@ -21,19 +21,22 @@ import org.apache.poi.util.HexDump; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
/** | |||
* Title: Interface Header Record (0x00E1)<P> | |||
* Description: Defines the beginning of Interface records (MMS)<P> | |||
* REFERENCE: PG 324 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> | |||
* @author Andrew C. Oliver (acoliver at apache dot org) | |||
* Defines the beginning of Interface records (MMS) | |||
*/ | |||
public final class InterfaceHdrRecord extends StandardRecord { | |||
public final static short sid = 0x00E1; | |||
private final int _codepage; | |||
public static final short sid = 0x00E1; | |||
/** | |||
* suggested (and probably correct) default | |||
*/ | |||
public final static int CODEPAGE = 0x04B0; | |||
public static final int CODEPAGE = 0x04B0; | |||
private final int _codepage; | |||
public InterfaceHdrRecord(InterfaceHdrRecord other) { | |||
super(other); | |||
_codepage = other._codepage; | |||
} | |||
public InterfaceHdrRecord(int codePage) { | |||
_codepage = codePage; | |||
@@ -63,4 +66,9 @@ public final class InterfaceHdrRecord extends StandardRecord { | |||
public short getSid() { | |||
return sid; | |||
} | |||
@Override | |||
public InterfaceHdrRecord copy() { | |||
return new InterfaceHdrRecord(this); | |||
} | |||
} |
@@ -21,28 +21,30 @@ import org.apache.poi.util.BitField; | |||
import org.apache.poi.util.BitFieldFactory; | |||
import org.apache.poi.util.HexDump; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* Title: Iteration Record (0x0011)<p> | |||
* Description: Tells whether to iterate over formula calculations or not | |||
* (if a formula is dependent upon another formula's result) | |||
* (odd feature for something that can only have 32 elements in | |||
* a formula!)<p> | |||
* REFERENCE: PG 325 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) | |||
* Tells whether to iterate over formula calculations or not. | |||
* If a formula is dependent upon another formula's result. | |||
* (odd feature for something that can only have 32 elements in a formula!) | |||
*/ | |||
public final class IterationRecord extends StandardRecord implements Cloneable { | |||
public final static short sid = 0x0011; | |||
public final class IterationRecord extends StandardRecord { | |||
public static final short sid = 0x0011; | |||
private static final BitField iterationOn = BitFieldFactory.getInstance(0x0001); | |||
private int _flags; | |||
public IterationRecord(IterationRecord other) { | |||
super(other); | |||
_flags = other._flags; | |||
} | |||
public IterationRecord(boolean iterateOn) { | |||
_flags = iterationOn.setBoolean(0, iterateOn); | |||
} | |||
public IterationRecord(RecordInputStream in) | |||
{ | |||
public IterationRecord(RecordInputStream in) { | |||
_flags = in.readShort(); | |||
} | |||
@@ -85,7 +87,15 @@ public final class IterationRecord extends StandardRecord implements Cloneable { | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public IterationRecord clone() { | |||
return new IterationRecord(getIteration()); | |||
return copy(); | |||
} | |||
@Override | |||
public IterationRecord copy() { | |||
return new IterationRecord(this); | |||
} | |||
} |
@@ -21,36 +21,43 @@ import org.apache.poi.util.HexDump; | |||
import org.apache.poi.util.POILogFactory; | |||
import org.apache.poi.util.POILogger; | |||
import org.apache.poi.util.RecordFormatException; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* Label Record (0x0204) - read only support for strings stored directly in the cell... | |||
* Don't use this (except to read), use LabelSST instead <P> | |||
* REFERENCE: PG 325 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) | |||
* | |||
* Don't use this (except to read), use LabelSST instead | |||
* | |||
* @see org.apache.poi.hssf.record.LabelSSTRecord | |||
*/ | |||
public final class LabelRecord extends Record implements CellValueRecordInterface, Cloneable { | |||
private final static POILogger logger = POILogFactory.getLogger(LabelRecord.class); | |||
public final class LabelRecord extends Record implements CellValueRecordInterface { | |||
private static final POILogger logger = POILogFactory.getLogger(LabelRecord.class); | |||
public final static short sid = 0x0204; | |||
public static final short sid = 0x0204; | |||
private int field_1_row; | |||
private short field_2_column; | |||
private short field_3_xf_index; | |||
private short field_4_string_len; | |||
private byte field_5_unicode_flag; | |||
private String field_6_value; | |||
private int field_1_row; | |||
private short field_2_column; | |||
private short field_3_xf_index; | |||
private short field_4_string_len; | |||
private byte field_5_unicode_flag; | |||
private String field_6_value; | |||
/** Creates new LabelRecord */ | |||
public LabelRecord() | |||
{ | |||
public LabelRecord() {} | |||
public LabelRecord(LabelRecord other) { | |||
super(other); | |||
field_1_row = other.field_1_row; | |||
field_2_column = other.field_2_column; | |||
field_3_xf_index = other.field_3_xf_index; | |||
field_4_string_len = other.field_4_string_len; | |||
field_5_unicode_flag = other.field_5_unicode_flag; | |||
field_6_value = other.field_6_value; | |||
} | |||
/** | |||
* @param in the RecordInputstream to read the record from | |||
*/ | |||
public LabelRecord(RecordInputStream in) | |||
{ | |||
public LabelRecord(RecordInputStream in) { | |||
field_1_row = in.readUShort(); | |||
field_2_column = in.readShort(); | |||
field_3_xf_index = in.readShort(); | |||
@@ -182,14 +189,15 @@ public final class LabelRecord extends Record implements CellValueRecordInterfac | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public LabelRecord clone() { | |||
LabelRecord rec = new LabelRecord(); | |||
rec.field_1_row = field_1_row; | |||
rec.field_2_column = field_2_column; | |||
rec.field_3_xf_index = field_3_xf_index; | |||
rec.field_4_string_len = field_4_string_len; | |||
rec.field_5_unicode_flag = field_5_unicode_flag; | |||
rec.field_6_value = field_6_value; | |||
return rec; | |||
return copy(); | |||
} | |||
@Override | |||
public LabelRecord copy() { | |||
return new LabelRecord(this); | |||
} | |||
} |
@@ -19,18 +19,20 @@ package org.apache.poi.hssf.record; | |||
import org.apache.poi.util.HexDump; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* Title: Label SST Record<P> | |||
* Description: Refers to a string in the shared string table and is a column value.<P> | |||
* REFERENCE: PG 325 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) | |||
* Refers to a string in the shared string table and is a column value. | |||
*/ | |||
public final class LabelSSTRecord extends CellRecord implements Cloneable { | |||
public final static short sid = 0xfd; | |||
public final class LabelSSTRecord extends CellRecord { | |||
public static final short sid = 0xfd; | |||
private int field_4_sst_index; | |||
public LabelSSTRecord() { | |||
// fields uninitialised | |||
public LabelSSTRecord() {} | |||
public LabelSSTRecord(LabelSSTRecord other) { | |||
super(other); | |||
field_4_sst_index = other.field_4_sst_index; | |||
} | |||
public LabelSSTRecord(RecordInputStream in) { | |||
@@ -58,7 +60,7 @@ public final class LabelSSTRecord extends CellRecord implements Cloneable { | |||
public int getSSTIndex() { | |||
return field_4_sst_index; | |||
} | |||
@Override | |||
protected String getRecordName() { | |||
return "LABELSST"; | |||
@@ -85,10 +87,15 @@ public final class LabelSSTRecord extends CellRecord implements Cloneable { | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public LabelSSTRecord clone() { | |||
LabelSSTRecord rec = new LabelSSTRecord(); | |||
copyBaseFields(rec); | |||
rec.field_4_sst_index = field_4_sst_index; | |||
return rec; | |||
return copy(); | |||
} | |||
@Override | |||
public LabelSSTRecord copy() { | |||
return new LabelSSTRecord(this); | |||
} | |||
} |
@@ -16,11 +16,13 @@ | |||
==================================================================== */ | |||
package org.apache.poi.hssf.record; | |||
import org.apache.poi.common.Duplicatable; | |||
import org.apache.poi.ss.formula.ptg.Ptg; | |||
import org.apache.poi.util.HexDump; | |||
import org.apache.poi.util.LittleEndianInput; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.RecordFormatException; | |||
import org.apache.poi.util.Removal; | |||
import org.apache.poi.util.StringUtil; | |||
/** | |||
@@ -89,6 +91,24 @@ public class LbsDataSubRecord extends SubRecord { | |||
*/ | |||
private boolean[] _bsels; | |||
LbsDataSubRecord() {} | |||
public LbsDataSubRecord(LbsDataSubRecord other) { | |||
super(other); | |||
_cbFContinued = other._cbFContinued; | |||
_unknownPreFormulaInt = other._unknownPreFormulaInt; | |||
_linkPtg = (other._linkPtg == null) ? null : other._linkPtg.copy(); | |||
_unknownPostFormulaByte = other._unknownPostFormulaByte; | |||
_cLines = other._cLines; | |||
_iSel = other._iSel; | |||
_flags = other._flags; | |||
_idEdit = other._idEdit; | |||
_dropData = (other._dropData == null) ? null : other._dropData.copy(); | |||
_rgLines = (other._rgLines == null) ? null : other._rgLines.clone(); | |||
_bsels = (other._bsels == null) ? null : other._bsels.clone(); | |||
} | |||
/** | |||
* @param in the stream to read data from | |||
* @param cbFContinued the seconf short in the record header | |||
@@ -154,10 +174,6 @@ public class LbsDataSubRecord extends SubRecord { | |||
} | |||
LbsDataSubRecord(){ | |||
} | |||
/** | |||
* | |||
* @return a new instance of LbsDataSubRecord to construct auto-filters | |||
@@ -259,9 +275,16 @@ public class LbsDataSubRecord extends SubRecord { | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public LbsDataSubRecord clone() { | |||
// TODO: is immutable ??? | |||
return this; | |||
return copy(); | |||
} | |||
@Override | |||
public LbsDataSubRecord copy() { | |||
return new LbsDataSubRecord(this); | |||
} | |||
@Override | |||
@@ -303,7 +326,7 @@ public class LbsDataSubRecord extends SubRecord { | |||
/** | |||
* This structure specifies properties of the dropdown list control | |||
*/ | |||
public static class LbsDropData { | |||
public static class LbsDropData implements Duplicatable { | |||
/** | |||
* Combo dropdown control | |||
*/ | |||
@@ -318,7 +341,7 @@ public class LbsDataSubRecord extends SubRecord { | |||
public static final int STYLE_COMBO_SIMPLE_DROPDOWN = 2; | |||
/** | |||
* An unsigned integer that specifies the style of this dropdown. | |||
* An unsigned integer that specifies the style of this dropdown. | |||
*/ | |||
private int _wStyle; | |||
@@ -343,12 +366,20 @@ public class LbsDataSubRecord extends SubRecord { | |||
*/ | |||
private Byte _unused; | |||
public LbsDropData(){ | |||
public LbsDropData() { | |||
_str = ""; | |||
_unused = 0; | |||
} | |||
public LbsDropData(LittleEndianInput in){ | |||
public LbsDropData(LbsDropData other) { | |||
_wStyle = other._wStyle; | |||
_cLine = other._cLine; | |||
_dxMin = other._dxMin; | |||
_str = other._str; | |||
_unused = other._unused; | |||
} | |||
public LbsDropData(LittleEndianInput in) { | |||
_wStyle = in.readUShort(); | |||
_cLine = in.readUShort(); | |||
_dxMin = in.readUShort(); | |||
@@ -367,7 +398,7 @@ public class LbsDataSubRecord extends SubRecord { | |||
* <li>1: Combo Edit dropdown control</li> | |||
* <li>2: Simple dropdown control (just the dropdown button)</li> | |||
* </ul> | |||
* | |||
* | |||
* @param style the style - see possible values | |||
*/ | |||
public void setStyle(int style){ | |||
@@ -376,7 +407,7 @@ public class LbsDataSubRecord extends SubRecord { | |||
/** | |||
* Set the number of lines to be displayed in the dropdown. | |||
* | |||
* | |||
* @param num the number of lines to be displayed in the dropdown | |||
*/ | |||
public void setNumLines(int num){ | |||
@@ -417,5 +448,10 @@ public class LbsDataSubRecord extends SubRecord { | |||
return sb.toString(); | |||
} | |||
@Override | |||
public LbsDropData copy() { | |||
return new LbsDropData(this); | |||
} | |||
} | |||
} |
@@ -18,18 +18,23 @@ | |||
package org.apache.poi.hssf.record; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* Record for the left margin. | |||
*/ | |||
public final class LeftMarginRecord extends StandardRecord implements Margin, Cloneable { | |||
public final static short sid = 0x0026; | |||
public final class LeftMarginRecord extends StandardRecord implements Margin { | |||
public static final short sid = 0x0026; | |||
private double field_1_margin; | |||
public LeftMarginRecord() { } | |||
public LeftMarginRecord() {} | |||
public LeftMarginRecord(RecordInputStream in) | |||
{ | |||
public LeftMarginRecord(LeftMarginRecord other) { | |||
super(other); | |||
field_1_margin = other.field_1_margin; | |||
} | |||
public LeftMarginRecord(RecordInputStream in) { | |||
field_1_margin = in.readDouble(); | |||
} | |||
@@ -70,9 +75,15 @@ public final class LeftMarginRecord extends StandardRecord implements Margin, Cl | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public LeftMarginRecord clone() { | |||
LeftMarginRecord rec = new LeftMarginRecord(); | |||
rec.field_1_margin = this.field_1_margin; | |||
return rec; | |||
return copy(); | |||
} | |||
@Override | |||
public LeftMarginRecord copy() { | |||
return new LeftMarginRecord(this); | |||
} | |||
} | |||
} |
@@ -15,38 +15,36 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.hssf.record; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
/** | |||
* Title: MMS Record<P> | |||
* Description: defines how many add menu and del menu options are stored | |||
* in the file. Should always be set to 0 for HSSF workbooks<P> | |||
* REFERENCE: PG 328 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> | |||
* @author Andrew C. Oliver (acoliver at apache dot org) | |||
* defines how many add menu and del menu options are stored in the file. | |||
* Should always be set to 0 for HSSF workbooks. | |||
* | |||
* @version 2.0-pre | |||
*/ | |||
public final class MMSRecord | |||
extends StandardRecord | |||
{ | |||
public final static short sid = 0xC1; | |||
private byte field_1_addMenuCount; // = 0; | |||
private byte field_2_delMenuCount; // = 0; | |||
public final class MMSRecord extends StandardRecord { | |||
public static final short sid = 0xC1; | |||
private byte field_1_addMenuCount; | |||
private byte field_2_delMenuCount; | |||
public MMSRecord() | |||
{ | |||
public MMSRecord() {} | |||
public MMSRecord(MMSRecord other) { | |||
field_1_addMenuCount = other.field_1_addMenuCount; | |||
field_2_delMenuCount = other.field_2_delMenuCount; | |||
} | |||
public MMSRecord(RecordInputStream in) | |||
{ | |||
public MMSRecord(RecordInputStream in) { | |||
if (in.remaining()==0) { | |||
return; | |||
} | |||
field_1_addMenuCount = in.readByte(); | |||
field_2_delMenuCount = in.readByte(); | |||
} | |||
@@ -117,4 +115,9 @@ public final class MMSRecord | |||
{ | |||
return sid; | |||
} | |||
@Override | |||
public MMSRecord copy() { | |||
return new MMSRecord(this); | |||
} | |||
} |
@@ -17,22 +17,33 @@ | |||
package org.apache.poi.hssf.record; | |||
import java.util.stream.Stream; | |||
import org.apache.poi.ss.util.CellRangeAddress; | |||
import org.apache.poi.ss.util.CellRangeAddressList; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* Title: Merged Cells Record (0x00E5)<p> | |||
* | |||
* Description: Optional record defining a square area of cells to "merged" into one cell. | |||
* Optional record defining a square area of cells to "merged" into one cell. | |||
*/ | |||
public final class MergeCellsRecord extends StandardRecord implements Cloneable { | |||
public final static short sid = 0x00E5; | |||
/** sometimes the regions array is shared with other MergedCellsRecords */ | |||
public final class MergeCellsRecord extends StandardRecord { | |||
public static final short sid = 0x00E5; | |||
/** sometimes the regions array is shared with other MergedCellsRecords */ | |||
private final CellRangeAddress[] _regions; | |||
private final int _startIndex; | |||
private final int _numberOfRegions; | |||
public MergeCellsRecord(MergeCellsRecord other) { | |||
super(other); | |||
_regions = (other._regions == null) ? null | |||
: Stream.of(other._regions).map(CellRangeAddress::copy).toArray(CellRangeAddress[]::new); | |||
_startIndex = other._startIndex; | |||
_numberOfRegions = other._numberOfRegions; | |||
} | |||
public MergeCellsRecord(CellRangeAddress[] regions, int startIndex, int numberOfRegions) { | |||
_regions = regions; | |||
_startIndex = startIndex; | |||
@@ -63,7 +74,7 @@ public final class MergeCellsRecord extends StandardRecord implements Cloneable | |||
/** | |||
* @param index the n-th MergedRegion | |||
* | |||
* | |||
* @return MergedRegion at the given index representing the area that is Merged (r1,c1 - r2,c2) | |||
*/ | |||
public CellRangeAddress getAreaAt(int index) { | |||
@@ -107,12 +118,15 @@ public final class MergeCellsRecord extends StandardRecord implements Cloneable | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public MergeCellsRecord clone() { | |||
int nRegions = _numberOfRegions; | |||
CellRangeAddress[] clonedRegions = new CellRangeAddress[nRegions]; | |||
for (int i = 0; i < clonedRegions.length; i++) { | |||
clonedRegions[i] = _regions[_startIndex + i].copy(); | |||
} | |||
return new MergeCellsRecord(clonedRegions, 0, nRegions); | |||
return copy(); | |||
} | |||
@Override | |||
public MergeCellsRecord copy() { | |||
return new MergeCellsRecord(this); | |||
} | |||
} |
@@ -18,17 +18,15 @@ | |||
package org.apache.poi.hssf.record; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.Removal; | |||
/** | |||
* Title: Multiple Blank cell record(0x00BE)<p> | |||
* Description: Represents a set of columns in a row with no value but with styling.<p> | |||
* Represents a set of columns in a row with no value but with styling. | |||
* | |||
* REFERENCE: PG 329 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) | |||
* | |||
* @see BlankRecord | |||
*/ | |||
public final class MulBlankRecord extends StandardRecord { | |||
public final static short sid = 0x00BE; | |||
public static final short sid = 0x00BE; | |||
private final int _row; | |||
private final int _firstCol; | |||
@@ -55,7 +53,7 @@ public final class MulBlankRecord extends StandardRecord { | |||
public int getFirstColumn() { | |||
return _firstCol; | |||
} | |||
/** | |||
* @return ending column (last cell this holds in the row). Zero based | |||
*/ | |||
@@ -122,8 +120,8 @@ public final class MulBlankRecord extends StandardRecord { | |||
out.writeShort(_row); | |||
out.writeShort(_firstCol); | |||
int nItems = _xfs.length; | |||
for (int i = 0; i < nItems; i++) { | |||
out.writeShort(_xfs[i]); | |||
for (short xf : _xfs) { | |||
out.writeShort(xf); | |||
} | |||
out.writeShort(_lastCol); | |||
} | |||
@@ -134,7 +132,15 @@ public final class MulBlankRecord extends StandardRecord { | |||
} | |||
@Override | |||
@SuppressWarnings("squid:S2975") | |||
@Deprecated | |||
@Removal(version = "5.0.0") | |||
public MulBlankRecord clone() { | |||
return copy(); | |||
} | |||
@Override | |||
public MulBlankRecord copy() { | |||
// immutable - so OK to return this | |||
return this; | |||
} |
@@ -23,18 +23,15 @@ import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.RecordFormatException; | |||
/** | |||
* MULRK (0x00BD)<p> | |||
* | |||
* Used to store multiple RK numbers on a row. 1 MulRk = Multiple Cell values. | |||
* HSSF just converts this into multiple NUMBER records. READ-ONLY SUPPORT!<P> | |||
* REFERENCE: PG 330 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) | |||
* | |||
* HSSF just converts this into multiple NUMBER records. READ-ONLY SUPPORT! | |||
* | |||
* @since 2.0-pre | |||
*/ | |||
public final class MulRKRecord extends StandardRecord { | |||
public final static short sid = 0x00BD; | |||
public static final short sid = 0x00BD; | |||
private final int field_1_row; | |||
private final int field_1_row; | |||
private final short field_2_first_col; | |||
private final RkRec[] field_3_rks; | |||
private final short field_4_last_col; | |||
@@ -69,9 +66,9 @@ public final class MulRKRecord extends StandardRecord { | |||
/** | |||
* returns the xf index for column (coffset = column - field_2_first_col) | |||
* | |||
* | |||
* @param coffset the coffset = column - field_2_first_col | |||
* | |||
* | |||
* @return the XF index for the column | |||
*/ | |||
public short getXFAt(int coffset) { | |||
@@ -80,9 +77,9 @@ public final class MulRKRecord extends StandardRecord { | |||
/** | |||
* returns the rk number for column (coffset = column - field_2_first_col) | |||
* | |||
* | |||
* @param coffset the coffset = column - field_2_first_col | |||
* | |||
* | |||
* @return the value (decoded into a double) | |||
*/ | |||
public double getRKNumberAt(int coffset) { | |||
@@ -151,4 +148,10 @@ public final class MulRKRecord extends StandardRecord { | |||
return retval; | |||
} | |||
} | |||
@Override | |||
public MulRKRecord copy() { | |||
// immutable - so OK to return this | |||
return this; | |||
} | |||
} |
@@ -18,145 +18,154 @@ | |||
package org.apache.poi.hssf.record; | |||
import org.apache.poi.util.HexDump; | |||
import org.apache.poi.util.LittleEndianInput; | |||
import org.apache.poi.util.LittleEndianOutput; | |||
import org.apache.poi.util.StringUtil; | |||
/** | |||
* Title: NAMECMT Record (0x0894)<p> | |||
* | |||
* Description: Defines a comment associated with a specified name. | |||
* Defines a comment associated with a specified name. | |||
*/ | |||
public final class NameCommentRecord extends StandardRecord { | |||
public final static short sid = 0x0894; | |||
private final short field_1_record_type; | |||
private final short field_2_frt_cell_ref_flag; | |||
private final long field_3_reserved; | |||
//private short field_4_name_length; | |||
//private short field_5_comment_length; | |||
private String field_6_name_text; | |||
private String field_7_comment_text; | |||
public NameCommentRecord(final String name, final String comment) { | |||
field_1_record_type = 0; | |||
field_2_frt_cell_ref_flag = 0; | |||
field_3_reserved = 0; | |||
field_6_name_text = name; | |||
field_7_comment_text = comment; | |||
} | |||
@Override | |||
public void serialize(final LittleEndianOutput out) { | |||
final int field_4_name_length = field_6_name_text.length(); | |||
final int field_5_comment_length = field_7_comment_text.length(); | |||
out.writeShort(field_1_record_type); | |||
out.writeShort(field_2_frt_cell_ref_flag); | |||
out.writeLong(field_3_reserved); | |||
out.writeShort(field_4_name_length); | |||
out.writeShort(field_5_comment_length); | |||
boolean isNameMultiByte = StringUtil.hasMultibyte(field_6_name_text); | |||
out.writeByte(isNameMultiByte ? 1 : 0); | |||
if (isNameMultiByte) { | |||
StringUtil.putUnicodeLE(field_6_name_text, out); | |||
} else { | |||
StringUtil.putCompressedUnicode(field_6_name_text, out); | |||
public static final short sid = 0x0894; | |||
private final short field_1_record_type; | |||
private final short field_2_frt_cell_ref_flag; | |||
private final long field_3_reserved; | |||
//private short field_4_name_length; | |||
//private short field_5_comment_length; | |||
private String field_6_name_text; | |||
private String field_7_comment_text; | |||
public NameCommentRecord(NameCommentRecord other) { | |||
field_1_record_type = other.field_1_record_type; | |||
field_2_frt_cell_ref_flag = other.field_2_frt_cell_ref_flag; | |||
field_3_reserved = other.field_3_reserved; | |||
field_6_name_text = other.field_6_name_text; | |||
field_7_comment_text = other.field_7_comment_text; | |||
} | |||
boolean isCommentMultiByte = StringUtil.hasMultibyte(field_7_comment_text); | |||
out.writeByte(isCommentMultiByte ? 1 : 0); | |||
if (isCommentMultiByte) { | |||
StringUtil.putUnicodeLE(field_7_comment_text, out); | |||
} else { | |||
StringUtil.putCompressedUnicode(field_7_comment_text, out); | |||
public NameCommentRecord(final String name, final String comment) { | |||
field_1_record_type = 0; | |||
field_2_frt_cell_ref_flag = 0; | |||
field_3_reserved = 0; | |||
field_6_name_text = name; | |||
field_7_comment_text = comment; | |||
} | |||
/** | |||
* @param ris the RecordInputstream to read the record from | |||
*/ | |||
public NameCommentRecord(final RecordInputStream ris) { | |||
field_1_record_type = ris.readShort(); | |||
field_2_frt_cell_ref_flag = ris.readShort(); | |||
field_3_reserved = ris.readLong(); | |||
final int field_4_name_length = ris.readShort(); | |||
final int field_5_comment_length = ris.readShort(); | |||
if (ris.readByte() == 0) { | |||
field_6_name_text = StringUtil.readCompressedUnicode(ris, field_4_name_length); | |||
} else { | |||
field_6_name_text = StringUtil.readUnicodeLE(ris, field_4_name_length); | |||
} | |||
if (ris.readByte() == 0) { | |||
field_7_comment_text = StringUtil.readCompressedUnicode(ris, field_5_comment_length); | |||
} else { | |||
field_7_comment_text = StringUtil.readUnicodeLE(ris, field_5_comment_length); | |||
} | |||
} | |||
} | |||
@Override | |||
protected int getDataSize() { | |||
return 18 // 4 shorts + 1 long + 2 spurious 'nul's | |||
+ (StringUtil.hasMultibyte(field_6_name_text) ? field_6_name_text.length()*2 : field_6_name_text.length()) | |||
+ (StringUtil.hasMultibyte(field_7_comment_text) ? field_7_comment_text.length()*2 : field_7_comment_text.length()); | |||
} | |||
/** | |||
* @param ris the RecordInputstream to read the record from | |||
*/ | |||
public NameCommentRecord(final RecordInputStream ris) { | |||
field_1_record_type = ris.readShort(); | |||
field_2_frt_cell_ref_flag = ris.readShort(); | |||
field_3_reserved = ris.readLong(); | |||
final int field_4_name_length = ris.readShort(); | |||
final int field_5_comment_length = ris.readShort(); | |||
if (ris.readByte() == 0) { | |||
field_6_name_text = StringUtil.readCompressedUnicode(ris, field_4_name_length); | |||
} else { | |||
field_6_name_text = StringUtil.readUnicodeLE(ris, field_4_name_length); | |||
@Override | |||
public void serialize(final LittleEndianOutput out) { | |||
final int field_4_name_length = field_6_name_text.length(); | |||
final int field_5_comment_length = field_7_comment_text.length(); | |||
out.writeShort(field_1_record_type); | |||
out.writeShort(field_2_frt_cell_ref_flag); | |||
out.writeLong(field_3_reserved); | |||
out.writeShort(field_4_name_length); | |||
out.writeShort(field_5_comment_length); | |||
boolean isNameMultiByte = StringUtil.hasMultibyte(field_6_name_text); | |||
out.writeByte(isNameMultiByte ? 1 : 0); | |||
if (isNameMultiByte) { | |||
StringUtil.putUnicodeLE(field_6_name_text, out); | |||
} else { | |||
StringUtil.putCompressedUnicode(field_6_name_text, out); | |||
} | |||
boolean isCommentMultiByte = StringUtil.hasMultibyte(field_7_comment_text); | |||
out.writeByte(isCommentMultiByte ? 1 : 0); | |||
if (isCommentMultiByte) { | |||
StringUtil.putUnicodeLE(field_7_comment_text, out); | |||
} else { | |||
StringUtil.putCompressedUnicode(field_7_comment_text, out); | |||
} | |||
} | |||
@Override | |||
protected int getDataSize() { | |||
return 18 // 4 shorts + 1 long + 2 spurious 'nul's | |||
+ (StringUtil.hasMultibyte(field_6_name_text) ? field_6_name_text.length() * 2 : field_6_name_text.length()) | |||
+ (StringUtil.hasMultibyte(field_7_comment_text) ? field_7_comment_text.length() * 2 : field_7_comment_text.length()); | |||
} | |||
if (ris.readByte() == 0) { | |||
field_7_comment_text = StringUtil.readCompressedUnicode(ris, field_5_comment_length); | |||
} else { | |||
field_7_comment_text = StringUtil.readUnicodeLE(ris, field_5_comment_length); | |||
} | |||
} | |||
/** | |||
* return the non static version of the id for this record. | |||
*/ | |||
@Override | |||
public short getSid() { | |||
return sid; | |||
} | |||
@Override | |||
public String toString() { | |||
final StringBuilder sb = new StringBuilder(); | |||
sb.append("[NAMECMT]\n"); | |||
sb.append(" .record type = ").append(HexDump.shortToHex(field_1_record_type)).append("\n"); | |||
sb.append(" .frt cell ref flag = ").append(HexDump.byteToHex(field_2_frt_cell_ref_flag)).append("\n"); | |||
sb.append(" .reserved = ").append(field_3_reserved).append("\n"); | |||
sb.append(" .name length = ").append(field_6_name_text.length()).append("\n"); | |||
sb.append(" .comment length = ").append(field_7_comment_text.length()).append("\n"); | |||
sb.append(" .name = ").append(field_6_name_text).append("\n"); | |||
sb.append(" .comment = ").append(field_7_comment_text).append("\n"); | |||
sb.append("[/NAMECMT]\n"); | |||
return sb.toString(); | |||
} | |||
/** | |||
* @return the name of the NameRecord to which this comment applies. | |||
*/ | |||
public String getNameText() { | |||
return field_6_name_text; | |||
} | |||
/** | |||
* Updates the name we're associated with, normally used | |||
* when renaming that Name | |||
* | |||
* @param newName the new name | |||
*/ | |||
public void setNameText(String newName) { | |||
field_6_name_text = newName; | |||
} | |||
/** | |||
* @return the text of the comment. | |||
*/ | |||
public String getCommentText() { | |||
return field_7_comment_text; | |||
} | |||
public void setCommentText(String comment) { | |||
field_7_comment_text = comment; | |||
} | |||
public short getRecordType() { | |||
return field_1_record_type; | |||
} | |||
/** | |||
* return the non static version of the id for this record. | |||
*/ | |||
@Override | |||
public short getSid() { | |||
return sid; | |||
} | |||
@Override | |||
public String toString() { | |||
final StringBuilder sb = new StringBuilder(); | |||
sb.append("[NAMECMT]\n"); | |||
sb.append(" .record type = ").append(HexDump.shortToHex(field_1_record_type)).append("\n"); | |||
sb.append(" .frt cell ref flag = ").append(HexDump.byteToHex(field_2_frt_cell_ref_flag)).append("\n"); | |||
sb.append(" .reserved = ").append(field_3_reserved).append("\n"); | |||
sb.append(" .name length = ").append(field_6_name_text.length()).append("\n"); | |||
sb.append(" .comment length = ").append(field_7_comment_text.length()).append("\n"); | |||
sb.append(" .name = ").append(field_6_name_text).append("\n"); | |||
sb.append(" .comment = ").append(field_7_comment_text).append("\n"); | |||
sb.append("[/NAMECMT]\n"); | |||
return sb.toString(); | |||
} | |||
/** | |||
* @return the name of the NameRecord to which this comment applies. | |||
*/ | |||
public String getNameText() { | |||
return field_6_name_text; | |||
} | |||
/** | |||
* Updates the name we're associated with, normally used | |||
* when renaming that Name | |||
* | |||
* @param newName the new name | |||
*/ | |||
public void setNameText(String newName) { | |||
field_6_name_text = newName; | |||
} | |||
/** | |||
* @return the text of the comment. | |||
*/ | |||
public String getCommentText() { | |||
return field_7_comment_text; | |||
} | |||
public void setCommentText(String comment) { | |||
field_7_comment_text = comment; | |||
} | |||
public short getRecordType() { | |||
return field_1_record_type; | |||
} | |||
@Override | |||
public NameCommentRecord copy() { | |||
return new NameCommentRecord(this); | |||
} | |||
} |
@@ -19,44 +19,46 @@ package org.apache.poi.hssf.record; | |||
import org.apache.poi.hssf.record.cont.ContinuableRecord; | |||
import org.apache.poi.hssf.record.cont.ContinuableRecordOutput; | |||
import org.apache.poi.ss.formula.Formula; | |||
import org.apache.poi.ss.formula.ptg.Area3DPtg; | |||
import org.apache.poi.ss.formula.ptg.Ptg; | |||
import org.apache.poi.ss.formula.ptg.Ref3DPtg; | |||
import org.apache.poi.ss.formula.Formula; | |||
import org.apache.poi.util.*; | |||
import org.apache.poi.util.HexDump; | |||
import org.apache.poi.util.LittleEndianByteArrayInputStream; | |||
import org.apache.poi.util.LittleEndianInput; | |||
import org.apache.poi.util.StringUtil; | |||
/** | |||
* Title: DEFINEDNAME Record (0x0018)<p> | |||
* Description: Defines a named range within a workbook. | |||
* Defines a named range within a workbook. | |||
*/ | |||
public final class NameRecord extends ContinuableRecord { | |||
public final static short sid = 0x0018; | |||
public static final short sid = 0x0018; | |||
/**Included for completeness sake, not implemented */ | |||
public final static byte BUILTIN_CONSOLIDATE_AREA = 1; | |||
public static final byte BUILTIN_CONSOLIDATE_AREA = 1; | |||
/**Included for completeness sake, not implemented */ | |||
public final static byte BUILTIN_AUTO_OPEN = 2; | |||
public static final byte BUILTIN_AUTO_OPEN = 2; | |||
/**Included for completeness sake, not implemented */ | |||
public final static byte BUILTIN_AUTO_CLOSE = 3; | |||
public static final byte BUILTIN_AUTO_CLOSE = 3; | |||
/**Included for completeness sake, not implemented */ | |||
public final static byte BUILTIN_DATABASE = 4; | |||
public static final byte BUILTIN_DATABASE = 4; | |||
/**Included for completeness sake, not implemented */ | |||
public final static byte BUILTIN_CRITERIA = 5; | |||
public static final byte BUILTIN_CRITERIA = 5; | |||
public final static byte BUILTIN_PRINT_AREA = 6; | |||
public final static byte BUILTIN_PRINT_TITLE = 7; | |||
public static final byte BUILTIN_PRINT_AREA = 6; | |||
public static final byte BUILTIN_PRINT_TITLE = 7; | |||
/**Included for completeness sake, not implemented */ | |||
public final static byte BUILTIN_RECORDER = 8; | |||
public static final byte BUILTIN_RECORDER = 8; | |||
/**Included for completeness sake, not implemented */ | |||
public final static byte BUILTIN_DATA_FORM = 9; | |||
public static final byte BUILTIN_DATA_FORM = 9; | |||
/**Included for completeness sake, not implemented */ | |||
public final static byte BUILTIN_AUTO_ACTIVATE = 10; | |||
public static final byte BUILTIN_AUTO_ACTIVATE = 10; | |||
/**Included for completeness sake, not implemented */ | |||
public final static byte BUILTIN_AUTO_DEACTIVATE = 11; | |||
public static final byte BUILTIN_AUTO_DEACTIVATE = 11; | |||
/**Included for completeness sake, not implemented */ | |||
public final static byte BUILTIN_SHEET_TITLE = 12; | |||
public static final byte BUILTIN_SHEET_TITLE = 12; | |||
public final static byte BUILTIN_FILTER_DB = 13; | |||
public static final byte BUILTIN_FILTER_DB = 13; | |||
private static final class Option { | |||
public static final int OPT_HIDDEN_NAME = 0x0001; | |||
@@ -98,10 +100,26 @@ public final class NameRecord extends ContinuableRecord { | |||
field_17_status_bar_text = ""; | |||
} | |||
public NameRecord(NameRecord other) { | |||
super(other); | |||
field_1_option_flag = other.field_1_option_flag; | |||
field_2_keyboard_shortcut = other.field_2_keyboard_shortcut; | |||
field_5_externSheetIndex_plus1 = other.field_5_externSheetIndex_plus1; | |||
field_6_sheetNumber = other.field_6_sheetNumber; | |||
field_11_nameIsMultibyte = other.field_11_nameIsMultibyte; | |||
field_12_built_in_code = other.field_12_built_in_code; | |||
field_12_name_text = other.field_12_name_text; | |||
field_13_name_definition = other.field_13_name_definition; | |||
field_14_custom_menu_text = other.field_14_custom_menu_text; | |||
field_15_description_text = other.field_15_description_text; | |||
field_16_help_topic_text = other.field_16_help_topic_text; | |||
field_17_status_bar_text = other.field_17_status_bar_text; | |||
} | |||
/** | |||
* Constructor to create a built-in named region | |||
* @param builtin Built-in byte representation for the name record, use the public constants | |||
* @param sheetNumber the sheet which the name applies to | |||
* @param sheetNumber the sheet which the name applies to | |||
*/ | |||
public NameRecord(byte builtin, int sheetNumber) | |||
{ | |||
@@ -276,7 +294,7 @@ public final class NameRecord extends ContinuableRecord { | |||
/** | |||
* Convenience Function to determine if the name is a built-in name | |||
* | |||
* | |||
* @return true, if the name is a built-in name | |||
*/ | |||
public boolean isBuiltInName() | |||
@@ -590,4 +608,9 @@ public final class NameRecord extends ContinuableRecord { | |||
return "Unknown"; | |||
} | |||
@Override | |||
public NameRecord copy() { | |||
return new NameRecord(this); | |||
} | |||
} |