#64004 - Replace clone() with copy constructor - mainly HSSF classes

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1871911 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Andreas Beeker 2019-12-22 21:44:45 +00:00
parent ecb42bd78d
commit ba6152503e
370 changed files with 8491 additions and 6213 deletions

View File

@ -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 * 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. * 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 * 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. * processing with it based on it's type.
* *
* The test is implemented as a junit {@link Parameterized} test, which leads * 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). * 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 * 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 * {@link FileHandler} which defines how the file is loaded and which actions are
* tried with the file. * tried with the file.
* *
* The test can be expanded by adding more actions to the FileHandlers, this automatically * 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. * applies the action to any such file in our test-data repository.
* *
* There is also a list of files that should actually fail. * 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, * 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 * 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. * 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. * that we do not remove expected sanity checks.
*/ */
@RunWith(Parameterized.class) @RunWith(Parameterized.class)
@ -96,7 +96,7 @@ public class TestAllFiles {
private static final Map<String,String> FILE_PASSWORD; private static final Map<String,String> FILE_PASSWORD;
// map file extensions to the actual mappers // map file extensions to the actual mappers
public static final Map<String, FileHandler> HANDLERS = new HashMap<>(); public static final Map<String, FileHandler> HANDLERS = new HashMap<>();
@ -136,7 +136,7 @@ public class TestAllFiles {
// Visio - binary // Visio - binary
HANDLERS.put(".vsd", IGNORE_SCRATCHPAD ? new HPSFFileHandler() : new HDGFFileHandler()); HANDLERS.put(".vsd", IGNORE_SCRATCHPAD ? new HPSFFileHandler() : new HDGFFileHandler());
// Visio - ooxml // Visio - ooxml
HANDLERS.put(".vsdm", new XDGFFileHandler()); HANDLERS.put(".vsdm", new XDGFFileHandler());
HANDLERS.put(".vsdx", 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/protected_agile.docx", Decryptor.DEFAULT_PASSWORD);
passmap.put("poifs/60320-protected.xlsx", "Test001!!"); passmap.put("poifs/60320-protected.xlsx", "Test001!!");
passmap.put("poifs/protected_sha512.xlsx", "this is a test"); passmap.put("poifs/protected_sha512.xlsx", "this is a test");
FILE_PASSWORD = Collections.unmodifiableMap(passmap); FILE_PASSWORD = Collections.unmodifiableMap(passmap);
} }
@ -326,7 +326,7 @@ public class TestAllFiles {
"spreadsheet/testEXCEL_95.xls", "spreadsheet/testEXCEL_95.xls",
"spreadsheet/59074.xls", "spreadsheet/59074.xls",
"spreadsheet/60284.xls", "spreadsheet/60284.xls",
// OOXML Strict is not yet supported, see bug #57699 // OOXML Strict is not yet supported, see bug #57699
"spreadsheet/SampleSS.strict.xlsx", "spreadsheet/SampleSS.strict.xlsx",
"spreadsheet/SimpleStrict.xlsx", "spreadsheet/SimpleStrict.xlsx",
@ -342,7 +342,7 @@ public class TestAllFiles {
// sheet cloning errors // sheet cloning errors
"spreadsheet/56450.xls", "spreadsheet/56450.xls",
"spreadsheet/OddStyleRecord.xls", // "spreadsheet/OddStyleRecord.xls",
// msg files with non-standard encodings // msg files with non-standard encodings
"hsmf/ASCII_CP1251_LCID1049.msg", "hsmf/ASCII_CP1251_LCID1049.msg",
@ -377,7 +377,7 @@ public class TestAllFiles {
} }
FileHandler handler = HANDLERS.get(getExtension(file)); FileHandler handler = HANDLERS.get(getExtension(file));
files.add(new Object[] { file, handler }); files.add(new Object[] { file, handler });
// for some file-types also run OPCFileHandler // for some file-types also run OPCFileHandler
if(handler instanceof XSSFFileHandler || if(handler instanceof XSSFFileHandler ||
handler instanceof XWPFFileHandler || handler instanceof XWPFFileHandler ||
@ -385,7 +385,7 @@ public class TestAllFiles {
handler instanceof XDGFFileHandler) { handler instanceof XDGFFileHandler) {
files.add(new Object[] { file, new OPCFileHandler() }); files.add(new Object[] { file, new OPCFileHandler() });
} }
if (handler instanceof HSSFFileHandler || if (handler instanceof HSSFFileHandler ||
handler instanceof HSLFFileHandler || handler instanceof HSLFFileHandler ||
handler instanceof HWPFFileHandler || handler instanceof HWPFFileHandler ||
@ -410,7 +410,7 @@ public class TestAllFiles {
String pass = TestAllFiles.FILE_PASSWORD.get(file); String pass = TestAllFiles.FILE_PASSWORD.get(file);
Biff8EncryptionKey.setCurrentUserPassword(pass); Biff8EncryptionKey.setCurrentUserPassword(pass);
} }
@Test @Test
public void testAllFiles() throws Exception { public void testAllFiles() throws Exception {
if(handler == null) { if(handler == null) {
@ -426,7 +426,7 @@ public class TestAllFiles {
file.endsWith(".xlsb") || file.endsWith(".pptx")) && file.endsWith(".xlsb") || file.endsWith(".pptx")) &&
handler instanceof OPCFileHandler; handler instanceof OPCFileHandler;
boolean ignoreHPSF = (handler instanceof HPSFFileHandler); boolean ignoreHPSF = (handler instanceof HPSFFileHandler);
try { try {
try (InputStream stream = new BufferedInputStream(new FileInputStream(inputFile), 64 * 1024)) { try (InputStream stream = new BufferedInputStream(new FileInputStream(inputFile), 64 * 1024)) {
handler.handleFile(stream, file); handler.handleFile(stream, file);
@ -436,7 +436,7 @@ public class TestAllFiles {
handler.handleExtracting(inputFile); 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); EXPECTED_FAILURES.contains(file) && !ignoredOPC && !ignoreHPSF);
} catch (OldFileFormatException e) { } catch (OldFileFormatException e) {
// for old word files we should still support extracting text // for old word files we should still support extracting text

View File

@ -28,14 +28,14 @@ import org.apache.poi.hssf.record.Record;
import org.junit.Test; 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() * HSSFWorkbook.getWorkbook()
*/ */
public class RecordsStresser { public class RecordsStresser {
public static void handleWorkbook(HSSFWorkbook wb) { public static void handleWorkbook(HSSFWorkbook wb) {
List<Record> records = wb.getWorkbook().getRecords(); List<Record> records = wb.getWorkbook().getRecords();
for(Record record : records) { 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 // 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) || // if(record.getClass().equals(InterfaceHdrRecord.class) ||
// record.getClass().equals(MMSRecord.class) || // record.getClass().equals(MMSRecord.class) ||
@ -46,18 +46,16 @@ public class RecordsStresser {
// continue; // continue;
// } // }
try { try {
Record newRecord = (Record) record.clone(); 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()", 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.getClass(), newRecord.getClass());
byte[] origBytes = record.serialize(); byte[] origBytes = record.serialize();
byte[] newBytes = newRecord.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); origBytes, newBytes);
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
} catch (RuntimeException e) { } catch (RuntimeException e) {
// some Records do not implement clone, ignore those for now // some Records do not implement clone, ignore those for now
assertTrue(e.getMessage().contains("needs to define a clone method")); assertTrue(e.getMessage().contains("needs to define a clone method"));

View File

@ -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();
}

View File

@ -171,7 +171,4 @@ public abstract class AbstractEscherOptRecord extends EscherRecord {
"properties", this::getEscherProperties "properties", this::getEscherProperties
); );
} }
@Override
public abstract AbstractEscherOptRecord copy();
} }

View File

@ -142,13 +142,9 @@ public final class EscherContainerRecord extends EscherRecord implements Iterabl
* @return true, if any child has the given recordId * @return true, if any child has the given recordId
*/ */
public boolean hasChildOfType(short recordId) { public boolean hasChildOfType(short recordId) {
for (EscherRecord r : this) { return _childRecords.stream().anyMatch(r -> r.getRecordId() == recordId);
if(r.getRecordId() == recordId) {
return true;
}
}
return false;
} }
@Override @Override
public EscherRecord getChild( int index ) { public EscherRecord getChild( int index ) {
return _childRecords.get(index); return _childRecords.get(index);
@ -170,6 +166,7 @@ public final class EscherContainerRecord extends EscherRecord implements Iterabl
return Collections.unmodifiableList(_childRecords).iterator(); return Collections.unmodifiableList(_childRecords).iterator();
} }
/** /**
* replaces the internal child list with the contents of the supplied <tt>childRecords</tt> * replaces the internal child list with the contents of the supplied <tt>childRecords</tt>
*/ */

View File

@ -24,6 +24,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.Supplier; import java.util.function.Supplier;
import org.apache.poi.common.Duplicatable;
import org.apache.poi.common.usermodel.GenericRecord; import org.apache.poi.common.usermodel.GenericRecord;
import org.apache.poi.util.BitField; import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory; 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.GenericRecordXmlWriter;
import org.apache.poi.util.Internal; import org.apache.poi.util.Internal;
import org.apache.poi.util.LittleEndian; 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 * 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. * 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 fInstance = BitFieldFactory.getInstance(0xfff0);
private static final BitField fVersion = BitFieldFactory.getInstance(0x000f); 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. * Escher records may need to be clonable in the future.
* *
* @return the cloned object * @return the cloned object
* @deprecated use {@link #copy()}
*/ */
@Override @Override
@SuppressWarnings("squid:S2975") @SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public final EscherRecord clone() { public final EscherRecord clone() {
return copy(); return copy();
} }
@ -350,5 +355,6 @@ public abstract class EscherRecord implements Cloneable, GenericRecord {
); );
} }
@Override
public abstract EscherRecord copy(); public abstract EscherRecord copy();
} }

View File

@ -31,7 +31,7 @@ import org.apache.poi.util.RecordFormatException;
* Escher format. We don't attempt to understand the contents, since * Escher format. We don't attempt to understand the contents, since
* they will be in the parent's format, not Escher format. * 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 //arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000; private static final int MAX_RECORD_LENGTH = 100_000;

View File

@ -31,7 +31,7 @@ import org.apache.poi.util.LittleEndian;
* This record is used whenever a escher record is encountered that * This record is used whenever a escher record is encountered that
* we do not explicitly support. * 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 //arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000_000; private static final int MAX_RECORD_LENGTH = 100_000_000;

View File

@ -23,11 +23,9 @@ import org.apache.poi.util.RecordFormatException;
/** /**
*/ */
abstract class DummyRecordBase extends Record { abstract class DummyRecordBase extends Record {
protected DummyRecordBase() { protected DummyRecordBase() {}
//
}
public final short getSid() { public final short getSid() {
return -1; return -1;
} }

View File

@ -25,37 +25,42 @@ package org.apache.poi.hssf.eventusermodel.dummyrecord;
public final class LastCellOfRowDummyRecord extends DummyRecordBase { public final class LastCellOfRowDummyRecord extends DummyRecordBase {
private final int row; private final int row;
private final int lastColumnNumber; private final int lastColumnNumber;
public LastCellOfRowDummyRecord(int row, int lastColumnNumber) { public LastCellOfRowDummyRecord(int row, int lastColumnNumber) {
this.row = row; this.row = row;
this.lastColumnNumber = lastColumnNumber; this.lastColumnNumber = lastColumnNumber;
} }
/** /**
* Returns the (0 based) number of the row we are * Returns the (0 based) number of the row we are
* currently working on. * currently working on.
* *
* @return the (0 based) number of the row * @return the (0 based) number of the row
*/ */
public int getRow() { public int getRow() {
return row; return row;
} }
/** /**
* Returns the (0 based) number of the last column * Returns the (0 based) number of the last column
* seen for this row. You should have already been * seen for this row. You should have already been
* called with that record. * called with that record.
* This is -1 in the case of there being no columns * This is -1 in the case of there being no columns
* for the row. * for the row.
* *
* @return the (0 based) number of the last column * @return the (0 based) number of the last column
*/ */
public int getLastColumnNumber() { public int getLastColumnNumber() {
return lastColumnNumber; return lastColumnNumber;
} }
@Override @Override
public String toString() { public String toString() {
return "End-of-Row for Row=" + row + " at Column=" + lastColumnNumber; return "End-of-Row for Row=" + row + " at Column=" + lastColumnNumber;
} }
@Override
public LastCellOfRowDummyRecord copy() {
return this;
}
} }

View File

@ -23,13 +23,18 @@ package org.apache.poi.hssf.eventusermodel.dummyrecord;
* but still want to trigger something * but still want to trigger something
*/ */
public final class MissingCellDummyRecord extends DummyRecordBase { public final class MissingCellDummyRecord extends DummyRecordBase {
private int row; private final int row;
private int column; private final int column;
public MissingCellDummyRecord(int row, int column) { public MissingCellDummyRecord(int row, int column) {
this.row = row; this.row = row;
this.column = column; this.column = column;
} }
public int getRow() { return row; } public int getRow() { return row; }
public int getColumn() { return column; } public int getColumn() { return column; }
@Override
public MissingCellDummyRecord copy() {
return this;
}
} }

View File

@ -23,12 +23,17 @@ package org.apache.poi.hssf.eventusermodel.dummyrecord;
* want to trigger something * want to trigger something
*/ */
public final class MissingRowDummyRecord extends DummyRecordBase { public final class MissingRowDummyRecord extends DummyRecordBase {
private int rowNumber; private final int rowNumber;
public MissingRowDummyRecord(int rowNumber) { public MissingRowDummyRecord(int rowNumber) {
this.rowNumber = rowNumber; this.rowNumber = rowNumber;
} }
public int getRowNumber() { public int getRowNumber() {
return rowNumber; return rowNumber;
} }
@Override
public MissingRowDummyRecord copy() {
return this;
}
} }

View File

@ -132,7 +132,7 @@ public final class InternalSheet {
if (rs.peekNextSid() != BOFRecord.sid) { if (rs.peekNextSid() != BOFRecord.sid) {
throw new RecordFormatException("BOF record expected"); throw new RecordFormatException("BOF record expected");
} }
BOFRecord bof = (BOFRecord) rs.getNext(); BOFRecord bof = (BOFRecord) rs.getNext();
if (bof.getType() == BOFRecord.TYPE_WORKSHEET) { if (bof.getType() == BOFRecord.TYPE_WORKSHEET) {
// Good, well supported // Good, well supported
@ -152,7 +152,7 @@ public final class InternalSheet {
throw new UnsupportedBOFType(bof.getType()); throw new UnsupportedBOFType(bof.getType());
} }
records.add(bof); records.add(bof);
while (rs.hasNext()) { while (rs.hasNext()) {
int recSid = rs.peekNextSid(); int recSid = rs.peekNextSid();
@ -339,14 +339,14 @@ public final class InternalSheet {
recs.add(r); recs.add(r);
}}); }});
} }
public static class UnsupportedBOFType extends RecordFormatException { public static class UnsupportedBOFType extends RecordFormatException {
private final int type; private final int type;
protected UnsupportedBOFType(int type) { protected UnsupportedBOFType(int type) {
super("BOF not of a supported type, found " + type); super("BOF not of a supported type, found " + type);
this.type = type; this.type = type;
} }
public int getType() { public int getType() {
return type; return type;
} }
@ -360,11 +360,7 @@ public final class InternalSheet {
_destList = destList; _destList = destList;
} }
public void visitRecord(Record r) { public void visitRecord(Record r) {
try { _destList.add(r.copy());
_destList.add((Record)r.clone());
} catch (CloneNotSupportedException e) {
throw new RecordFormatException(e);
}
} }
} }
@ -374,7 +370,7 @@ public final class InternalSheet {
* can be added to a sheet. The <b>Record</b> object does not implement cloneable. * 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 * When adding a new record, implement a public clone method if and only if the record
* belongs to a sheet. * belongs to a sheet.
* *
* @return the cloned sheet * @return the cloned sheet
*/ */
public InternalSheet cloneSheet() { public InternalSheet cloneSheet() {
@ -391,12 +387,8 @@ public final class InternalSheet {
*/ */
rb = new DrawingRecord(); rb = new DrawingRecord();
} }
try { Record rec = ((Record) rb).copy();
Record rec = (Record) ((Record) rb).clone(); clonedRecords.add(rec);
clonedRecords.add(rec);
} catch (CloneNotSupportedException e) {
throw new RecordFormatException(e);
}
} }
return createSheet(new RecordStream(clonedRecords, 0)); 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 * Updates formulas in cells and conditional formats due to moving of cells
* *
* @param shifter the formular shifter * @param shifter the formular shifter
* @param externSheetIndex the externSheet index of this sheet * @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) * set the default row height for the sheet (if the rows do not define their own height)
* *
* @param dch the default row height * @param dch the default row height
*/ */
public void setDefaultRowHeight(short dch) { public void setDefaultRowHeight(short dch) {
@ -1247,7 +1239,7 @@ public final class InternalSheet {
/** /**
* Gets the gridset record for this sheet. * Gets the gridset record for this sheet.
* *
* @return the gridset record for this sheet * @return the gridset record for this sheet
*/ */
public GridsetRecord getGridsetRecord() public GridsetRecord getGridsetRecord()
@ -1257,9 +1249,9 @@ public final class InternalSheet {
/** /**
* Returns the first occurrence of a record matching a particular sid. * Returns the first occurrence of a record matching a particular sid.
* *
* @param sid the sid to search for * @param sid the sid to search for
* *
* @return the matching record or {@code null} if it wasn't found * @return the matching record or {@code null} if it wasn't found
*/ */
public Record findFirstRecordBySid(short sid) { public Record findFirstRecordBySid(short sid) {
@ -1330,7 +1322,7 @@ public final class InternalSheet {
{ {
printGridlines = newPrintGridlines; printGridlines = newPrintGridlines;
} }
/** /**
* Returns the PrintHeadersRecord. * Returns the PrintHeadersRecord.
* @return PrintHeadersRecord for the sheet. * @return PrintHeadersRecord for the sheet.
@ -1519,7 +1511,7 @@ public final class InternalSheet {
public boolean isDisplayRowColHeadings() { public boolean isDisplayRowColHeadings() {
return windowTwo.getDisplayRowColHeadings(); return windowTwo.getDisplayRowColHeadings();
} }
/** /**
* Sets whether the RowColHeadings are shown in a viewer. * Sets whether the RowColHeadings are shown in a viewer.
* @param show whether to show RowColHeadings or not * @param show whether to show RowColHeadings or not
@ -1681,7 +1673,7 @@ public final class InternalSheet {
temp.toArray(result); temp.toArray(result);
return result; return result;
} }
public int getColumnOutlineLevel(int columnIndex) { public int getColumnOutlineLevel(int columnIndex) {
return _columnInfos.getOutlineLevel(columnIndex); return _columnInfos.getOutlineLevel(columnIndex);
} }

View File

@ -32,7 +32,7 @@ public final class RecordStream {
/** /**
* Creates a RecordStream bounded by startIndex and endIndex * Creates a RecordStream bounded by startIndex and endIndex
* *
* @param inputList the list to iterate over * @param inputList the list to iterate over
* @param startIndex the start index within the list * @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 * @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 _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 * @return -1 if at end of records
*/ */

View File

@ -25,14 +25,15 @@ import org.apache.poi.ddf.EscherContainerRecord;
import org.apache.poi.ddf.EscherRecord; import org.apache.poi.ddf.EscherRecord;
import org.apache.poi.ddf.EscherRecordFactory; import org.apache.poi.ddf.EscherRecordFactory;
import org.apache.poi.ddf.NullEscherSerializationListener; import org.apache.poi.ddf.NullEscherSerializationListener;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.hssf.util.LazilyConcatenatedByteArray; 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 * The escher container record is used to hold escher records. It is abstract and
* must be subclassed for maximum benefit. * must be subclassed for maximum benefit.
*/ */
public abstract class AbstractEscherHolderRecord extends Record implements Cloneable { public abstract class AbstractEscherHolderRecord extends Record {
private static boolean DESERIALISE; private static boolean DESERIALISE;
static { static {
try { 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(); private final LazilyConcatenatedByteArray rawDataContainer = new LazilyConcatenatedByteArray();
public AbstractEscherHolderRecord() public AbstractEscherHolderRecord() {}
{
escherRecords = new ArrayList<>(); public AbstractEscherHolderRecord(AbstractEscherHolderRecord other) {
other.escherRecords.stream().map(EscherRecord::copy).forEach(escherRecords::add);
rawDataContainer.concatenate(other.rawDataContainer);
} }
public AbstractEscherHolderRecord(RecordInputStream in) public AbstractEscherHolderRecord(RecordInputStream in) {
{
escherRecords = new ArrayList<>();
if (! DESERIALISE ) { if (! DESERIALISE ) {
rawDataContainer.concatenate(in.readRemainder()); rawDataContainer.concatenate(in.readRemainder());
} else { } else {
@ -143,10 +144,16 @@ public abstract class AbstractEscherHolderRecord extends Record implements Clone
public abstract short getSid(); public abstract short getSid();
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public AbstractEscherHolderRecord clone() { public AbstractEscherHolderRecord clone() {
return (AbstractEscherHolderRecord)cloneViaReserialise(); return copy();
} }
@Override
public abstract AbstractEscherHolderRecord copy();
public void addEscherRecord(int index, EscherRecord element) public void addEscherRecord(int index, EscherRecord element)
{ {
escherRecords.add( index, 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 * If we have a EscherContainerRecord as one of our
* children (and most top level escher holders do), * children (and most top level escher holders do),
* then return that. * then return that.
* *
* @return the EscherContainerRecord or {@code null} if no child is a container record * @return the EscherContainerRecord or {@code null} if no child is a container record
*/ */
public EscherContainerRecord getEscherContainer() { public EscherContainerRecord getEscherContainer() {
@ -187,15 +194,15 @@ public abstract class AbstractEscherHolderRecord extends Record implements Clone
* Descends into all our children, returning the * Descends into all our children, returning the
* first EscherRecord with the given id, or null * first EscherRecord with the given id, or null
* if none found * if none found
* *
* @param id the record to look for * @param id the record to look for
* *
* @return the record or {@code null} if it can't be found * @return the record or {@code null} if it can't be found
*/ */
public EscherRecord findFirstWithId(short id) { public EscherRecord findFirstWithId(short id) {
return findFirstWithId(id, getEscherRecords()); return findFirstWithId(id, getEscherRecords());
} }
private EscherRecord findFirstWithId(short id, List<EscherRecord> records) { private EscherRecord findFirstWithId(short id, List<EscherRecord> records) {
// Check at our level // Check at our level
for (EscherRecord r : records) { 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 * 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. * as a whole group so we need to join them together.
* *
* @param record the record data to concatenate to the end * @param record the record data to concatenate to the end
*/ */
public void join( AbstractEscherHolderRecord record ) public void join( AbstractEscherHolderRecord record )

View File

@ -17,18 +17,19 @@
package org.apache.poi.hssf.record; 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.hssf.util.CellRangeAddress8Bit;
import org.apache.poi.ss.formula.Formula; 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.HexDump;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.Removal;
/** /**
* ARRAY (0x0221)<p> * ARRAY (0x0221)<p>
* *
* Treated in a similar way to SharedFormulaRecord * 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; public final static short sid = 0x0221;
private static final int OPT_ALWAYS_RECALCULATE = 0x0001; private static final int OPT_ALWAYS_RECALCULATE = 0x0001;
@ -38,6 +39,13 @@ public final class ArrayRecord extends SharedValueRecordBase implements Cloneabl
private int _field3notUsed; private int _field3notUsed;
private Formula _formula; 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) { public ArrayRecord(RecordInputStream in) {
super(in); super(in);
_options = in.readUShort(); _options = in.readUShort();
@ -92,16 +100,18 @@ public final class ArrayRecord extends SharedValueRecordBase implements Cloneabl
} }
sb.append("]"); sb.append("]");
return sb.toString(); return sb.toString();
} }
@Override @Override
public ArrayRecord clone() { @SuppressWarnings("squid:S2975")
ArrayRecord rec = new ArrayRecord(_formula.copy(), getRange()); @Deprecated
@Removal(version = "5.0.0")
public ArrayRecord clone() {
return copy();
}
// they both seem unused, but clone them nevertheless to have an exact copy @Override
rec._options = _options; public ArrayRecord copy() {
rec._field3notUsed = _field3notUsed; return new ArrayRecord(this);
return rec;
} }
} }

View File

@ -20,27 +20,28 @@
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.Removal;
/** /**
* The AutoFilterInfo record specifies the number of columns that have AutoFilter enabled * The AutoFilterInfo record specifies the number of columns that have AutoFilter enabled
* and indicates the beginning of the collection of AutoFilter records. * and indicates the beginning of the collection of AutoFilter records.
*
* @author Yegor Kozlov
*/ */
public final class AutoFilterInfoRecord extends StandardRecord implements Cloneable { public final class AutoFilterInfoRecord extends StandardRecord {
public final static short sid = 0x9D; public static final short sid = 0x9D;
/** /**
* Number of AutoFilter drop-down arrows on the sheet * 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(); _cEntries = in.readShort();
} }
@ -91,9 +92,15 @@ public final class AutoFilterInfoRecord extends StandardRecord implements Clonea
} }
@Override @Override
public AutoFilterInfoRecord clone() @SuppressWarnings("squid:S2975")
{ @Deprecated
return (AutoFilterInfoRecord)cloneViaReserialise(); @Removal(version = "5.0.0")
public AutoFilterInfoRecord clone() {
return copy();
}
@Override
public AutoFilterInfoRecord copy() {
return new AutoFilterInfoRecord(this);
} }
} }

View File

@ -19,44 +19,40 @@ package org.apache.poi.hssf.record;
import org.apache.poi.util.HexDump; import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.Removal;
/** /**
* Title: Beginning Of File (0x0809)<P> * Somewhat of a misnomer, its used for the beginning of a set of records that
* Description: Somewhat of a misnomer, its used for the beginning of a set of * have a particular purpose or subject. Used in sheets and workbooks.
* 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)
*/ */
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 * 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} * {@link #biff5_sid}
*/ */
public final static short sid = 0x809; public static final short sid = 0x809;
// SIDs from earlier BIFF versions // SIDs from earlier BIFF versions
public final static short biff2_sid = 0x009; public static final short biff2_sid = 0x009;
public final static short biff3_sid = 0x209; public static final short biff3_sid = 0x209;
public final static short biff4_sid = 0x409; public static final short biff4_sid = 0x409;
public final static short biff5_sid = 0x809; public static final short biff5_sid = 0x809;
/** suggested default (0x0600 - BIFF8) */ /** suggested default (0x0600 - BIFF8) */
public final static int VERSION = 0x0600; public static final int VERSION = 0x0600;
/** suggested default 0x10d3 */ /** suggested default 0x10d3 */
public final static int BUILD = 0x10d3; public static final int BUILD = 0x10d3;
/** suggested default 0x07CC (1996) */ /** 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) */ /** 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 static final int TYPE_WORKBOOK = 0x05;
public final static int TYPE_VB_MODULE = 0x06; public static final int TYPE_VB_MODULE = 0x06;
public final static int TYPE_WORKSHEET = 0x10; public static final int TYPE_WORKSHEET = 0x10;
public final static int TYPE_CHART = 0x20; public static final int TYPE_CHART = 0x20;
public final static int TYPE_EXCEL_4_MACRO = 0x40; public static final int TYPE_EXCEL_4_MACRO = 0x40;
public final static int TYPE_WORKSPACE_FILE = 0x100; public static final int TYPE_WORKSPACE_FILE = 0x100;
private int field_1_version; private int field_1_version;
private int field_2_type; 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. * 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) { private BOFRecord(int type) {
field_1_version = VERSION; field_1_version = VERSION;
field_2_type = type; field_2_type = type;
@ -79,7 +84,7 @@ public final class BOFRecord extends StandardRecord implements Cloneable {
field_5_history = 0x01; field_5_history = 0x01;
field_6_rversion = VERSION; field_6_rversion = VERSION;
} }
public static BOFRecord createSheetBOF() { public static BOFRecord createSheetBOF() {
return new BOFRecord(TYPE_WORKSHEET); return new BOFRecord(TYPE_WORKSHEET);
} }
@ -269,14 +274,15 @@ public final class BOFRecord extends StandardRecord implements Cloneable {
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public BOFRecord clone() { public BOFRecord clone() {
BOFRecord rec = new BOFRecord(); return copy();
rec.field_1_version = field_1_version; }
rec.field_2_type = field_2_type;
rec.field_3_build = field_3_build; @Override
rec.field_4_year = field_4_year; public BOFRecord copy() {
rec.field_5_history = field_5_history; return new BOFRecord(this);
rec.field_6_rversion = field_6_rversion;
return rec;
} }
} }

View File

@ -15,33 +15,31 @@
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
==================================================================== */ ==================================================================== */
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
/** /**
* Title: Backup Record <P> * Boolean specifying whether the GUI should store a backup of the file.
* 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)
* @version 2.0-pre * @version 2.0-pre
*/ */
public final class BackupRecord public final class BackupRecord extends StandardRecord {
extends StandardRecord public static final short sid = 0x40;
{
public final static short sid = 0x40;
private short field_1_backup; // = 0;
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(); field_1_backup = in.readShort();
} }
@ -90,4 +88,9 @@ public final class BackupRecord
{ {
return sid; return sid;
} }
@Override
public BackupRecord copy() {
return new BackupRecord(this);
}
} }

View File

@ -19,28 +19,32 @@ package org.apache.poi.hssf.record;
import org.apache.poi.util.HexDump; import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.Removal;
/** /**
* Title: Blank cell record (0x0201) <P> * Represents a column in a row with no value but with styling.
* 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)
* @version 2.0-pre * @version 2.0-pre
*/ */
public final class BlankRecord extends StandardRecord implements CellValueRecordInterface, Cloneable { public final class BlankRecord extends StandardRecord implements CellValueRecordInterface {
public final static short sid = 0x0201; public static final short sid = 0x0201;
private int field_1_row;
private short field_2_col; private int field_1_row;
private short field_3_xf; private short field_2_col;
private short field_3_xf;
/** Creates a new instance of BlankRecord */ /** 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_1_row = in.readUShort();
field_2_col = in.readShort(); field_2_col = in.readShort();
field_3_xf = in.readShort(); field_3_xf = in.readShort();
@ -138,11 +142,15 @@ public final class BlankRecord extends StandardRecord implements CellValueRecord
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public BlankRecord clone() { public BlankRecord clone() {
BlankRecord rec = new BlankRecord(); return copy();
rec.field_1_row = field_1_row; }
rec.field_2_col = field_2_col;
rec.field_3_xf = field_3_xf; @Override
return rec; public BlankRecord copy() {
return new BlankRecord(this);
} }
} }

View File

@ -15,33 +15,31 @@
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
==================================================================== */ ==================================================================== */
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
/** /**
* Title: Save External Links record (BookBool)<P> * Contains a flag specifying whether the Gui should save externally linked values from other workbooks.
* 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)
* @version 2.0-pre * @version 2.0-pre
*/ */
public final class BookBoolRecord public final class BookBoolRecord extends StandardRecord {
extends StandardRecord public static final short sid = 0xDA;
{
public final static short sid = 0xDA;
private short field_1_save_link_values;
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(); field_1_save_link_values = in.readShort();
} }
@ -90,4 +88,9 @@ public final class BookBoolRecord
{ {
return sid; return sid;
} }
@Override
public BookBoolRecord copy() {
return new BookBoolRecord(this);
}
} }

View File

@ -21,24 +21,27 @@ import org.apache.poi.ss.usermodel.FormulaError;
import org.apache.poi.util.HexDump; import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.RecordFormatException; import org.apache.poi.util.RecordFormatException;
import org.apache.poi.util.Removal;
/** /**
* Creates new BoolErrRecord. (0x0205) <P> * Creates new BoolErrRecord. (0x0205)
* 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)
*/ */
public final class BoolErrRecord extends CellRecord implements Cloneable { public final class BoolErrRecord extends CellRecord {
public final static short sid = 0x0205; public static final short sid = 0x0205;
private int _value; 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; private boolean _isError;
/** Creates new BoolErrRecord */ /** Creates new BoolErrRecord */
public BoolErrRecord() { public BoolErrRecord() {}
// fields uninitialised
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 @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public BoolErrRecord clone() { public BoolErrRecord clone() {
BoolErrRecord rec = new BoolErrRecord(); return copy();
copyBaseFields(rec); }
rec._value = _value;
rec._isError = _isError; @Override
return rec; public BoolErrRecord copy() {
return new BoolErrRecord(this);
} }
} }

View File

@ -20,22 +20,24 @@ package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.Removal;
/** /**
* Record for the bottom margin. * Record for the bottom margin.
*/ */
public final class BottomMarginRecord extends StandardRecord implements Margin, Cloneable { public final class BottomMarginRecord extends StandardRecord implements Margin {
public final static short sid = 0x29; public static final short sid = 0x29;
private double field_1_margin; 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(); field_1_margin = in.readDouble();
} }
@ -79,10 +81,15 @@ public final class BottomMarginRecord extends StandardRecord implements Margin,
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public BottomMarginRecord clone() { public BottomMarginRecord clone() {
BottomMarginRecord rec = new BottomMarginRecord(); return copy();
rec.field_1_margin = this.field_1_margin;
return rec;
} }
} // END OF @Override
public BottomMarginRecord copy() {
return new BottomMarginRecord(this);
}
}

View File

@ -18,9 +18,9 @@
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import java.util.Arrays; import java.util.Arrays;
import java.util.Comparator;
import java.util.List; import java.util.List;
import org.apache.poi.ss.util.WorkbookUtil;
import org.apache.poi.util.BitField; import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.BitFieldFactory;
import org.apache.poi.util.HexDump; 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.LittleEndianConsts;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.StringUtil; import org.apache.poi.util.StringUtil;
import org.apache.poi.ss.util.WorkbookUtil;
/** /**
* Title: Bound Sheet Record (aka BundleSheet) (0x0085)<P> * Defines a sheet within a workbook. Basically stores the sheet name and
* Description: Defines a sheet within a workbook. Basically stores the sheet name * tells where the Beginning of file record is within the HSSF file.
* 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)
*/ */
public final class BoundSheetRecord extends StandardRecord { 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 hiddenFlag = BitFieldFactory.getInstance(0x01);
private static final BitField veryHiddenFlag = BitFieldFactory.getInstance(0x02); private static final BitField veryHiddenFlag = BitFieldFactory.getInstance(0x02);
private int field_1_position_of_BOF; private int field_1_position_of_BOF;
private int field_2_option_flags; private int field_2_option_flags;
private int field_4_isMultibyteUnicode; private int field_4_isMultibyteUnicode;
@ -52,13 +48,21 @@ public final class BoundSheetRecord extends StandardRecord {
setSheetname(sheetname); 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 + * UTF8: sid + len + bof + flags + len(str) + unicode + str 2 + 2 + 4 + 2 +
* 1 + 1 + len(str) * 1 + 1 + len(str)
* *
* UNICODE: sid + len + bof + flags + len(str) + unicode + str 2 + 2 + 4 + 2 + * UNICODE: sid + len + bof + flags + len(str) + unicode + str 2 + 2 + 4 + 2 +
* 1 + 1 + 2 * len(str) * 1 + 1 + 2 * len(str)
* *
* @param in the record stream to read from * @param in the record stream to read from
*/ */
public BoundSheetRecord(RecordInputStream in) { public BoundSheetRecord(RecordInputStream in) {
@ -158,7 +162,7 @@ public final class BoundSheetRecord extends StandardRecord {
/** /**
* Is the sheet hidden? Different from very hidden * Is the sheet hidden? Different from very hidden
* *
* @return {@code true} if hidden * @return {@code true} if hidden
*/ */
public boolean isHidden() { public boolean isHidden() {
@ -167,7 +171,7 @@ public final class BoundSheetRecord extends StandardRecord {
/** /**
* Is the sheet hidden? Different from very hidden * Is the sheet hidden? Different from very hidden
* *
* @param hidden {@code true} if hidden * @param hidden {@code true} if hidden
*/ */
public void setHidden(boolean 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 * Is the sheet very hidden? Different from (normal) hidden
* *
* @return {@code true} if very hidden * @return {@code true} if very hidden
*/ */
public boolean isVeryHidden() { public boolean isVeryHidden() {
@ -185,7 +189,7 @@ public final class BoundSheetRecord extends StandardRecord {
/** /**
* Is the sheet very hidden? Different from (normal) hidden * Is the sheet very hidden? Different from (normal) hidden
* *
* @param veryHidden {@code true} if very hidden * @param veryHidden {@code true} if very hidden
*/ */
public void setVeryHidden(boolean veryHidden) { 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 * Converts a List of {@link BoundSheetRecord}s to an array and sorts by the position of their
* BOFs. * BOFs.
* *
* @param boundSheetRecords the boundSheetRecord list to arrayify * @param boundSheetRecords the boundSheetRecord list to arrayify
* *
* @return the sorted boundSheetRecords * @return the sorted boundSheetRecords
*/ */
public static BoundSheetRecord[] orderByBofPosition(List<BoundSheetRecord> boundSheetRecords) { public static BoundSheetRecord[] orderByBofPosition(List<BoundSheetRecord> boundSheetRecords) {
BoundSheetRecord[] bsrs = new BoundSheetRecord[boundSheetRecords.size()]; BoundSheetRecord[] bsrs = new BoundSheetRecord[boundSheetRecords.size()];
boundSheetRecords.toArray(bsrs); boundSheetRecords.toArray(bsrs);
Arrays.sort(bsrs, BOFComparator); Arrays.sort(bsrs, BoundSheetRecord::compareRecords);
return bsrs; return bsrs;
} }
private static final Comparator<BoundSheetRecord> BOFComparator = new Comparator<BoundSheetRecord>() {
public int compare(BoundSheetRecord bsr1, BoundSheetRecord bsr2) { private static int compareRecords(BoundSheetRecord bsr1, BoundSheetRecord bsr2) {
return bsr1.getPositionOfBof() - bsr2.getPositionOfBof(); return bsr1.getPositionOfBof() - bsr2.getPositionOfBof();
} }
};
@Override
public BoundSheetRecord copy() {
return new BoundSheetRecord(this);
}
} }

View File

@ -21,22 +21,28 @@ import org.apache.poi.hssf.record.common.FtrHeader;
import org.apache.poi.hssf.record.common.FutureRecord; import org.apache.poi.hssf.record.common.FutureRecord;
import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.Removal;
/** /**
* Conditional Formatting Header v12 record CFHEADER12 (0x0879), * Conditional Formatting Header v12 record CFHEADER12 (0x0879),
* for conditional formattings introduced in Excel 2007 and newer. * 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; public static final short sid = 0x0879;
private FtrHeader futureHeader; private FtrHeader futureHeader;
/** Creates new CFHeaderRecord */
public CFHeader12Record() { public CFHeader12Record() {
createEmpty(); createEmpty();
futureHeader = new FtrHeader(); futureHeader = new FtrHeader();
futureHeader.setRecordType(sid); futureHeader.setRecordType(sid);
} }
public CFHeader12Record(CFHeader12Record other) {
super(other);
futureHeader = other.futureHeader.copy();
}
public CFHeader12Record(CellRangeAddress[] regions, int nRules) { public CFHeader12Record(CellRangeAddress[] regions, int nRules) {
super(regions, nRules); super(regions, nRules);
futureHeader = new FtrHeader(); futureHeader = new FtrHeader();
@ -78,12 +84,17 @@ public final class CFHeader12Record extends CFHeaderBase implements FutureRecord
public CellRangeAddress getAssociatedRange() { public CellRangeAddress getAssociatedRange() {
return futureHeader.getAssociatedRange(); return futureHeader.getAssociatedRange();
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public CFHeader12Record clone() { public CFHeader12Record clone() {
CFHeader12Record result = new CFHeader12Record(); return copy();
result.futureHeader = (FtrHeader)futureHeader.clone(); }
super.copyTo(result);
return result; @Override
public CFHeader12Record copy() {
return new CFHeader12Record(this);
} }
} }

View File

@ -21,20 +21,28 @@ import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList; import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.ss.util.CellRangeUtil; import org.apache.poi.ss.util.CellRangeUtil;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.Removal;
/** /**
* Parent of Conditional Formatting Header records, * Parent of Conditional Formatting Header records,
* {@link CFHeaderRecord} and {@link CFHeader12Record}. * {@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_1_numcf;
private int field_2_need_recalculation_and_id; private int field_2_need_recalculation_and_id;
private CellRangeAddress field_3_enclosing_cell_range; private CellRangeAddress field_3_enclosing_cell_range;
private CellRangeAddressList field_4_cell_ranges; 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) { protected CFHeaderBase(CellRangeAddress[] regions, int nRules) {
CellRangeAddress[] mergeCellRanges = CellRangeUtil.mergeCellRanges(regions); CellRangeAddress[] mergeCellRanges = CellRangeUtil.mergeCellRanges(regions);
setCellRanges(mergeCellRanges); 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. * modify the enclosing cell range accordingly.
* @param cellRanges - list of CellRange objects * @param cellRanges - list of CellRange objects
*/ */
@ -151,13 +159,12 @@ public abstract class CFHeaderBase extends StandardRecord implements Cloneable {
field_4_cell_ranges.serialize(out); field_4_cell_ranges.serialize(out);
} }
protected void copyTo(CFHeaderBase result) { @Override
result.field_1_numcf = field_1_numcf; @SuppressWarnings("squid:S2975")
result.field_2_need_recalculation_and_id = field_2_need_recalculation_and_id; @Deprecated
result.field_3_enclosing_cell_range = field_3_enclosing_cell_range.copy(); @Removal(version = "5.0.0")
result.field_4_cell_ranges = field_4_cell_ranges.copy(); public abstract CFHeaderBase clone();
}
@Override @Override
public abstract CFHeaderBase clone(); // NOSONAR public abstract CFHeaderBase copy();
} }

View File

@ -18,19 +18,24 @@
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.util.Removal;
/** /**
* Conditional Formatting Header record CFHEADER (0x01B0). * Conditional Formatting Header record CFHEADER (0x01B0).
* Used to describe a {@link CFRuleRecord}. * Used to describe a {@link CFRuleRecord}.
* @see CFHeader12Record * @see CFHeader12Record
*/ */
public final class CFHeaderRecord extends CFHeaderBase implements Cloneable { public final class CFHeaderRecord extends CFHeaderBase {
public static final short sid = 0x01B0; public static final short sid = 0x01B0;
/** Creates new CFHeaderRecord */
public CFHeaderRecord() { public CFHeaderRecord() {
createEmpty(); createEmpty();
} }
public CFHeaderRecord(CFHeaderRecord other) {
super(other);
}
public CFHeaderRecord(CellRangeAddress[] regions, int nRules) { public CFHeaderRecord(CellRangeAddress[] regions, int nRules) {
super(regions, nRules); super(regions, nRules);
} }
@ -48,9 +53,15 @@ public final class CFHeaderRecord extends CFHeaderBase implements Cloneable {
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public CFHeaderRecord clone() { public CFHeaderRecord clone() {
CFHeaderRecord result = new CFHeaderRecord(); return copy();
super.copyTo(result); }
return result;
@Override
public CFHeaderRecord copy() {
return new CFHeaderRecord(this);
} }
} }

View File

@ -39,18 +39,19 @@ import org.apache.poi.util.HexDump;
import org.apache.poi.util.IOUtils; import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.POILogger; 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, * <p>This is for newer-style Excel conditional formattings,
* from Excel 2007 onwards. * from Excel 2007 onwards.
* *
* <p>{@link CFRuleRecord} is used where the condition type is * <p>{@link CFRuleRecord} is used where the condition type is
* {@link #CONDITION_TYPE_CELL_VALUE_IS} or {@link #CONDITION_TYPE_FORMULA}, * {@link #CONDITION_TYPE_CELL_VALUE_IS} or {@link #CONDITION_TYPE_FORMULA},
* this is only used for the other types * 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 //arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000; 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 int template_type;
private byte template_param_length; private byte template_param_length;
private byte[] template_params; private byte[] template_params;
private DataBarFormatting data_bar; private DataBarFormatting data_bar;
private IconMultiStateFormatting multistate; private IconMultiStateFormatting multistate;
private ColorGradientFormatting color_gradient; private ColorGradientFormatting color_gradient;
// TODO Parse this, see #58150 // TODO Parse this, see #58150
private byte[] filter_data; 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) { private CFRule12Record(byte conditionType, byte comparisonOperation) {
super(conditionType, comparisonOperation); super(conditionType, comparisonOperation);
setDefaults(); setDefaults();
@ -84,15 +106,17 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl
setDefaults(); setDefaults();
this.formula_scale = Formula.create(formulaScale); this.formula_scale = Formula.create(formulaScale);
} }
private void setDefaults() { private void setDefaults() {
futureHeader = new FtrHeader(); futureHeader = new FtrHeader();
futureHeader.setRecordType(sid); futureHeader.setRecordType(sid);
ext_formatting_length = 0; ext_formatting_length = 0;
ext_formatting_data = new byte[4]; ext_formatting_data = new byte[4];
formula_scale = Formula.create(Ptg.EMPTY_PTG_ARRAY); formula_scale = Formula.create(Ptg.EMPTY_PTG_ARRAY);
ext_opts = 0; ext_opts = 0;
priority = 0; priority = 0;
template_type = getConditionType(); template_type = getConditionType();
@ -102,10 +126,10 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl
/** /**
* Creates a new comparison operation rule * Creates a new comparison operation rule
* *
* @param sheet the sheet * @param sheet the sheet
* @param formulaText the first formula text * @param formulaText the first formula text
* *
* @return a new comparison operation rule * @return a new comparison operation rule
*/ */
public static CFRule12Record create(HSSFSheet sheet, String formulaText) { 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, return new CFRule12Record(CONDITION_TYPE_FORMULA, ComparisonOperator.NO_COMPARISON,
formula1, null, null); formula1, null, null);
} }
/** /**
* Creates a new comparison operation rule * Creates a new comparison operation rule
* *
* @param sheet the sheet * @param sheet the sheet
* @param comparisonOperation the comparison operation * @param comparisonOperation the comparison operation
* @param formulaText1 the first formula text * @param formulaText1 the first formula text
* @param formulaText2 the second formula text * @param formulaText2 the second formula text
* *
* @return a new comparison operation rule * @return a new comparison operation rule
*/ */
public static CFRule12Record create(HSSFSheet sheet, byte comparisonOperation, public static CFRule12Record create(HSSFSheet sheet, byte comparisonOperation,
String formulaText1, String formulaText2) { String formulaText1, String formulaText2) {
Ptg[] formula1 = parseFormula(formulaText1, sheet); Ptg[] formula1 = parseFormula(formulaText1, sheet);
Ptg[] formula2 = parseFormula(formulaText2, 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); formula1, formula2, null);
} }
/** /**
* Creates a new comparison operation rule * Creates a new comparison operation rule
* *
* @param sheet the sheet * @param sheet the sheet
* @param comparisonOperation the comparison operation * @param comparisonOperation the comparison operation
* @param formulaText1 the first formula text * @param formulaText1 the first formula text
* @param formulaText2 the second formula text * @param formulaText2 the second formula text
* @param formulaTextScale the scale to apply for the comparison * @param formulaTextScale the scale to apply for the comparison
* *
* @return a new comparison operation rule * @return a new comparison operation rule
*/ */
public static CFRule12Record create(HSSFSheet sheet, byte comparisonOperation, 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[] formula1 = parseFormula(formulaText1, sheet);
Ptg[] formula2 = parseFormula(formulaText2, sheet); Ptg[] formula2 = parseFormula(formulaText2, sheet);
Ptg[] formula3 = parseFormula(formulaTextScale, 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); formula1, formula2, formula3);
} }
/** /**
* Creates a new Data Bar formatting * Creates a new Data Bar formatting
* *
* @param sheet the sheet * @param sheet the sheet
* @param color the data bar color * @param color the data bar color
* *
* @return a new Data Bar formatting * @return a new Data Bar formatting
*/ */
public static CFRule12Record create(HSSFSheet sheet, ExtendedColor color) { 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); ComparisonOperator.NO_COMPARISON);
DataBarFormatting dbf = r.createDataBarFormatting(); DataBarFormatting dbf = r.createDataBarFormatting();
dbf.setColor(color); dbf.setColor(color);
dbf.setPercentMin((byte)0); dbf.setPercentMin((byte)0);
dbf.setPercentMax((byte)100); dbf.setPercentMax((byte)100);
DataBarThreshold min = new DataBarThreshold(); DataBarThreshold min = new DataBarThreshold();
min.setType(RangeType.MIN.id); min.setType(RangeType.MIN.id);
dbf.setThresholdMin(min); dbf.setThresholdMin(min);
DataBarThreshold max = new DataBarThreshold(); DataBarThreshold max = new DataBarThreshold();
max.setType(RangeType.MAX.id); max.setType(RangeType.MAX.id);
dbf.setThresholdMax(max); dbf.setThresholdMax(max);
return r; return r;
} }
/** /**
* Creates a new Icon Set / Multi-State formatting * Creates a new Icon Set / Multi-State formatting
* *
* @param sheet the sheet * @param sheet the sheet
* @param iconSet the icon set * @param iconSet the icon set
* *
* @return a new Icon Set / Multi-State formatting * @return a new Icon Set / Multi-State formatting
*/ */
public static CFRule12Record create(HSSFSheet sheet, IconSet iconSet) { 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++) { for (int i=0; i<ts.length; i++) {
ts[i] = new IconMultiStateThreshold(); ts[i] = new IconMultiStateThreshold();
} }
CFRule12Record r = new CFRule12Record(CONDITION_TYPE_ICON_SET, CFRule12Record r = new CFRule12Record(CONDITION_TYPE_ICON_SET,
ComparisonOperator.NO_COMPARISON); ComparisonOperator.NO_COMPARISON);
IconMultiStateFormatting imf = r.createMultiStateFormatting(); IconMultiStateFormatting imf = r.createMultiStateFormatting();
imf.setIconSet(iconSet); imf.setIconSet(iconSet);
imf.setThresholds(ts); imf.setThresholds(ts);
return r; return r;
} }
/** /**
* Creates a new Color Scale / Color Gradient formatting * Creates a new Color Scale / Color Gradient formatting
* *
* @param sheet the sheet * @param sheet the sheet
* *
* @return a new Color Scale / Color Gradient formatting * @return a new Color Scale / Color Gradient formatting
*/ */
public static CFRule12Record createColorScale(HSSFSheet sheet) { public static CFRule12Record createColorScale(HSSFSheet sheet) {
@ -216,8 +240,8 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl
ts[i] = new ColorGradientThreshold(); ts[i] = new ColorGradientThreshold();
colors[i] = new ExtendedColor(); colors[i] = new ExtendedColor();
} }
CFRule12Record r = new CFRule12Record(CONDITION_TYPE_COLOR_SCALE, CFRule12Record r = new CFRule12Record(CONDITION_TYPE_COLOR_SCALE,
ComparisonOperator.NO_COMPARISON); ComparisonOperator.NO_COMPARISON);
ColorGradientFormatting cgf = r.createColorGradientFormatting(); ColorGradientFormatting cgf = r.createColorGradientFormatting();
cgf.setNumControlPoints(numPoints); cgf.setNumControlPoints(numPoints);
@ -232,7 +256,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl
setComparisonOperation(in.readByte()); setComparisonOperation(in.readByte());
int field_3_formula1_len = in.readUShort(); int field_3_formula1_len = in.readUShort();
int field_4_formula2_len = in.readUShort(); int field_4_formula2_len = in.readUShort();
ext_formatting_length = in.readInt(); ext_formatting_length = in.readInt();
ext_formatting_data = new byte[0]; ext_formatting_data = new byte[0];
if (ext_formatting_length == 0) { if (ext_formatting_length == 0) {
@ -245,13 +269,13 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl
in.readFully(ext_formatting_data); in.readFully(ext_formatting_data);
} }
} }
setFormula1(Formula.read(field_3_formula1_len, in)); setFormula1(Formula.read(field_3_formula1_len, in));
setFormula2(Formula.read(field_4_formula2_len, in)); setFormula2(Formula.read(field_4_formula2_len, in));
int formula_scale_len = in.readUShort(); int formula_scale_len = in.readUShort();
formula_scale = Formula.read(formula_scale_len, in); formula_scale = Formula.read(formula_scale_len, in);
ext_opts = in.readByte(); ext_opts = in.readByte();
priority = in.readUShort(); priority = in.readUShort();
template_type = 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); logger.log(POILogger.WARN, "CF Rule v12 template params length should be 0 or 16, found " + template_param_length);
in.readRemainder(); in.readRemainder();
} }
byte type = getConditionType(); byte type = getConditionType();
if (type == CONDITION_TYPE_COLOR_SCALE) { if (type == CONDITION_TYPE_COLOR_SCALE) {
color_gradient = new ColorGradientFormatting(in); color_gradient = new ColorGradientFormatting(in);
@ -275,7 +299,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl
multistate = new IconMultiStateFormatting(in); multistate = new IconMultiStateFormatting(in);
} }
} }
public boolean containsDataBarBlock() { public boolean containsDataBarBlock() {
return (data_bar != null); return (data_bar != null);
} }
@ -284,7 +308,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl
} }
public DataBarFormatting createDataBarFormatting() { public DataBarFormatting createDataBarFormatting() {
if (data_bar != null) return data_bar; if (data_bar != null) return data_bar;
// Convert, setup and return // Convert, setup and return
setConditionType(CONDITION_TYPE_DATA_BAR); setConditionType(CONDITION_TYPE_DATA_BAR);
data_bar = new DataBarFormatting(); data_bar = new DataBarFormatting();
@ -299,7 +323,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl
} }
public IconMultiStateFormatting createMultiStateFormatting() { public IconMultiStateFormatting createMultiStateFormatting() {
if (multistate != null) return multistate; if (multistate != null) return multistate;
// Convert, setup and return // Convert, setup and return
setConditionType(CONDITION_TYPE_ICON_SET); setConditionType(CONDITION_TYPE_ICON_SET);
multistate = new IconMultiStateFormatting(); multistate = new IconMultiStateFormatting();
@ -314,7 +338,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl
} }
public ColorGradientFormatting createColorGradientFormatting() { public ColorGradientFormatting createColorGradientFormatting() {
if (color_gradient != null) return color_gradient; if (color_gradient != null) return color_gradient;
// Convert, setup and return // Convert, setup and return
setConditionType(CONDITION_TYPE_COLOR_SCALE); setConditionType(CONDITION_TYPE_COLOR_SCALE);
color_gradient = new ColorGradientFormatting(); color_gradient = new ColorGradientFormatting();
@ -356,7 +380,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl
*/ */
public void serialize(LittleEndianOutput out) { public void serialize(LittleEndianOutput out) {
futureHeader.serialize(out); futureHeader.serialize(out);
int formula1Len=getFormulaSize(getFormula1()); int formula1Len=getFormulaSize(getFormula1());
int formula2Len=getFormulaSize(getFormula2()); int formula2Len=getFormulaSize(getFormula2());
@ -364,7 +388,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl
out.writeByte(getComparisonOperation()); out.writeByte(getComparisonOperation());
out.writeShort(formula1Len); out.writeShort(formula1Len);
out.writeShort(formula2Len); out.writeShort(formula2Len);
// TODO Update ext_formatting_length // TODO Update ext_formatting_length
if (ext_formatting_length == 0) { if (ext_formatting_length == 0) {
out.writeInt(0); out.writeInt(0);
@ -374,18 +398,18 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl
serializeFormattingBlock(out); serializeFormattingBlock(out);
out.write(ext_formatting_data); out.write(ext_formatting_data);
} }
getFormula1().serializeTokens(out); getFormula1().serializeTokens(out);
getFormula2().serializeTokens(out); getFormula2().serializeTokens(out);
out.writeShort(getFormulaSize(formula_scale)); out.writeShort(getFormulaSize(formula_scale));
formula_scale.serializeTokens(out); formula_scale.serializeTokens(out);
out.writeByte(ext_opts); out.writeByte(ext_opts);
out.writeShort(priority); out.writeShort(priority);
out.writeShort(template_type); out.writeShort(template_type);
out.writeByte(template_param_length); out.writeByte(template_param_length);
out.write(template_params); out.write(template_params);
byte type = getConditionType(); byte type = getConditionType();
if (type == CONDITION_TYPE_COLOR_SCALE) { if (type == CONDITION_TYPE_COLOR_SCALE) {
color_gradient.serialize(out); color_gradient.serialize(out);
@ -409,7 +433,7 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl
len += getFormulaSize(getFormula2()); len += getFormulaSize(getFormula2());
len += 2 + getFormulaSize(formula_scale); len += 2 + getFormulaSize(formula_scale);
len += 6 + template_params.length; len += 6 + template_params.length;
byte type = getConditionType(); byte type = getConditionType();
if (type == CONDITION_TYPE_COLOR_SCALE) { if (type == CONDITION_TYPE_COLOR_SCALE) {
len += color_gradient.getDataLength(); len += color_gradient.getDataLength();
@ -461,44 +485,18 @@ public final class CFRule12Record extends CFRuleBase implements FutureRecord, Cl
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public CFRule12Record clone() { public CFRule12Record clone() {
CFRule12Record rec = new CFRule12Record(getConditionType(), getComparisonOperation()); return copy();
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);
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() { public short getFutureRecordType() {
return futureHeader.getRecordType(); return futureHeader.getRecordType();
} }

View File

@ -30,32 +30,31 @@ import org.apache.poi.util.BitFieldFactory;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
import org.apache.poi.util.Removal;
/** /**
* Conditional Formatting Rules. This can hold old-style rules * Conditional Formatting Rules. This can hold old-style rules
* *
* *
* <p>This is for the older-style Excel conditional formattings, * <p>This is for the older-style Excel conditional formattings,
* new-style (Excel 2007+) also make use of {@link CFRule12Record} * new-style (Excel 2007+) also make use of {@link CFRule12Record}
* for their rules.</p> * 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 // FIXME: Merge with org.apache.poi.ss.usermodel.ComparisonOperator and rewrite as an enum
public static final class ComparisonOperator { public interface ComparisonOperator {
public static final byte NO_COMPARISON = 0; byte NO_COMPARISON = 0;
public static final byte BETWEEN = 1; byte BETWEEN = 1;
public static final byte NOT_BETWEEN = 2; byte NOT_BETWEEN = 2;
public static final byte EQUAL = 3; byte EQUAL = 3;
public static final byte NOT_EQUAL = 4; byte NOT_EQUAL = 4;
public static final byte GT = 5; byte GT = 5;
public static final byte LT = 6; byte LT = 6;
public static final byte GE = 7; byte GE = 7;
public static final byte LE = 8; byte LE = 8;
private static final byte max_operator = 8; byte max_operator = 8;
} }
protected static final POILogger logger = POILogFactory.getLogger(CFRuleBase.class);
private byte condition_type;
// The only kinds that CFRuleRecord handles // The only kinds that CFRuleRecord handles
public static final byte CONDITION_TYPE_CELL_VALUE_IS = 1; public static final byte CONDITION_TYPE_CELL_VALUE_IS = 1;
public static final byte CONDITION_TYPE_FORMULA = 2; 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_FILTER = 5;
public static final byte CONDITION_TYPE_ICON_SET = 6; 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_CELL_VALUE = 0x0000;
public static final int TEMPLATE_FORMULA = 0x0001; public static final int TEMPLATE_FORMULA = 0x0001;
public static final int TEMPLATE_COLOR_SCALE_FORMATTING = 0x0002; 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_DUPLICATE_VALUES = 0x001B;
public static final int TEMPLATE_ABOVE_OR_EQUAL_TO_AVERAGE = 0x001D; public static final int TEMPLATE_ABOVE_OR_EQUAL_TO_AVERAGE = 0x001D;
public static final int TEMPLATE_BELOW_OR_EQUAL_TO_AVERAGE = 0x001E; 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 modificationBits = bf(0x003FFFFF); // Bits: font,align,bord,patt,prot
static final BitField alignHor = bf(0x00000001); // 0 = Horizontal alignment modified static final BitField alignHor = bf(0x00000001); // 0 = Horizontal alignment modified
static final BitField alignVer = bf(0x00000002); // 0 = Vertical 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); return BitFieldFactory.getInstance(i);
} }
private byte condition_type;
private byte comparison_operator;
protected int formatting_options; 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 FontFormatting _fontFormatting;
protected BorderFormatting _borderFormatting; protected BorderFormatting _borderFormatting;
protected PatternFormatting _patternFormatting; protected PatternFormatting _patternFormatting;
private Formula formula1; private Formula formula1;
private Formula formula2; private Formula formula2;
/** /**
* Creates new CFRuleRecord * Creates new CFRuleRecord
* *
* @param conditionType the condition type * @param conditionType the condition type
* @param comparisonOperation the comparison operation * @param comparisonOperation the comparison operation
*/ */
@ -151,19 +155,34 @@ public abstract class CFRuleBase extends StandardRecord implements Cloneable {
formula1 = Formula.create(Ptg.EMPTY_PTG_ARRAY); formula1 = Formula.create(Ptg.EMPTY_PTG_ARRAY);
formula2 = Formula.create(Ptg.EMPTY_PTG_ARRAY); formula2 = Formula.create(Ptg.EMPTY_PTG_ARRAY);
} }
protected CFRuleBase(byte conditionType, byte comparisonOperation, Ptg[] formula1, Ptg[] formula2) { protected CFRuleBase(byte conditionType, byte comparisonOperation, Ptg[] formula1, Ptg[] formula2) {
this(conditionType, comparisonOperation); this(conditionType, comparisonOperation);
this.formula1 = Formula.create(formula1); this.formula1 = Formula.create(formula1);
this.formula2 = Formula.create(formula2); this.formula2 = Formula.create(formula2);
} }
protected CFRuleBase() {} 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) { protected int readFormatOptions(RecordInputStream in) {
formatting_options = in.readInt(); formatting_options = in.readInt();
formatting_not_used = in.readShort(); formatting_not_used = in.readShort();
int len = 6; int len = 6;
if (containsFontFormattingBlock()) { if (containsFontFormattingBlock()) {
_fontFormatting = new FontFormatting(in); _fontFormatting = new FontFormatting(in);
len += _fontFormatting.getDataLength(); len += _fontFormatting.getDataLength();
@ -178,7 +197,7 @@ public abstract class CFRuleBase extends StandardRecord implements Cloneable {
_patternFormatting = new PatternFormatting(in); _patternFormatting = new PatternFormatting(in);
len += _patternFormatting.getDataLength(); len += _patternFormatting.getDataLength();
} }
return len; return len;
} }
@ -187,10 +206,8 @@ public abstract class CFRuleBase extends StandardRecord implements Cloneable {
} }
protected void setConditionType(byte condition_type) { protected void setConditionType(byte condition_type) {
if ((this instanceof CFRuleRecord)) { if ((this instanceof CFRuleRecord)) {
if (condition_type == CONDITION_TYPE_CELL_VALUE_IS || if (!(condition_type == CONDITION_TYPE_CELL_VALUE_IS ||
condition_type == CONDITION_TYPE_FORMULA) { condition_type == CONDITION_TYPE_FORMULA)) {
// Good, valid combination
} else {
throw new IllegalArgumentException("CFRuleRecord only accepts Value-Is and Formula types"); 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) if (operation < 0 || operation > ComparisonOperator.max_operator)
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Valid operators are only in the range 0 to " +ComparisonOperator.max_operator); "Valid operators are only in the range 0 to " +ComparisonOperator.max_operator);
this.comparison_operator = operation; this.comparison_operator = operation;
} }
public byte getComparisonOperation() { public byte getComparisonOperation() {
@ -351,7 +368,7 @@ public abstract class CFRuleBase extends StandardRecord implements Cloneable {
private void setOptionFlag(boolean flag, BitField field) { private void setOptionFlag(boolean flag, BitField field) {
formatting_options = field.setBoolean(formatting_options, flag); formatting_options = field.setBoolean(formatting_options, flag);
} }
protected int getFormattingBlockSize() { protected int getFormattingBlockSize() {
return 6 + return 6 +
(containsFontFormattingBlock()?_fontFormatting.getRawRecord().length:0)+ (containsFontFormattingBlock()?_fontFormatting.getRawRecord().length:0)+
@ -375,7 +392,7 @@ public abstract class CFRuleBase extends StandardRecord implements Cloneable {
_patternFormatting.serialize(out); _patternFormatting.serialize(out);
} }
} }
/** /**
* get the stack of the 1st expression as a list * 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); int sheetIndex = sheet.getWorkbook().getSheetIndex(sheet);
return HSSFFormulaParser.parse(formula, sheet.getWorkbook(), FormulaType.CELL, sheetIndex); 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 @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public abstract CFRuleBase clone(); public abstract CFRuleBase clone();
@Override
public abstract CFRuleBase copy();
} }

View File

@ -23,18 +23,22 @@ import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.ss.formula.Formula; import org.apache.poi.ss.formula.Formula;
import org.apache.poi.ss.formula.ptg.Ptg; import org.apache.poi.ss.formula.ptg.Ptg;
import org.apache.poi.util.LittleEndianOutput; 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, * <p>This is for the older-style Excel conditional formattings,
* new-style (Excel 2007+) also make use of {@link CFRule12Record} * new-style (Excel 2007+) also make use of {@link CFRule12Record}
* for their rules.</p> * for their rules.</p>
*/ */
public final class CFRuleRecord extends CFRuleBase implements Cloneable { public final class CFRuleRecord extends CFRuleBase {
public static final short sid = 0x01B1; public static final short sid = 0x01B1;
/** Creates new CFRuleRecord */ public CFRuleRecord(CFRuleRecord other) {
super(other);
}
private CFRuleRecord(byte conditionType, byte comparisonOperation) { private CFRuleRecord(byte conditionType, byte comparisonOperation) {
super(conditionType, comparisonOperation); super(conditionType, comparisonOperation);
setDefaults(); setDefaults();
@ -59,10 +63,10 @@ public final class CFRuleRecord extends CFRuleBase implements Cloneable {
/** /**
* Creates a new comparison operation rule * Creates a new comparison operation rule
* *
* @param sheet the sheet * @param sheet the sheet
* @param formulaText the formula text * @param formulaText the formula text
* *
* @return a new comparison operation rule * @return a new comparison operation rule
*/ */
public static CFRuleRecord create(HSSFSheet sheet, String formulaText) { 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 * Creates a new comparison operation rule
* *
* @param sheet the sheet * @param sheet the sheet
* @param comparisonOperation the comparison operation * @param comparisonOperation the comparison operation
* @param formulaText1 the first formula text * @param formulaText1 the first formula text
* @param formulaText2 the second formula text * @param formulaText2 the second formula text
* *
* @return a new comparison operation rule * @return a new comparison operation rule
*/ */
public static CFRuleRecord create(HSSFSheet sheet, byte comparisonOperation, public static CFRuleRecord create(HSSFSheet sheet, byte comparisonOperation,
@ -120,7 +124,7 @@ public final class CFRuleRecord extends CFRuleBase implements Cloneable {
out.writeByte(getComparisonOperation()); out.writeByte(getComparisonOperation());
out.writeShort(formula1Len); out.writeShort(formula1Len);
out.writeShort(formula2Len); out.writeShort(formula2Len);
serializeFormattingBlock(out); serializeFormattingBlock(out);
getFormula1().serializeTokens(out); getFormula1().serializeTokens(out);
@ -156,9 +160,15 @@ public final class CFRuleRecord extends CFRuleBase implements Cloneable {
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public CFRuleRecord clone() { public CFRuleRecord clone() {
CFRuleRecord rec = new CFRuleRecord(getConditionType(), getComparisonOperation()); return copy();
super.copyTo(rec); }
return rec;
@Override
public CFRuleRecord copy() {
return new CFRuleRecord(this);
} }
} }

View File

@ -19,30 +19,26 @@ package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
/** /**
* XCT - CRN Count <P> * XCT - CRN Count
*
* REFERENCE: 5.114<P>
*
* @author Josh Micich
*/ */
public final class CRNCountRecord extends StandardRecord { 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 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 CRNCountRecord() {
private int field_2_sheet_table_index; // incomplete code
public CRNCountRecord() {
throw new RuntimeException("incomplete code");
} }
public int getNumberOfCRNs() { public CRNCountRecord(CRNCountRecord other) {
return field_1_number_crn_records; 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) { public CRNCountRecord(RecordInputStream in) {
field_1_number_crn_records = in.readShort(); field_1_number_crn_records = in.readShort();
if(field_1_number_crn_records < 0) { if(field_1_number_crn_records < 0) {
@ -53,6 +49,9 @@ public final class CRNCountRecord extends StandardRecord {
field_2_sheet_table_index = in.readShort(); field_2_sheet_table_index = in.readShort();
} }
public int getNumberOfCRNs() {
return field_1_number_crn_records;
}
public String toString() { public String toString() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
@ -77,4 +76,9 @@ public final class CRNCountRecord extends StandardRecord {
public short getSid() { public short getSid() {
return sid; return sid;
} }
@Override
public CRNCountRecord copy() {
return new CRNCountRecord(this);
}
} }

View File

@ -21,27 +21,30 @@ import org.apache.poi.ss.formula.constant.ConstantValueParser;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
/** /**
* Title: CRN(0x005A)<p> * This record stores the contents of an external cell or cell range
* Description: This record stores the contents of an external cell or cell range<p>
* REFERENCE: OOO 5.23
*/ */
public final class CRNRecord extends StandardRecord { 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_1_last_column_index;
private int field_2_first_column_index; private int field_2_first_column_index;
private int field_3_row_index; private int field_3_row_index;
private Object[] field_4_constant_values; private Object[] field_4_constant_values;
public CRNRecord() { private CRNRecord() {
throw new RuntimeException("incomplete code"); // incomplete code
} }
public int getNumberOfCRNs() { public CRNRecord(CRNRecord other) {
return field_1_last_column_index; 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) { public CRNRecord(RecordInputStream in) {
field_1_last_column_index = in.readUByte(); field_1_last_column_index = in.readUByte();
field_2_first_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); field_4_constant_values = ConstantValueParser.parse(in, nValues);
} }
public int getNumberOfCRNs() {
return field_1_last_column_index;
}
public String toString() { public String toString() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
@ -77,4 +83,9 @@ public final class CRNRecord extends StandardRecord {
public short getSid() { public short getSid() {
return sid; return sid;
} }
@Override
public CRNRecord copy() {
return new CRNRecord(this);
}
} }

View File

@ -15,34 +15,37 @@
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
==================================================================== */ ==================================================================== */
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.Removal;
/** /**
* Title: Calc Count Record * Specifies the maximum times the gui should perform a formula recalculation.
* Description: Specifies the maximum times the gui should perform a formula * For instance: in the case a formula includes cells that are themselves a result of a formula and
* recalculation. For instance: in the case a formula includes * a value changes. This is essentially a failsafe against an infinite loop in the event the formulas
* cells that are themselves a result of a formula and a value * are not independent.
* 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>
* @version 2.0-pre * @version 2.0-pre
* @see org.apache.poi.hssf.record.CalcModeRecord * @see CalcModeRecord
*/ */
public final class CalcCountRecord extends StandardRecord implements Cloneable { public final class CalcCountRecord extends StandardRecord {
public final static short sid = 0xC; public static final short sid = 0xC;
private short field_1_iterations;
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(); field_1_iterations = in.readShort();
} }
@ -91,9 +94,15 @@ public final class CalcCountRecord extends StandardRecord implements Cloneable {
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public CalcCountRecord clone() { public CalcCountRecord clone() {
CalcCountRecord rec = new CalcCountRecord(); return copy();
rec.field_1_iterations = field_1_iterations; }
return rec;
@Override
public CalcCountRecord copy() {
return new CalcCountRecord(this);
} }
} }

View File

@ -15,52 +15,42 @@
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
==================================================================== */ ==================================================================== */
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.Removal;
/** /**
* Title: Calc Mode Record<P> * Tells the gui whether to calculate formulas automatically, manually or automatically except for tables.
* 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)
* @version 2.0-pre * @version 2.0-pre
* @see org.apache.poi.hssf.record.CalcCountRecord * @see CalcCountRecord
*/ */
public final class CalcModeRecord extends StandardRecord implements Cloneable { public final class CalcModeRecord extends StandardRecord {
public final static short sid = 0xD; 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 except for tables (-1) */
* automatically calculate formulas (1) public static final short AUTOMATIC_EXCEPT_TABLES = -1;
*/
public final static short AUTOMATIC = 1; private short field_1_calcmode;
/** public CalcModeRecord() {}
* automatically calculate formulas except for tables (-1)
*/
public final static short AUTOMATIC_EXCEPT_TABLES = -1; public CalcModeRecord(CalcModeRecord other) {
private short field_1_calcmode; super(other);
field_1_calcmode = other.field_1_calcmode;
public CalcModeRecord()
{
} }
public CalcModeRecord(RecordInputStream in) public CalcModeRecord(RecordInputStream in) {
{
field_1_calcmode = in.readShort(); field_1_calcmode = in.readShort();
} }
@ -119,9 +109,15 @@ public final class CalcModeRecord extends StandardRecord implements Cloneable {
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public CalcModeRecord clone() { public CalcModeRecord clone() {
CalcModeRecord rec = new CalcModeRecord(); return copy();
rec.field_1_calcmode = field_1_calcmode; }
return rec;
@Override
public CalcModeRecord copy() {
return new CalcModeRecord(this);
} }
} }

View File

@ -29,8 +29,13 @@ public abstract class CellRecord extends StandardRecord implements CellValueReco
private int _columnIndex; private int _columnIndex;
private int _formatIndex; private int _formatIndex;
protected CellRecord() { protected CellRecord() {}
// fields uninitialised
protected CellRecord(CellRecord other) {
super(other);
_rowIndex = other.getRow();
_columnIndex = other.getColumn();
_formatIndex = other.getXFIndex();
} }
protected CellRecord(RecordInputStream in) { 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 * Append specific debug info (used by {@link #toString()} for the value
* contained in this record. Trailing new-line should not be appended * contained in this record. Trailing new-line should not be appended
* (superclass does that). * (superclass does that).
* *
* @param sb the StringBuilder to write to * @param sb the StringBuilder to write to
*/ */
protected abstract void appendValueText(StringBuilder sb); protected abstract void appendValueText(StringBuilder sb);
/** /**
* Gets the debug info BIFF record type name (used by {@link #toString()}. * Gets the debug info BIFF record type name (used by {@link #toString()}.
* *
* @return the record type name * @return the record type name
*/ */
protected abstract String getRecordName(); protected abstract String getRecordName();
/** /**
* writes out the value data for this cell record * writes out the value data for this cell record
* *
* @param out the output * @param out the output
*/ */
protected abstract void serializeValue(LittleEndianOutput out); protected abstract void serializeValue(LittleEndianOutput out);
@ -137,9 +142,6 @@ public abstract class CellRecord extends StandardRecord implements CellValueReco
return 6 + getValueDataSize(); return 6 + getValueDataSize();
} }
protected final void copyBaseFields(CellRecord rec) { @Override
rec._rowIndex = _rowIndex; public abstract CellRecord copy();
rec._columnIndex = _columnIndex;
rec._formatIndex = _formatIndex;
}
} }

View File

@ -15,7 +15,7 @@
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
==================================================================== */ ==================================================================== */
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
@ -23,33 +23,33 @@ import org.apache.poi.util.CodePageUtil;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
/** /**
* Title: Codepage Record * The default characterset. for the workbook<p>
* <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> * Use {@link CodePageUtil} to turn these values into Java code pages to encode/decode strings.
* <p>Use {@link CodePageUtil} to turn these values into Java code pages *
* to encode/decode strings.</p>
* @version 2.0-pre * @version 2.0-pre
*/ */
public final class CodepageRecord public final class CodepageRecord extends StandardRecord {
extends StandardRecord public static final short sid = 0x42;
{
public final static short sid = 0x42;
private short field_1_codepage; // = 0;
/** /**
* Excel 97+ (Biff 8) should always store strings as UTF-16LE or * Excel 97+ (Biff 8) should always store strings as UTF-16LE or
* compressed versions of that. As such, this should always be * compressed versions of that. As such, this should always be
* 0x4b0 = UTF_16, except for files coming from older versions. * 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(); field_1_codepage = in.readShort();
} }
@ -100,4 +100,9 @@ public final class CodepageRecord
{ {
return sid; return sid;
} }
@Override
public CodepageRecord copy() {
return new CodepageRecord(this);
}
} }

View File

@ -17,27 +17,27 @@
package org.apache.poi.hssf.record; 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.BitField;
import org.apache.poi.util.BitFieldFactory; 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> * Defines with width and formatting for a range of columns
* 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)
*/ */
public final class ColumnInfoRecord extends StandardRecord implements Cloneable { public final class ColumnInfoRecord extends StandardRecord {
public static final short sid = 0x007D; 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 _firstCol;
private int _lastCol; private int _lastCol;
private int _colWidth; private int _colWidth;
private int _xfIndex; private int _xfIndex;
private int _options; 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" // Excel seems write values 2, 10, and 260, even though spec says "must be zero"
private int field_6_reserved; 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 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) { public ColumnInfoRecord(RecordInputStream in) {
_firstCol = in.readUShort(); _firstCol = in.readUShort();
_lastCol = in.readUShort(); _lastCol = in.readUShort();
@ -196,7 +206,7 @@ public final class ColumnInfoRecord extends StandardRecord implements Cloneable
/** /**
* @param other the format to match with * @param other the format to match with
* *
* @return {@code true} if the format, options and column width match * @return {@code true} if the format, options and column width match
*/ */
public boolean formatMatches(ColumnInfoRecord other) { public boolean formatMatches(ColumnInfoRecord other) {
@ -246,14 +256,15 @@ public final class ColumnInfoRecord extends StandardRecord implements Cloneable
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public ColumnInfoRecord clone() { public ColumnInfoRecord clone() {
ColumnInfoRecord rec = new ColumnInfoRecord(); return copy();
rec._firstCol = _firstCol; }
rec._lastCol = _lastCol;
rec._colWidth = _colWidth; @Override
rec._xfIndex = _xfIndex; public ColumnInfoRecord copy() {
rec._options = _options; return new ColumnInfoRecord(this);
rec.field_6_reserved = field_6_reserved;
return rec;
} }
} }

View File

@ -23,50 +23,51 @@ import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianInput;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.RecordFormatException; 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. * 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 class CommonObjectDataSubRecord extends SubRecord {
public final static short sid = 0x0015; public static final short sid = 0x0015;
private static final BitField locked = BitFieldFactory.getInstance(0x0001); private static final BitField locked = BitFieldFactory.getInstance(0x0001);
private static final BitField printable = BitFieldFactory.getInstance(0x0010); private static final BitField printable = BitFieldFactory.getInstance(0x0010);
private static final BitField autofill = BitFieldFactory.getInstance(0x2000); private static final BitField autofill = BitFieldFactory.getInstance(0x2000);
private static final BitField autoline = BitFieldFactory.getInstance(0x4000); private static final BitField autoline = BitFieldFactory.getInstance(0x4000);
public final static short OBJECT_TYPE_GROUP = 0; public static final short OBJECT_TYPE_GROUP = 0;
public final static short OBJECT_TYPE_LINE = 1; public static final short OBJECT_TYPE_LINE = 1;
public final static short OBJECT_TYPE_RECTANGLE = 2; public static final short OBJECT_TYPE_RECTANGLE = 2;
public final static short OBJECT_TYPE_OVAL = 3; public static final short OBJECT_TYPE_OVAL = 3;
public final static short OBJECT_TYPE_ARC = 4; public static final short OBJECT_TYPE_ARC = 4;
public final static short OBJECT_TYPE_CHART = 5; public static final short OBJECT_TYPE_CHART = 5;
public final static short OBJECT_TYPE_TEXT = 6; public static final short OBJECT_TYPE_TEXT = 6;
public final static short OBJECT_TYPE_BUTTON = 7; public static final short OBJECT_TYPE_BUTTON = 7;
public final static short OBJECT_TYPE_PICTURE = 8; public static final short OBJECT_TYPE_PICTURE = 8;
public final static short OBJECT_TYPE_POLYGON = 9; public static final short OBJECT_TYPE_POLYGON = 9;
public final static short OBJECT_TYPE_RESERVED1 = 10; public static final short OBJECT_TYPE_RESERVED1 = 10;
public final static short OBJECT_TYPE_CHECKBOX = 11; public static final short OBJECT_TYPE_CHECKBOX = 11;
public final static short OBJECT_TYPE_OPTION_BUTTON = 12; public static final short OBJECT_TYPE_OPTION_BUTTON = 12;
public final static short OBJECT_TYPE_EDIT_BOX = 13; public static final short OBJECT_TYPE_EDIT_BOX = 13;
public final static short OBJECT_TYPE_LABEL = 14; public static final short OBJECT_TYPE_LABEL = 14;
public final static short OBJECT_TYPE_DIALOG_BOX = 15; public static final short OBJECT_TYPE_DIALOG_BOX = 15;
public final static short OBJECT_TYPE_SPINNER = 16; public static final short OBJECT_TYPE_SPINNER = 16;
public final static short OBJECT_TYPE_SCROLL_BAR = 17; public static final short OBJECT_TYPE_SCROLL_BAR = 17;
public final static short OBJECT_TYPE_LIST_BOX = 18; public static final short OBJECT_TYPE_LIST_BOX = 18;
public final static short OBJECT_TYPE_GROUP_BOX = 19; public static final short OBJECT_TYPE_GROUP_BOX = 19;
public final static short OBJECT_TYPE_COMBO_BOX = 20; public static final short OBJECT_TYPE_COMBO_BOX = 20;
public final static short OBJECT_TYPE_RESERVED2 = 21; public static final short OBJECT_TYPE_RESERVED2 = 21;
public final static short OBJECT_TYPE_RESERVED3 = 22; public static final short OBJECT_TYPE_RESERVED3 = 22;
public final static short OBJECT_TYPE_RESERVED4 = 23; public static final short OBJECT_TYPE_RESERVED4 = 23;
public final static short OBJECT_TYPE_RESERVED5 = 24; public static final short OBJECT_TYPE_RESERVED5 = 24;
public final static short OBJECT_TYPE_COMMENT = 25; public static final short OBJECT_TYPE_COMMENT = 25;
public final static short OBJECT_TYPE_RESERVED6 = 26; public static final short OBJECT_TYPE_RESERVED6 = 26;
public final static short OBJECT_TYPE_RESERVED7 = 27; public static final short OBJECT_TYPE_RESERVED7 = 27;
public final static short OBJECT_TYPE_RESERVED8 = 28; public static final short OBJECT_TYPE_RESERVED8 = 28;
public final static short OBJECT_TYPE_RESERVED9 = 29; public static final short OBJECT_TYPE_RESERVED9 = 29;
public final static short OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING = 30; public static final short OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING = 30;
private short field_1_objectType; private short field_1_objectType;
private int field_2_objectId; private int field_2_objectId;
private short field_3_option; private short field_3_option;
@ -75,9 +76,16 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea
private int field_6_reserved3; 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) { public CommonObjectDataSubRecord(LittleEndianInput in, int size) {
@ -101,31 +109,31 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea
buffer.append(" .objectType = ") buffer.append(" .objectType = ")
.append("0x").append(HexDump.toHex( getObjectType ())) .append("0x").append(HexDump.toHex( getObjectType ()))
.append(" (").append( getObjectType() ).append(" )"); .append(" (").append( getObjectType() ).append(" )");
buffer.append(System.getProperty("line.separator")); buffer.append(System.getProperty("line.separator"));
buffer.append(" .objectId = ") buffer.append(" .objectId = ")
.append("0x").append(HexDump.toHex( getObjectId ())) .append("0x").append(HexDump.toHex( getObjectId ()))
.append(" (").append( getObjectId() ).append(" )"); .append(" (").append( getObjectId() ).append(" )");
buffer.append(System.getProperty("line.separator")); buffer.append(System.getProperty("line.separator"));
buffer.append(" .option = ") buffer.append(" .option = ")
.append("0x").append(HexDump.toHex( getOption ())) .append("0x").append(HexDump.toHex( getOption ()))
.append(" (").append( getOption() ).append(" )"); .append(" (").append( getOption() ).append(" )");
buffer.append(System.getProperty("line.separator")); buffer.append(System.getProperty("line.separator"));
buffer.append(" .locked = ").append(isLocked()).append('\n'); buffer.append(" .locked = ").append(isLocked()).append('\n');
buffer.append(" .printable = ").append(isPrintable()).append('\n'); buffer.append(" .printable = ").append(isPrintable()).append('\n');
buffer.append(" .autofill = ").append(isAutofill()).append('\n'); buffer.append(" .autofill = ").append(isAutofill()).append('\n');
buffer.append(" .autoline = ").append(isAutoline()).append('\n'); buffer.append(" .autoline = ").append(isAutoline()).append('\n');
buffer.append(" .reserved1 = ") buffer.append(" .reserved1 = ")
.append("0x").append(HexDump.toHex( getReserved1 ())) .append("0x").append(HexDump.toHex( getReserved1 ()))
.append(" (").append( getReserved1() ).append(" )"); .append(" (").append( getReserved1() ).append(" )");
buffer.append(System.getProperty("line.separator")); buffer.append(System.getProperty("line.separator"));
buffer.append(" .reserved2 = ") buffer.append(" .reserved2 = ")
.append("0x").append(HexDump.toHex( getReserved2 ())) .append("0x").append(HexDump.toHex( getReserved2 ()))
.append(" (").append( getReserved2() ).append(" )"); .append(" (").append( getReserved2() ).append(" )");
buffer.append(System.getProperty("line.separator")); buffer.append(System.getProperty("line.separator"));
buffer.append(" .reserved3 = ") buffer.append(" .reserved3 = ")
.append("0x").append(HexDump.toHex( getReserved3 ())) .append("0x").append(HexDump.toHex( getReserved3 ()))
.append(" (").append( getReserved3() ).append(" )"); .append(" (").append( getReserved3() ).append(" )");
buffer.append(System.getProperty("line.separator")); buffer.append(System.getProperty("line.separator"));
buffer.append("[/ftCmo]\n"); buffer.append("[/ftCmo]\n");
return buffer.toString(); return buffer.toString();
@ -159,23 +167,23 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public CommonObjectDataSubRecord clone() { public CommonObjectDataSubRecord clone() {
CommonObjectDataSubRecord rec = new CommonObjectDataSubRecord(); return copy();
}
rec.field_1_objectType = field_1_objectType;
rec.field_2_objectId = field_2_objectId; @Override
rec.field_3_option = field_3_option; public CommonObjectDataSubRecord copy() {
rec.field_4_reserved1 = field_4_reserved1; return new CommonObjectDataSubRecord(this);
rec.field_5_reserved2 = field_5_reserved2;
rec.field_6_reserved3 = field_6_reserved3;
return rec;
} }
/** /**
* Get the object type field for the CommonObjectData record. * Get the object type field for the CommonObjectData record.
* *
* @return One of * @return One of
* OBJECT_TYPE_GROUP * OBJECT_TYPE_GROUP
* OBJECT_TYPE_LINE * OBJECT_TYPE_LINE
* OBJECT_TYPE_RECTANGLE * OBJECT_TYPE_RECTANGLE
@ -217,7 +225,7 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea
* Set the object type field for the CommonObjectData record. * Set the object type field for the CommonObjectData record.
* *
* @param field_1_objectType * @param field_1_objectType
* One of * One of
* OBJECT_TYPE_GROUP * OBJECT_TYPE_GROUP
* OBJECT_TYPE_LINE * OBJECT_TYPE_LINE
* OBJECT_TYPE_RECTANGLE * OBJECT_TYPE_RECTANGLE
@ -257,7 +265,7 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea
/** /**
* Get the object id field for the CommonObjectData record. * Get the object id field for the CommonObjectData record.
* *
* @return the object id field * @return the object id field
*/ */
public int getObjectId() public int getObjectId()
@ -267,7 +275,7 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea
/** /**
* Set the object id field for the CommonObjectData record. * Set the object id field for the CommonObjectData record.
* *
* @param field_2_objectId the object id field * @param field_2_objectId the object id field
*/ */
public void setObjectId(int field_2_objectId) 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. * Get the option field for the CommonObjectData record.
* *
* @return the option field * @return the option field
*/ */
public short getOption() public short getOption()
@ -287,7 +295,7 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea
/** /**
* Set the option field for the CommonObjectData record. * Set the option field for the CommonObjectData record.
* *
* @param field_3_option the option field * @param field_3_option the option field
*/ */
public void setOption(short field_3_option) 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. * Get the reserved1 field for the CommonObjectData record.
* *
* @return the reserved1 field * @return the reserved1 field
*/ */
public int getReserved1() public int getReserved1()
@ -307,7 +315,7 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea
/** /**
* Set the reserved1 field for the CommonObjectData record. * Set the reserved1 field for the CommonObjectData record.
* *
* @param field_4_reserved1 the reserved1 field * @param field_4_reserved1 the reserved1 field
*/ */
public void setReserved1(int field_4_reserved1) 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. * Get the reserved2 field for the CommonObjectData record.
* *
* @return the reserved2 field * @return the reserved2 field
*/ */
public int getReserved2() public int getReserved2()
@ -327,7 +335,7 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea
/** /**
* Set the reserved2 field for the CommonObjectData record. * Set the reserved2 field for the CommonObjectData record.
* *
* @param field_5_reserved2 the reserved2 field * @param field_5_reserved2 the reserved2 field
*/ */
public void setReserved2(int field_5_reserved2) 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. * Get the reserved3 field for the CommonObjectData record.
* *
* @return the reserved3 field * @return the reserved3 field
*/ */
public int getReserved3() public int getReserved3()
@ -347,7 +355,7 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea
/** /**
* Set the reserved3 field for the CommonObjectData record. * Set the reserved3 field for the CommonObjectData record.
* *
* @param field_6_reserved3 the reserved3 field * @param field_6_reserved3 the reserved3 field
*/ */
public void setReserved3(int field_6_reserved3) public void setReserved3(int field_6_reserved3)
@ -358,7 +366,7 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea
/** /**
* Sets the locked field value. * Sets the locked field value.
* true if object is locked when sheet has been protected * true if object is locked when sheet has been protected
* *
* @param value {@code 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) public void setLocked(boolean value)
@ -378,7 +386,7 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea
/** /**
* Sets the printable field value. * Sets the printable field value.
* object appears when printed * object appears when printed
* *
* @param value {@code true} if object appears when printed * @param value {@code true} if object appears when printed
*/ */
public void setPrintable(boolean value) public void setPrintable(boolean value)
@ -398,7 +406,7 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea
/** /**
* Sets the autofill field value. * Sets the autofill field value.
* whether object uses an automatic fill style * whether object uses an automatic fill style
* *
* @param value {@code true} if object uses an automatic fill style * @param value {@code true} if object uses an automatic fill style
*/ */
public void setAutofill(boolean value) public void setAutofill(boolean value)
@ -418,7 +426,7 @@ public final class CommonObjectDataSubRecord extends SubRecord implements Clonea
/** /**
* Sets the autoline field value. * Sets the autoline field value.
* whether object uses an automatic line style * whether object uses an automatic line style
* *
* @param value {@code true} if object uses an automatic line style * @param value {@code true} if object uses an automatic line style
*/ */
public void setAutoline(boolean value) public void setAutoline(boolean value)

View File

@ -19,23 +19,26 @@ package org.apache.poi.hssf.record;
import org.apache.poi.util.HexDump; import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.Removal;
/** /**
* Title: Continue Record(0x003C) - Helper class used primarily for SST Records <P> * 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> * handles overflow for prior record in the input stream; content is tailored to that prior record
* @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)
*/ */
public final class ContinueRecord extends StandardRecord implements Cloneable { public final class ContinueRecord extends StandardRecord {
public final static short sid = 0x003C; public static final short sid = 0x003C;
private byte[] _data; private byte[] _data;
public ContinueRecord(byte[] data) { public ContinueRecord(byte[] data) {
_data = data; _data = data;
} }
public ContinueRecord(ContinueRecord other) {
super(other);
_data = (other._data == null) ? null : other._data.clone();
}
protected int getDataSize() { protected int getDataSize() {
return _data.length; return _data.length;
} }
@ -70,7 +73,15 @@ public final class ContinueRecord extends StandardRecord implements Cloneable {
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public ContinueRecord clone() { public ContinueRecord clone() {
return new ContinueRecord(_data); return copy();
}
@Override
public ContinueRecord copy() {
return new ContinueRecord(this);
} }
} }

View File

@ -15,37 +15,36 @@
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
==================================================================== */ ==================================================================== */
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
/** /**
* Title: Country Record (aka WIN.INI country)<P> * Country Record (aka WIN.INI country) - used for localization<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> * 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 * @version 2.0-pre
*/ */
public final class CountryRecord public final class CountryRecord extends StandardRecord {
extends StandardRecord public static final short sid = 0x8c;
{
public final static short sid = 0x8c;
// 1 for US // 1 for US
private short field_1_default_country; private short field_1_default_country;
private short field_2_current_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_1_default_country = in.readShort();
field_2_current_country = in.readShort(); field_2_current_country = in.readShort();
} }
@ -120,4 +119,9 @@ public final class CountryRecord
{ {
return sid; return sid;
} }
@Override
public CountryRecord copy() {
return new CountryRecord(this);
}
} }

View File

@ -19,39 +19,15 @@ package org.apache.poi.hssf.record;
import org.apache.poi.util.HexDump; import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.Removal;
/** /**
* Title: DBCell Record (0x00D7)<p> * Used by Excel and other MS apps to quickly find rows in the sheets.
* 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)
*/ */
public final class DBCellRecord extends StandardRecord implements Cloneable { public final class DBCellRecord extends StandardRecord {
public final static short sid = 0x00D7; public static final short sid = 0x00D7;
public final static int BLOCK_SIZE = 32; public static final int BLOCK_SIZE = 32;
public static final class Builder {
private short[] _cellOffsets;
private int _nCellOffsets;
public Builder() {
_cellOffsets = new short[4];
}
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 * offset from the start of this DBCellRecord to the start of the first cell in
* the next DBCell block. * 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 int field_1_row_offset;
private final short[] field_2_cell_offsets; private final short[] field_2_cell_offsets;
DBCellRecord(int rowOffset, short[]cellOffsets) { public DBCellRecord(int rowOffset, short[] cellOffsets) {
field_1_row_offset = rowOffset; field_1_row_offset = rowOffset;
field_2_cell_offsets = cellOffsets; field_2_cell_offsets = cellOffsets;
} }
public DBCellRecord(RecordInputStream in) { public DBCellRecord(RecordInputStream in) {
field_1_row_offset = in.readUShort(); field_1_row_offset = in.readUShort();
int size = in.remaining(); int size = in.remaining();
field_2_cell_offsets = new short[ size / 2 ]; 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(); field_2_cell_offsets[ i ] = in.readShort();
} }
} }
public String toString() { public String toString() {
StringBuilder buffer = new StringBuilder(); StringBuilder buffer = new StringBuilder();
@ -91,8 +65,8 @@ public final class DBCellRecord extends StandardRecord implements Cloneable {
public void serialize(LittleEndianOutput out) { public void serialize(LittleEndianOutput out) {
out.writeInt(field_1_row_offset); out.writeInt(field_1_row_offset);
for (int k = 0; k < field_2_cell_offsets.length; k++) { for (short field_2_cell_offset : field_2_cell_offsets) {
out.writeShort(field_2_cell_offsets[ k ]); out.writeShort(field_2_cell_offset);
} }
} }
protected int getDataSize() { protected int getDataSize() {
@ -104,7 +78,15 @@ public final class DBCellRecord extends StandardRecord implements Cloneable {
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public DBCellRecord clone() { public DBCellRecord clone() {
return copy();
}
@Override
public DBCellRecord copy() {
// safe because immutable // safe because immutable
return this; return this;
} }

View File

@ -18,10 +18,10 @@
*/ */
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import java.io.ByteArrayInputStream;
import java.util.Arrays; import java.util.Arrays;
import org.apache.poi.util.IOUtils; import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.RecordFormatException; import org.apache.poi.util.RecordFormatException;
import org.apache.poi.util.StringUtil; import org.apache.poi.util.StringUtil;
@ -67,8 +67,7 @@ import org.apache.poi.util.StringUtil;
* *
* At the moment this class is read-only. * At the moment this class is read-only.
*/ */
public class DConRefRecord extends StandardRecord public class DConRefRecord extends StandardRecord {
{
//arbitrarily selected; may need to increase //arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000; private static final int MAX_RECORD_LENGTH = 100_000;
@ -108,54 +107,25 @@ public class DConRefRecord extends StandardRecord
*/ */
private byte[] _unused; 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. * Read constructor.
* *
* @param data byte array containing a DConRef Record, including the header. * @param data byte array containing a DConRef Record, including the header.
*/ */
public DConRefRecord(byte[] data) public DConRefRecord(byte[] data) {
{ this(bytesToRIStream(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);
} }
/** /**
@ -163,10 +133,10 @@ public class DConRefRecord extends StandardRecord
* *
* @param inStream RecordInputStream containing a DConRefRecord structure. * @param inStream RecordInputStream containing a DConRefRecord structure.
*/ */
public DConRefRecord(RecordInputStream inStream) public DConRefRecord(RecordInputStream inStream) {
{ if (inStream.getSid() != sid) {
if (inStream.getSid() != sid)
throw new RecordFormatException("Wrong sid: " + inStream.getSid()); throw new RecordFormatException("Wrong sid: " + inStream.getSid());
}
firstRow = inStream.readUShort(); firstRow = inStream.readUShort();
lastRow = inStream.readUShort(); lastRow = inStream.readUShort();
@ -174,17 +144,23 @@ public class DConRefRecord extends StandardRecord
lastCol = inStream.readUByte(); lastCol = inStream.readUByte();
charCount = inStream.readUShort(); charCount = inStream.readUShort();
charType = inStream.readUByte() & 0x01; //first bit only.
// byteLength depends on whether we are using single- or double-byte chars. // 7 bits reserved + 1 bit type - first bit only
int byteLength = charCount * (charType + 1); 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); path = IOUtils.safelyAllocate(byteLength, MAX_RECORD_LENGTH);
inStream.readFully(path); 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(); _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 //all of the path strings start with either 0x02 or 0x01 followed by zero or
//more of 0x01..0x08 //more of 0x01..0x08
int offset = 1; int offset = 1;
while (path[offset] < 0x20 && offset < path.length) while (offset < path.length && path[offset] < 0x20) {
{
offset++; offset++;
} }
String out = new String(Arrays.copyOfRange(path, offset, path.length), StringUtil.UTF8); String out = new String(Arrays.copyOfRange(path, offset, path.length), StringUtil.UTF8);
@ -310,8 +285,17 @@ public class DConRefRecord extends StandardRecord
*/ */
public boolean isExternalRef() public boolean isExternalRef()
{ {
if (path[0] == 0x01) return path[0] == 0x01;
return true; }
return false;
@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;
} }
} }

View File

@ -23,21 +23,26 @@ import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
/** /**
* Title: Double Stream Flag Record (0x0161)<p> * Tells if this is a double stream file. (never applies to HSSF generated files)<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> * Double Stream files contain both BIFF8 and BIFF7 workbooks.
* REFERENCE: PG 305 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)
*/ */
public final class DSFRecord extends StandardRecord { 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 static final BitField biff5BookStreamFlag = BitFieldFactory.getInstance(0x0001);
private int _options; private int _options;
private DSFRecord(DSFRecord other) {
super(other);
_options = other._options;
}
private DSFRecord(int options) { private DSFRecord(int options) {
_options = options; _options = options;
} }
public DSFRecord(boolean isBiff5BookStreamPresent) { public DSFRecord(boolean isBiff5BookStreamPresent) {
this(0); this(0);
_options = biff5BookStreamFlag.setBoolean(0, isBiff5BookStreamPresent); _options = biff5BookStreamFlag.setBoolean(0, isBiff5BookStreamPresent);
@ -71,4 +76,9 @@ public final class DSFRecord extends StandardRecord {
public short getSid() { public short getSid() {
return sid; return sid;
} }
@Override
public DSFRecord copy() {
return new DSFRecord(this);
}
} }

View File

@ -18,14 +18,13 @@
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.Removal;
/** /**
* Title: DATAVALIDATIONS Record (0x01B2)<p> * This record is the list header of all data validation records (0x01BE) in the current sheet.
* Description: used in data validation ;
* 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 class DVALRecord extends StandardRecord {
public final static short sid = 0x01B2; public static final short sid = 0x01B2;
/** Options of the DVAL */ /** Options of the DVAL */
private short field_1_options; private short field_1_options;
@ -47,12 +46,21 @@ public final class DVALRecord extends StandardRecord implements Cloneable {
field_5_dv_no = 0x00000000; 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) { public DVALRecord(RecordInputStream in) {
field_1_options = in.readShort(); field_1_options = in.readShort();
field_2_horiz_pos = in.readInt(); field_2_horiz_pos = in.readInt();
field_3_vert_pos = in.readInt(); field_3_vert_pos = in.readInt();
field_cbo_id = in.readInt(); field_cbo_id = in.readInt();
field_5_dv_no = 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) { public void serialize(LittleEndianOutput out) {
out.writeShort(getOptions()); out.writeShort(getOptions());
out.writeInt(getHorizontalPos()); out.writeInt(getHorizontalPos());
out.writeInt(getVerticalPos()); out.writeInt(getVerticalPos());
@ -158,14 +165,16 @@ public final class DVALRecord extends StandardRecord implements Cloneable {
return sid; return sid;
} }
@Override @Override
public DVALRecord clone() { @SuppressWarnings("squid:S2975")
DVALRecord rec = new DVALRecord(); @Deprecated
rec.field_1_options = field_1_options; @Removal(version = "5.0.0")
rec.field_2_horiz_pos = field_2_horiz_pos; public DVALRecord clone() {
rec.field_3_vert_pos = field_3_vert_pos; return copy();
rec.field_cbo_id = field_cbo_id; }
rec.field_5_dv_no = field_5_dv_no;
return rec; @Override
public DVALRecord copy() {
return new DVALRecord(this);
} }
} }

View File

@ -25,46 +25,23 @@ import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList; import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.util.BitField; import org.apache.poi.util.BitField;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.Removal;
import org.apache.poi.util.StringUtil; import org.apache.poi.util.StringUtil;
/** /**
* Title: DATAVALIDATION Record (0x01BE)<p> * This record stores data validation settings and a list of cell ranges which contain these settings.
* Description: This record stores data validation settings and a list of cell ranges * The data validation settings of a sheet are stored in a sequential list of DV records.
* which contain these settings. The data validation settings of a sheet * This list is followed by DVAL record(s)
* 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 class DVRecord extends StandardRecord {
public final static short sid = 0x01BE; public static final short sid = 0x01BE;
/** the unicode string used for error/prompt title/text when not present */ /** the unicode string used for error/prompt title/text when not present */
private static final UnicodeString NULL_TEXT_STRING = new UnicodeString("\0"); private static final UnicodeString NULL_TEXT_STRING = new UnicodeString("\0");
/** Option flags */
private int _option_flags;
/** Title of the prompt box, cannot be longer than 32 chars */
private UnicodeString _promptTitle;
/** Title of the error box, cannot be longer than 32 chars */
private UnicodeString _errorTitle;
/** Text of the prompt box, cannot be longer than 255 chars */
private UnicodeString _promptText;
/** Text of the error box, cannot be longer than 255 chars */
private 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;
/** 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;
/** Cell range address list with all affected ranges */
private CellRangeAddressList _regions;
/** /**
* Option flags field * Option flags field
* *
* @see HSSFDataValidation utility class * @see HSSFDataValidation utility class
*/ */
private static final BitField opt_data_type = new BitField(0x0000000F); private static final BitField opt_data_type = new BitField(0x0000000F);
@ -76,13 +53,49 @@ public final class DVRecord extends StandardRecord implements Cloneable {
private static final BitField opt_show_error_on_invalid_value = new BitField(0x00080000); private static final BitField opt_show_error_on_invalid_value = new BitField(0x00080000);
private static final BitField opt_condition_operator = new BitField(0x00700000); 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 final UnicodeString _promptTitle;
/** Title of the error box, cannot be longer than 32 chars */
private final UnicodeString _errorTitle;
/** Text of the prompt box, cannot be longer than 255 chars */
private final UnicodeString _promptText;
/** Text of the error box, cannot be longer than 255 chars */
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 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 final Formula _formula2;
/** Cell range address list with all affected ranges */
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, public DVRecord(int validationType, int operator, int errorStyle, boolean emptyCellAllowed,
boolean suppressDropDownArrow, boolean isExplicitList, boolean suppressDropDownArrow, boolean isExplicitList,
boolean showPromptBox, String promptTitle, String promptText, boolean showPromptBox, String promptTitle, String promptText,
boolean showErrorBox, String errorTitle, String errorText, boolean showErrorBox, String errorTitle, String errorText,
Ptg[] formula1, Ptg[] formula2, Ptg[] formula1, Ptg[] formula2,
CellRangeAddressList regions) { CellRangeAddressList regions) {
// check length-limits // check length-limits
if(promptTitle != null && promptTitle.length() > 32) { if(promptTitle != null && promptTitle.length() > 32) {
throw new IllegalStateException("Prompt-title cannot be longer than 32 characters, but had: " + promptTitle); 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) { public DVRecord(RecordInputStream in) {
_option_flags = in.readInt(); _option_flags = in.readInt();
_promptTitle = readUnicodeString(in); _promptTitle = readUnicodeString(in);
@ -144,7 +156,6 @@ public final class DVRecord extends StandardRecord implements Cloneable {
_regions = new CellRangeAddressList(in); _regions = new CellRangeAddressList(in);
} }
// --> start option flags
/** /**
* @return the condition data type * @return the condition data type
* @see org.apache.poi.ss.usermodel.DataValidationConstraint.ValidationType * @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) { private static void appendFormula(StringBuilder sb, String label, Formula f) {
sb.append(label); sb.append(label);
if (f == null) { if (f == null) {
sb.append("<empty>\n"); sb.append("<empty>\n");
return; return;
@ -291,7 +302,7 @@ public final class DVRecord extends StandardRecord implements Cloneable {
public void serialize(LittleEndianOutput out) { public void serialize(LittleEndianOutput out) {
out.writeInt(_option_flags); out.writeInt(_option_flags);
serializeUnicodeString(_promptTitle, out); serializeUnicodeString(_promptTitle, out);
serializeUnicodeString(_errorTitle, out); serializeUnicodeString(_errorTitle, out);
serializeUnicodeString(_promptText, out); serializeUnicodeString(_promptText, out);
@ -299,19 +310,19 @@ public final class DVRecord extends StandardRecord implements Cloneable {
out.writeShort(_formula1.getEncodedTokenSize()); out.writeShort(_formula1.getEncodedTokenSize());
out.writeShort(_not_used_1); out.writeShort(_not_used_1);
_formula1.serializeTokens(out); _formula1.serializeTokens(out);
out.writeShort(_formula2.getEncodedTokenSize()); out.writeShort(_formula2.getEncodedTokenSize());
out.writeShort(_not_used_2); out.writeShort(_not_used_2);
_formula2.serializeTokens(out); _formula2.serializeTokens(out);
_regions.serialize(out); _regions.serialize(out);
} }
/** /**
* When entered via the UI, Excel translates empty string into "\0" * 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), * 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 * 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". * Excel UI and encode 'not present' as "\0".
*/ */
private static UnicodeString resolveTitleText(String str) { private static UnicodeString resolveTitleText(String str) {
if (str == null || str.length() < 1) { if (str == null || str.length() < 1) {
@ -354,13 +365,18 @@ public final class DVRecord extends StandardRecord implements Cloneable {
public short getSid() { public short getSid() {
return sid; return sid;
} }
/**
* Clones the object. Uses serialisation, as the
* contents are somewhat complex
*/
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public DVRecord clone() { public DVRecord clone() {
return (DVRecord)cloneViaReserialise(); return copy();
}
/** Clones the object. */
@Override
public DVRecord copy() {
return new DVRecord(this);
} }
} }

View File

@ -15,33 +15,31 @@
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
==================================================================== */ ==================================================================== */
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
/** /**
* Title: Date Window 1904 Flag record <P> * Flag specifying whether 1904 date windowing is used.
* 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)
* @version 2.0-pre * @version 2.0-pre
*/ */
public final class DateWindow1904Record public final class DateWindow1904Record extends StandardRecord {
extends StandardRecord public static final short sid = 0x22;
{
public final static short sid = 0x22;
private short field_1_window;
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(); field_1_window = in.readShort();
} }
@ -88,4 +86,9 @@ public final class DateWindow1904Record
{ {
return sid; return sid;
} }
@Override
public DateWindow1904Record copy() {
return new DateWindow1904Record(this);
}
} }

View File

@ -18,30 +18,32 @@
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.Removal;
/** /**
* Title: Default Column Width Record (0x0055) <P> * Specifies the default width for columns that have no specific width set.
* 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)
* @version 2.0-pre * @version 2.0-pre
*/ */
public final class DefaultColWidthRecord extends StandardRecord implements Cloneable { public final class DefaultColWidthRecord extends StandardRecord {
public final static short sid = 0x0055; public static final short sid = 0x0055;
private int field_1_col_width;
/** /**
* The default column width is 8 characters * 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; 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) public DefaultColWidthRecord(RecordInputStream in)
{ {
field_1_col_width = in.readUShort(); field_1_col_width = in.readUShort();
@ -92,9 +94,15 @@ public final class DefaultColWidthRecord extends StandardRecord implements Clone
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public DefaultColWidthRecord clone() { public DefaultColWidthRecord clone() {
DefaultColWidthRecord rec = new DefaultColWidthRecord(); return copy();
rec.field_1_col_width = field_1_col_width; }
return rec;
@Override
public DefaultColWidthRecord copy() {
return new DefaultColWidthRecord(this);
} }
} }

View File

@ -1,4 +1,3 @@
/* ==================================================================== /* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with contributor license agreements. See the NOTICE file distributed with
@ -20,35 +19,35 @@
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.Removal;
/** /**
* Title: Default Row Height Record * Row height for rows with undefined or not explicitly defined heights.
* 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)
* @version 2.0-pre * @version 2.0-pre
*/ */
public final class DefaultRowHeightRecord extends StandardRecord implements Cloneable { public final class DefaultRowHeightRecord extends StandardRecord {
public final static short sid = 0x225; public static final short sid = 0x225;
private short field_1_option_flags;
private short field_2_row_height;
/** /** 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 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_1_option_flags = 0x0000;
field_2_row_height = DEFAULT_ROW_HEIGHT; 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_1_option_flags = in.readShort();
field_2_row_height = in.readShort(); field_2_row_height = in.readShort();
} }
@ -121,10 +120,15 @@ public final class DefaultRowHeightRecord extends StandardRecord implements Clon
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public DefaultRowHeightRecord clone() { public DefaultRowHeightRecord clone() {
DefaultRowHeightRecord rec = new DefaultRowHeightRecord(); return copy();
rec.field_1_option_flags = field_1_option_flags; }
rec.field_2_row_height = field_2_row_height;
return rec; @Override
public DefaultRowHeightRecord copy() {
return new DefaultRowHeightRecord(this);
} }
} }

View File

@ -18,15 +18,12 @@
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.Removal;
/** /** Controls the accuracy of the calculations */
* Title: Delta Record (0x0010)<p> public final class DeltaRecord extends StandardRecord {
* Description: controls the accuracy of the calculations<p> public static final short sid = 0x0010;
* REFERENCE: PG 303 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) public static final double DEFAULT_VALUE = 0.0010;
*/
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
// a double is an IEEE 8-byte float...damn IEEE and their goofy standards an // a double is an IEEE 8-byte float...damn IEEE and their goofy standards an
// ambiguous numeric identifiers // ambiguous numeric identifiers
@ -36,6 +33,11 @@ public final class DeltaRecord extends StandardRecord implements Cloneable {
field_1_max_change = maxChange; field_1_max_change = maxChange;
} }
public DeltaRecord(DeltaRecord other) {
super(other);
field_1_max_change = other.field_1_max_change;
}
public DeltaRecord(RecordInputStream in) { public DeltaRecord(RecordInputStream in) {
field_1_max_change = in.readDouble(); field_1_max_change = in.readDouble();
} }
@ -70,7 +72,15 @@ public final class DeltaRecord extends StandardRecord implements Cloneable {
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public DeltaRecord clone() { public DeltaRecord clone() {
return copy();
}
@Override
public DeltaRecord copy() {
// immutable // immutable
return this; return this;
} }

View File

@ -15,41 +15,44 @@
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
==================================================================== */ ==================================================================== */
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
import org.apache.poi.util.Removal;
/** /**
* Title: Dimensions Record<P> * Provides the minumum and maximum bounds of a sheet.
* 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)
* @version 2.0-pre * @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); 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_1_first_row;
private int field_2_last_row; // plus 1 private int field_2_last_row; // plus 1
private short field_3_first_col; private short field_3_first_col;
private short field_4_last_col; private short field_4_last_col;
private short field_5_zero; // must be 0 (reserved) 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_1_first_row = in.readInt();
field_2_last_row = in.readInt(); field_2_last_row = in.readInt();
field_3_first_col = in.readShort(); field_3_first_col = in.readShort();
@ -179,13 +182,15 @@ public final class DimensionsRecord extends StandardRecord implements Cloneable
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public DimensionsRecord clone() { public DimensionsRecord clone() {
DimensionsRecord rec = new DimensionsRecord(); return copy();
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; @Override
rec.field_4_last_col = field_4_last_col; public DimensionsRecord copy() {
rec.field_5_zero = field_5_zero; return new DimensionsRecord(this);
return rec;
} }
} }

View File

@ -17,13 +17,13 @@
package org.apache.poi.hssf.record; 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.EscherRecord;
import org.apache.poi.ddf.NullEscherSerializationListener; import org.apache.poi.ddf.NullEscherSerializationListener;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
import java.util.Iterator;
import java.util.List;
public final class DrawingGroupRecord extends AbstractEscherHolderRecord { public final class DrawingGroupRecord extends AbstractEscherHolderRecord {
public static final short sid = 0xEB; public static final short sid = 0xEB;
@ -31,12 +31,13 @@ public final class DrawingGroupRecord extends AbstractEscherHolderRecord {
static final int MAX_RECORD_SIZE = 8228; static final int MAX_RECORD_SIZE = 8228;
private static final int MAX_DATA_SIZE = MAX_RECORD_SIZE - 4; 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 ); super( in );
} }
@ -136,4 +137,9 @@ public final class DrawingGroupRecord extends AbstractEscherHolderRecord {
LittleEndian.putShort(data, 0 + offset, ContinueRecord.sid); LittleEndian.putShort(data, 0 + offset, ContinueRecord.sid);
LittleEndian.putShort(data, 2 + offset, (short) sizeExcludingHeader); LittleEndian.putShort(data, 2 + offset, (short) sizeExcludingHeader);
} }
@Override
public DrawingGroupRecord copy() {
return new DrawingGroupRecord(this);
}
} }

View File

@ -18,10 +18,9 @@
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
/** import org.apache.poi.util.Removal;
* DrawingRecord (0x00EC)
*/ public final class DrawingRecord extends StandardRecord {
public final class DrawingRecord extends StandardRecord implements Cloneable {
public static final short sid = 0x00EC; public static final short sid = 0x00EC;
private static final byte[] EMPTY_BYTE_ARRAY = {}; private static final byte[] EMPTY_BYTE_ARRAY = {};
@ -33,6 +32,13 @@ public final class DrawingRecord extends StandardRecord implements Cloneable {
recordData = EMPTY_BYTE_ARRAY; 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) { public DrawingRecord(RecordInputStream in) {
recordData = in.readRemainder(); recordData = in.readRemainder();
} }
@ -69,20 +75,21 @@ public final class DrawingRecord extends StandardRecord implements Cloneable {
recordData = thedata; 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 * Cloning of drawing records must be executed through HSSFPatriarch, because all id's must be changed
* @return cloned drawing records * @return cloned drawing records
*/ */
@Override @Override
public DrawingRecord clone() { public DrawingRecord copy() {
DrawingRecord rec = new DrawingRecord(); return new DrawingRecord(this);
rec.recordData = recordData.clone();
if (contd != null) {
// TODO - this code probably never executes
rec.contd = contd.clone();
}
return rec;
} }
@Override @Override

View File

@ -26,8 +26,10 @@ import java.io.ByteArrayInputStream;
public final class DrawingRecordForBiffViewer extends AbstractEscherHolderRecord { public final class DrawingRecordForBiffViewer extends AbstractEscherHolderRecord {
public static final short sid = 0xEC; public static final short sid = 0xEC;
public DrawingRecordForBiffViewer() public DrawingRecordForBiffViewer() {}
{
public DrawingRecordForBiffViewer(DrawingRecordForBiffViewer other) {
super(other);
} }
public DrawingRecordForBiffViewer( RecordInputStream in) public DrawingRecordForBiffViewer( RecordInputStream in)
@ -59,4 +61,9 @@ public final class DrawingRecordForBiffViewer extends AbstractEscherHolderRecord
{ {
return sid; return sid;
} }
@Override
public DrawingRecordForBiffViewer copy() {
return new DrawingRecordForBiffViewer(this);
}
} }

View File

@ -20,13 +20,14 @@ package org.apache.poi.hssf.record;
import org.apache.poi.util.HexDump; import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianInput;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.Removal;
/** /**
* MsoDrawingSelection (0x00ED)<p> * MsoDrawingSelection (0x00ED)<p>
* Reference: * Reference:
* [MS-OGRAPH].pdf sec 2.4.69 * [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; 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 _type;
private final int _length; private final int _length;
public OfficeArtRecordHeader(OfficeArtRecordHeader other) {
_verAndInstance = other._verAndInstance;
_type = other._type;
_length = other._length;
}
public OfficeArtRecordHeader(LittleEndianInput in) { public OfficeArtRecordHeader(LittleEndianInput in) {
_verAndInstance = in.readUShort(); _verAndInstance = in.readUShort();
_type = in.readUShort(); _type = in.readUShort();
@ -57,11 +64,10 @@ public final class DrawingSelectionRecord extends StandardRecord implements Clon
} }
public String debugFormatAsString() { public String debugFormatAsString() {
StringBuilder sb = new StringBuilder(32); return
sb.append("ver+inst=").append(HexDump.shortToHex(_verAndInstance)); "ver+inst=" + HexDump.shortToHex(_verAndInstance) +
sb.append(" type=").append(HexDump.shortToHex(_type)); " type=" + HexDump.shortToHex(_type) +
sb.append(" len=").append(HexDump.intToHex(_length)); " len=" + HexDump.intToHex(_length);
return sb.toString();
} }
} }
@ -93,7 +99,7 @@ public final class DrawingSelectionRecord extends StandardRecord implements Clon
} }
protected int getDataSize() { protected int getDataSize() {
return OfficeArtRecordHeader.ENCODED_SIZE return OfficeArtRecordHeader.ENCODED_SIZE
+ 12 // 3 int fields + 12 // 3 int fields
+ _shapeIds.length * 4; + _shapeIds.length * 4;
} }
@ -109,7 +115,15 @@ public final class DrawingSelectionRecord extends StandardRecord implements Clon
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public DrawingSelectionRecord clone() { public DrawingSelectionRecord clone() {
return copy();
}
@Override
public DrawingSelectionRecord copy() {
// currently immutable // currently immutable
return this; return this;
} }

View File

@ -18,33 +18,25 @@
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.Removal;
/** /**
* End Of File record. * Marks the end of records belonging to a particular object in the HSSF File
* <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)
* @version 2.0-pre * @version 2.0-pre
*/ */
public final class EOFRecord extends StandardRecord implements Cloneable { public final class EOFRecord extends StandardRecord {
public final static short sid = 0x0A; public static final short sid = 0x0A;
public static final int ENCODED_SIZE = 4; public static final int ENCODED_SIZE = 4;
public static final EOFRecord instance = new EOFRecord(); public static final EOFRecord instance = new EOFRecord();
private EOFRecord() { private EOFRecord() {}
// no data fields
}
/** /**
* @param in unused (since this record has no data) * @param in unused (since this record has no data)
*/ */
public EOFRecord(RecordInputStream in) public EOFRecord(RecordInputStream in) {}
{
}
public String toString() public String toString()
{ {
@ -68,7 +60,15 @@ public final class EOFRecord extends StandardRecord implements Cloneable {
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public EOFRecord clone() { public EOFRecord clone() {
return copy();
}
@Override
public EOFRecord copy() {
return instance; return instance;
} }
} }

View File

@ -33,6 +33,7 @@ import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
import org.apache.poi.util.RecordFormatException; import org.apache.poi.util.RecordFormatException;
import org.apache.poi.util.Removal;
import org.apache.poi.util.StringUtil; 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 * A sub-record within the OBJ record which stores a reference to an object
* stored in a separate entry within the OLE2 compound file. * 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); private static POILogger logger = POILogFactory.getLogger(EmbeddedObjectRefSubRecord.class);
//arbitrarily selected; may need to increase //arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000; 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; field_4_ole_classname = null;
} }
public short getSid() { public EmbeddedObjectRefSubRecord(EmbeddedObjectRefSubRecord other) {
return sid; 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) { public EmbeddedObjectRefSubRecord(LittleEndianInput in, int size) {
@ -158,6 +167,10 @@ public final class EmbeddedObjectRefSubRecord extends SubRecord implements Clone
field_6_unknown = readRawData(in, remaining); field_6_unknown = readRawData(in, remaining);
} }
public short getSid() {
return sid;
}
private static Ptg readRefPtg(byte[] formulaRawBytes) { private static Ptg readRefPtg(byte[] formulaRawBytes) {
LittleEndianInput in = new LittleEndianInputStream(new ByteArrayInputStream(formulaRawBytes)); LittleEndianInput in = new LittleEndianInputStream(new ByteArrayInputStream(formulaRawBytes));
byte ptgSid = in.readByte(); byte ptgSid = in.readByte();
@ -310,8 +323,16 @@ public final class EmbeddedObjectRefSubRecord extends SubRecord implements Clone
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public EmbeddedObjectRefSubRecord clone() { public EmbeddedObjectRefSubRecord clone() {
return this; // TODO proper clone return copy();
}
@Override
public EmbeddedObjectRefSubRecord copy() {
return new EmbeddedObjectRefSubRecord(this);
} }
public String toString() { public String toString() {
@ -339,15 +360,15 @@ public final class EmbeddedObjectRefSubRecord extends SubRecord implements Clone
sb.append("[/ftPictFmla]"); sb.append("[/ftPictFmla]");
return sb.toString(); return sb.toString();
} }
public void setUnknownFormulaData(byte[] formularData) { public void setUnknownFormulaData(byte[] formularData) {
field_2_unknownFormulaData = formularData; field_2_unknownFormulaData = formularData;
} }
public void setOleClassname(String oleClassname) { public void setOleClassname(String oleClassname) {
field_4_ole_classname = oleClassname; field_4_ole_classname = oleClassname;
} }
public void setStorageId(int storageId) { public void setStorageId(int storageId) {
field_5_stream_id = storageId; field_5_stream_id = storageId;
} }

View File

@ -14,27 +14,25 @@
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
==================================================================== */ ==================================================================== */
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianInput;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.RecordFormatException; import org.apache.poi.util.RecordFormatException;
import org.apache.poi.util.Removal;
/** /**
* ftEnd (0x0000)<p> * ftEnd (0x0000)<p>
* *
* The end data record is used to denote the end of the subrecords. * 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) // 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; private static final int ENCODED_SIZE = 0;
public EndSubRecord() public EndSubRecord() {}
{
}
/** /**
* @param in unused (since this record has no data) * @param in unused (since this record has no data)
@ -76,8 +74,15 @@ public final class EndSubRecord extends SubRecord implements Cloneable {
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public EndSubRecord clone() { public EndSubRecord clone() {
return copy();
}
@Override
public EndSubRecord copy() {
return new EndSubRecord(); return new EndSubRecord();
} }
} }

View File

@ -85,7 +85,7 @@ import org.apache.poi.util.RecordFormatException;
public final class EscherAggregate extends AbstractEscherHolderRecord { public final class EscherAggregate extends AbstractEscherHolderRecord {
public static final short sid = 9876; // not a real sid - dummy value 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 //arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000_000; 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. * @return Returns the current sid.
*/ */
@ -814,4 +821,9 @@ public final class EscherAggregate extends AbstractEscherHolderRecord {
public void removeTailRecord(NoteRecord note) { public void removeTailRecord(NoteRecord note) {
tailRec.remove(note.getShapeId()); tailRec.remove(note.getShapeId());
} }
@Override
public EscherAggregate copy() {
return new EscherAggregate(this);
}
} }

View File

@ -17,28 +17,27 @@
package org.apache.poi.hssf.record; 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.ContinuableRecord;
import org.apache.poi.hssf.record.cont.ContinuableRecordOutput; import org.apache.poi.hssf.record.cont.ContinuableRecordOutput;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import java.util.ArrayList;
/** /**
* Title: Extended Static String Table (0x00FF)<p> * Extended Static String Table (0x00FF)<p>
* Description: This record is used for a quick lookup into the SST record. This * This record is used for a quick lookup into the SST record. This record breaks the SST table
* record breaks the SST table into a set of buckets. The offsets * into a set of buckets. The offsets to these buckets within the SST record are kept as well as
* to these buckets within the SST record are kept as well as the * the position relative to the start of the SST record.
* position relative to the start of the SST record.<p>
* REFERENCE: PG 313 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)
*/ */
public final class ExtSSTRecord extends ContinuableRecord { 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; public static final int DEFAULT_BUCKET_SIZE = 8;
//Can't seem to find this documented but from the biffviewer it is clear that //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. //Excel only records the indexes for the first 128 buckets.
public static final int MAX_BUCKETS = 128; public static final int MAX_BUCKETS = 128;
public static final class InfoSubRecord { public static final class InfoSubRecord {
public static final int ENCODED_SIZE = 8; public static final int ENCODED_SIZE = 8;
private int field_1_stream_pos; // stream pointer to the SST record 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 * Creates new ExtSSTInfoSubRecord
* *
* @param streamPos stream pointer to the SST record * @param streamPos stream pointer to the SST record
* @param bucketSstOffset ... don't really understand this yet * @param bucketSstOffset ... don't really understand this yet
*/ */
@ -57,6 +56,12 @@ public final class ExtSSTRecord extends ContinuableRecord {
field_2_bucket_sst_offset = bucketSstOffset; 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) public InfoSubRecord(RecordInputStream in)
{ {
field_1_stream_pos = in.readInt(); field_1_stream_pos = in.readInt();
@ -78,8 +83,8 @@ public final class ExtSSTRecord extends ContinuableRecord {
out.writeShort(field_3_zero); out.writeShort(field_3_zero);
} }
} }
private short _stringsPerBucket; private short _stringsPerBucket;
private InfoSubRecord[] _sstInfos; private InfoSubRecord[] _sstInfos;
@ -89,6 +94,12 @@ public final class ExtSSTRecord extends ContinuableRecord {
_sstInfos = new InfoSubRecord[0]; _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) { public ExtSSTRecord(RecordInputStream in) {
_stringsPerBucket = in.readShort(); _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 * Given a number of strings (in the sst), returns the size of the extsst record
* *
* @param numStrings the number of strings * @param numStrings the number of strings
* *
* @return the size of the extsst record * @return the size of the extsst record
*/ */
public static int getRecordSizeForStrings(int numStrings) { public static int getRecordSizeForStrings(int numStrings) {
@ -181,4 +192,9 @@ public final class ExtSSTRecord extends ContinuableRecord {
_sstInfos[i] = new InfoSubRecord(bucketAbsoluteOffsets[i], bucketRelativeOffsets[i]); _sstInfos[i] = new InfoSubRecord(bucketAbsoluteOffsets[i], bucketRelativeOffsets[i]);
} }
} }
@Override
public ExtSSTRecord copy() {
return new ExtSSTRecord(this);
}
} }

View File

@ -14,7 +14,7 @@
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
==================================================================== */ ==================================================================== */
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
@ -23,179 +23,164 @@ import org.apache.poi.util.BitFieldFactory;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
/** /**
* Title: Extended Format Record * Probably one of the more complex records.<p>
* Description: Probably one of the more complex records. There are two breeds: * There are two breeds: Style and Cell.<p>
* Style and Cell. * It should be noted that fields in the extended format record are somewhat arbitrary.
*<P> * Almost all of the fields are bit-level, but we name them as best as possible by functional group.
* It should be noted that fields in the extended format record are * In some places this is better than others.
* 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>
* *
* REFERENCE: PG 426 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)
* @since 2.0-pre * @since 2.0-pre
*/ */
public final class ExtendedFormatRecord public final class ExtendedFormatRecord extends StandardRecord {
extends StandardRecord public static final short sid = 0xE0;
{
public static final short sid = 0xE0;
// null constant // null constant
public static final short NULL = (short)0xfff0; public static final short NULL = (short)0xfff0;
// xf type // xf type
public static final short XF_STYLE = 1; public static final short XF_STYLE = 1;
public static final short XF_CELL = 0; public static final short XF_CELL = 0;
// borders // borders
public static final short NONE = 0x0; public static final short NONE = 0x0;
public static final short THIN = 0x1; public static final short THIN = 0x1;
public static final short MEDIUM = 0x2; public static final short MEDIUM = 0x2;
public static final short DASHED = 0x3; public static final short DASHED = 0x3;
public static final short DOTTED = 0x4; public static final short DOTTED = 0x4;
public static final short THICK = 0x5; public static final short THICK = 0x5;
public static final short DOUBLE = 0x6; public static final short DOUBLE = 0x6;
public static final short HAIR = 0x7; public static final short HAIR = 0x7;
public static final short MEDIUM_DASHED = 0x8; public static final short MEDIUM_DASHED = 0x8;
public static final short DASH_DOT = 0x9; public static final short DASH_DOT = 0x9;
public static final short MEDIUM_DASH_DOT = 0xA; public static final short MEDIUM_DASH_DOT = 0xA;
public static final short DASH_DOT_DOT = 0xB; public static final short DASH_DOT_DOT = 0xB;
public static final short MEDIUM_DASH_DOT_DOT = 0xC; public static final short MEDIUM_DASH_DOT_DOT = 0xC;
public static final short SLANTED_DASH_DOT = 0xD; public static final short SLANTED_DASH_DOT = 0xD;
// alignment // alignment
public static final short GENERAL = 0x0; public static final short GENERAL = 0x0;
public static final short LEFT = 0x1; public static final short LEFT = 0x1;
public static final short CENTER = 0x2; public static final short CENTER = 0x2;
public static final short RIGHT = 0x3; public static final short RIGHT = 0x3;
public static final short FILL = 0x4; public static final short FILL = 0x4;
public static final short JUSTIFY = 0x5; public static final short JUSTIFY = 0x5;
public static final short CENTER_SELECTION = 0x6; public static final short CENTER_SELECTION = 0x6;
// vertical alignment // vertical alignment
public static final short VERTICAL_TOP = 0x0; public static final short VERTICAL_TOP = 0x0;
public static final short VERTICAL_CENTER = 0x1; public static final short VERTICAL_CENTER = 0x1;
public static final short VERTICAL_BOTTOM = 0x2; public static final short VERTICAL_BOTTOM = 0x2;
public static final short VERTICAL_JUSTIFY = 0x3; public static final short VERTICAL_JUSTIFY = 0x3;
// fill // fill
public static final short NO_FILL = 0 ; public static final short NO_FILL = 0;
public static final short SOLID_FILL = 1 ; public static final short SOLID_FILL = 1;
public static final short FINE_DOTS = 2 ; public static final short FINE_DOTS = 2;
public static final short ALT_BARS = 3 ; public static final short ALT_BARS = 3;
public static final short SPARSE_DOTS = 4 ; public static final short SPARSE_DOTS = 4;
public static final short THICK_HORZ_BANDS = 5 ; public static final short THICK_HORZ_BANDS = 5;
public static final short THICK_VERT_BANDS = 6 ; public static final short THICK_VERT_BANDS = 6;
public static final short THICK_BACKWARD_DIAG = 7 ; public static final short THICK_BACKWARD_DIAG = 7;
public static final short THICK_FORWARD_DIAG = 8 ; public static final short THICK_FORWARD_DIAG = 8;
public static final short BIG_SPOTS = 9 ; public static final short BIG_SPOTS = 9;
public static final short BRICKS = 10 ; public static final short BRICKS = 10;
public static final short THIN_HORZ_BANDS = 11 ; public static final short THIN_HORZ_BANDS = 11;
public static final short THIN_VERT_BANDS = 12 ; public static final short THIN_VERT_BANDS = 12;
public static final short THIN_BACKWARD_DIAG = 13 ; public static final short THIN_BACKWARD_DIAG = 13;
public static final short THIN_FORWARD_DIAG = 14 ; public static final short THIN_FORWARD_DIAG = 14;
public static final short SQUARES = 15 ; public static final short SQUARES = 15;
public static final short DIAMONDS = 16 ; 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
// field_3_cell_options bit map // field_3_cell_options bit map
private static final BitField _locked = BitFieldFactory.getInstance(0x0001); private static final BitField _locked = bf(0x0001);
private static final BitField _hidden = BitFieldFactory.getInstance(0x0002); private static final BitField _hidden = bf(0x0002);
private static final BitField _xf_type = BitFieldFactory.getInstance(0x0004); private static final BitField _xf_type = bf(0x0004);
private static final BitField _123_prefix = BitFieldFactory.getInstance(0x0008); private static final BitField _123_prefix = bf(0x0008);
private static final BitField _parent_index = BitFieldFactory.getInstance(0xFFF0); private static final BitField _parent_index = bf(0xFFF0);
private short field_3_cell_options;
// field_4_alignment_options bit map // field_4_alignment_options bit map
private static final BitField _alignment = BitFieldFactory.getInstance(0x0007); private static final BitField _alignment = bf(0x0007);
private static final BitField _wrap_text = BitFieldFactory.getInstance(0x0008); private static final BitField _wrap_text = bf(0x0008);
private static final BitField _vertical_alignment = BitFieldFactory.getInstance(0x0070); private static final BitField _vertical_alignment = bf(0x0070);
private static final BitField _justify_last = BitFieldFactory.getInstance(0x0080); private static final BitField _justify_last = bf(0x0080);
private static final BitField _rotation = BitFieldFactory.getInstance(0xFF00); private static final BitField _rotation = bf(0xFF00);
private short field_4_alignment_options;
// field_5_indention_options // field_5_indention_options
private static final BitField _indent = private static final BitField _indent = bf(0x000F);
BitFieldFactory.getInstance(0x000F); private static final BitField _shrink_to_fit = bf(0x0010);
private static final BitField _shrink_to_fit = private static final BitField _merge_cells = bf(0x0020);
BitFieldFactory.getInstance(0x0010); private static final BitField _reading_order = bf(0x00C0);
private static final BitField _merge_cells =
BitFieldFactory.getInstance(0x0020);
private static final BitField _reading_order =
BitFieldFactory.getInstance(0x00C0);
// apparently bits 8 and 9 are unused // apparently bits 8 and 9 are unused
private static final BitField _indent_not_parent_format = private static final BitField _indent_not_parent_format = bf(0x0400);
BitFieldFactory.getInstance(0x0400); private static final BitField _indent_not_parent_font = bf(0x0800);
private static final BitField _indent_not_parent_font = private static final BitField _indent_not_parent_alignment = bf(0x1000);
BitFieldFactory.getInstance(0x0800); private static final BitField _indent_not_parent_border = bf(0x2000);
private static final BitField _indent_not_parent_alignment = private static final BitField _indent_not_parent_pattern = bf(0x4000);
BitFieldFactory.getInstance(0x1000); private static final BitField _indent_not_parent_cell_options = bf(0x8000);
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;
// field_6_border_options bit map // field_6_border_options bit map
private static final BitField _border_left = BitFieldFactory.getInstance(0x000F); private static final BitField _border_left = bf(0x000F);
private static final BitField _border_right = BitFieldFactory.getInstance(0x00F0); private static final BitField _border_right = bf(0x00F0);
private static final BitField _border_top = BitFieldFactory.getInstance(0x0F00); private static final BitField _border_top = bf(0x0F00);
private static final BitField _border_bottom = BitFieldFactory.getInstance(0xF000); private static final BitField _border_bottom = bf(0xF000);
private short field_6_border_options;
// all three of the following attributes are palette options // all three of the following attributes are palette options
// field_7_palette_options bit map // field_7_palette_options bit map
private static final BitField _left_border_palette_idx = private static final BitField _left_border_palette_idx = bf(0x007F);
BitFieldFactory.getInstance(0x007F); private static final BitField _right_border_palette_idx = bf(0x3F80);
private static final BitField _right_border_palette_idx = private static final BitField _diag = bf(0xC000);
BitFieldFactory.getInstance(0x3F80);
private static final BitField _diag =
BitFieldFactory.getInstance(0xC000);
private short field_7_palette_options;
// field_8_adtl_palette_options bit map // field_8_adtl_palette_options bit map
private static final BitField _top_border_palette_idx = private static final BitField _top_border_palette_idx = bf(0x0000007F);
BitFieldFactory.getInstance(0x0000007F); private static final BitField _bottom_border_palette_idx = bf(0x00003F80);
private static final BitField _bottom_border_palette_idx = private static final BitField _adtl_diag = bf(0x001fc000);
BitFieldFactory.getInstance(0x00003F80); private static final BitField _adtl_diag_line_style = bf(0x01e00000);
private static final BitField _adtl_diag =
BitFieldFactory.getInstance(0x001fc000);
private static final BitField _adtl_diag_line_style =
BitFieldFactory.getInstance(0x01e00000);
// apparently bit 25 is unused // apparently bit 25 is unused
private static final BitField _adtl_fill_pattern = private static final BitField _adtl_fill_pattern = bf(0xfc000000);
BitFieldFactory.getInstance(0xfc000000);
private int field_8_adtl_palette_options; // additional to avoid 2
// field_9_fill_palette_options bit map // field_9_fill_palette_options bit map
private static final BitField _fill_foreground = BitFieldFactory.getInstance(0x007F); private static final BitField _fill_foreground = bf(0x007F);
private static final BitField _fill_background = BitFieldFactory.getInstance(0x3f80); private static final BitField _fill_background = bf(0x3f80);
// apparently bits 15 and 14 are unused private static BitField bf(int i) {
private short field_9_fill_palette_options; return BitFieldFactory.getInstance(i);
/**
* Constructor ExtendedFormatRecord
*
*
*/
public ExtendedFormatRecord()
{
} }
public ExtendedFormatRecord(RecordInputStream in)
{ // 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;
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) {
field_1_font_index = in.readShort(); field_1_font_index = in.readShort();
field_2_format_index = in.readShort(); field_2_format_index = in.readShort();
field_3_cell_options = 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 * <p>Sets whether or not to use the pattern in this XF instead of the
* parent XF (foreground/background).</p> * parent XF (foreground/background).</p>
* *
* @param pattern {@code true} if this XF has a different pattern * @param pattern {@code true} if this XF has a different pattern
* value than its parent, {@code false} otherwise. * value than its parent, {@code false} otherwise.
* @see #setIndentionOptions(short) * @see #setIndentionOptions(short)
@ -1788,16 +1773,16 @@ public final class ExtendedFormatRecord
{ {
return sid; return sid;
} }
/** /**
* Clones all the style information from another * 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. * will then hold all the same style options.
* *
* If The source ExtendedFormatRecord comes from * If The source ExtendedFormatRecord comes from
* a different Workbook, you will need to sort * a different Workbook, you will need to sort
* out the font and format indices yourself! * out the font and format indices yourself!
* *
* @param source the ExtendedFormatRecord to copy from * @param source the ExtendedFormatRecord to copy from
*/ */
public void cloneStyleFrom(ExtendedFormatRecord source) { public void cloneStyleFrom(ExtendedFormatRecord source) {
@ -1863,11 +1848,15 @@ public final class ExtendedFormatRecord
} }
return false; return false;
} }
public int[] stateSummary() { public int[] stateSummary() {
return new int[] { field_1_font_index, field_2_format_index, field_3_cell_options, field_4_alignment_options, 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 }; 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);
}
} }

View File

@ -28,9 +28,9 @@ import org.apache.poi.util.LittleEndianOutput;
*/ */
public class ExternSheetRecord extends StandardRecord { public class ExternSheetRecord extends StandardRecord {
public final static short sid = 0x0017; public static final short sid = 0x0017;
private final List<RefSubRecord> _list; private final List<RefSubRecord> _list = new ArrayList<>();
private static final class RefSubRecord { private static final class RefSubRecord {
public static final int ENCODED_SIZE = 6; public static final int ENCODED_SIZE = 6;
@ -38,26 +38,31 @@ public class ExternSheetRecord extends StandardRecord {
private final int _extBookIndex; private final int _extBookIndex;
private int _firstSheetIndex; // may be -1 (0xFFFF) private int _firstSheetIndex; // may be -1 (0xFFFF)
private int _lastSheetIndex; // 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) { public RefSubRecord(int extBookIndex, int firstSheetIndex, int lastSheetIndex) {
_extBookIndex = extBookIndex; _extBookIndex = extBookIndex;
_firstSheetIndex = firstSheetIndex; _firstSheetIndex = firstSheetIndex;
_lastSheetIndex = lastSheetIndex; _lastSheetIndex = lastSheetIndex;
} }
public RefSubRecord(RefSubRecord other) {
_extBookIndex = other._extBookIndex;
_firstSheetIndex = other._firstSheetIndex;
_lastSheetIndex = other._lastSheetIndex;
}
/** /**
* @param in the RecordInputstream to read the record from * @param in the RecordInputstream to read the record from
*/ */
public RefSubRecord(RecordInputStream in) { public RefSubRecord(RecordInputStream in) {
this(in.readShort(), in.readShort(), in.readShort()); this(in.readShort(), in.readShort(), in.readShort());
} }
public void adjustIndex(int offset) {
_firstSheetIndex += offset;
_lastSheetIndex += offset;
}
public int getExtBookIndex(){ public int getExtBookIndex(){
return _extBookIndex; return _extBookIndex;
} }
@ -67,7 +72,7 @@ public class ExternSheetRecord extends StandardRecord {
public int getLastSheetIndex(){ public int getLastSheetIndex(){
return _lastSheetIndex; return _lastSheetIndex;
} }
@Override @Override
public String toString() { public String toString() {
StringBuilder buffer = new StringBuilder(); StringBuilder buffer = new StringBuilder();
@ -76,55 +81,53 @@ public class ExternSheetRecord extends StandardRecord {
buffer.append(" lastSheet=").append(_lastSheetIndex); buffer.append(" lastSheet=").append(_lastSheetIndex);
return buffer.toString(); return buffer.toString();
} }
public void serialize(LittleEndianOutput out) { public void serialize(LittleEndianOutput out) {
out.writeShort(_extBookIndex); out.writeShort(_extBookIndex);
out.writeShort(_firstSheetIndex); out.writeShort(_firstSheetIndex);
out.writeShort(_lastSheetIndex); out.writeShort(_lastSheetIndex);
} }
} }
public ExternSheetRecord() {}
public ExternSheetRecord() { public ExternSheetRecord(ExternSheetRecord other) {
_list = new ArrayList<>(); other._list.stream().map(RefSubRecord::new).forEach(_list::add);
} }
public ExternSheetRecord(RecordInputStream in) { public ExternSheetRecord(RecordInputStream in) {
_list = new ArrayList<>();
int nItems = in.readShort(); int nItems = in.readShort();
for (int i = 0 ; i < nItems ; ++i) { for (int i = 0 ; i < nItems ; ++i) {
RefSubRecord rec = new RefSubRecord(in); RefSubRecord rec = new RefSubRecord(in);
_list.add(rec); _list.add(rec);
} }
} }
/**
/**
* @return number of REF structures * @return number of REF structures
*/ */
public int getNumOfRefs() { public int getNumOfRefs() {
return _list.size(); return _list.size();
} }
/** /**
* adds REF struct (ExternSheetSubRecord) * adds REF struct (ExternSheetSubRecord)
* @param rec REF struct * @param rec REF struct
*/ */
public void addREFRecord(RefSubRecord rec) { public void addREFRecord(RefSubRecord rec) {
_list.add(rec); _list.add(rec);
} }
/** returns the number of REF Records, which is in model /** returns the number of REF Records, which is in model
* @return number of REF records * @return number of REF records
*/ */
public int getNumOfREFRecords() { public int getNumOfREFRecords() {
return _list.size(); return _list.size();
} }
@Override @Override
public String toString() { public String toString() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
@ -137,22 +140,22 @@ public class ExternSheetRecord extends StandardRecord {
sb.append('\n'); sb.append('\n');
} }
sb.append("[/EXTERNSHEET]\n"); sb.append("[/EXTERNSHEET]\n");
return sb.toString(); return sb.toString();
} }
@Override @Override
protected int getDataSize() { protected int getDataSize() {
return 2 + _list.size() * RefSubRecord.ENCODED_SIZE; return 2 + _list.size() * RefSubRecord.ENCODED_SIZE;
} }
@Override @Override
public void serialize(LittleEndianOutput out) { public void serialize(LittleEndianOutput out) {
int nItems = _list.size(); int nItems = _list.size();
out.writeShort(nItems); out.writeShort(nItems);
for (int i = 0; i < nItems; i++) { for (int i = 0; i < nItems; i++) {
getRef(i).serialize(out); getRef(i).serialize(out);
} }
@ -161,22 +164,22 @@ public class ExternSheetRecord extends StandardRecord {
private RefSubRecord getRef(int i) { private RefSubRecord getRef(int i) {
return _list.get(i); return _list.get(i);
} }
public void removeSheet(int sheetIdx) { public void removeSheet(int sheetIdx) {
int nItems = _list.size(); int nItems = _list.size();
for (int i = 0; i < nItems; i++) { for (int i = 0; i < nItems; i++) {
RefSubRecord refSubRecord = _list.get(i); RefSubRecord refSubRecord = _list.get(i);
if(refSubRecord.getFirstSheetIndex() == sheetIdx && if(refSubRecord.getFirstSheetIndex() == sheetIdx &&
refSubRecord.getLastSheetIndex() == sheetIdx) { refSubRecord.getLastSheetIndex() == sheetIdx) {
// removing the entry would mess up the sheet index in Formula of NameRecord // removing the entry would mess up the sheet index in Formula of NameRecord
_list.set(i, new RefSubRecord(refSubRecord.getExtBookIndex(), -1, -1)); _list.set(i, new RefSubRecord(refSubRecord.getExtBookIndex(), -1, -1));
} else if (refSubRecord.getFirstSheetIndex() > sheetIdx && } else if (refSubRecord.getFirstSheetIndex() > sheetIdx &&
refSubRecord.getLastSheetIndex() > sheetIdx) { refSubRecord.getLastSheetIndex() > sheetIdx) {
_list.set(i, new RefSubRecord(refSubRecord.getExtBookIndex(), refSubRecord.getFirstSheetIndex()-1, refSubRecord.getLastSheetIndex()-1)); _list.set(i, new RefSubRecord(refSubRecord.getExtBookIndex(), refSubRecord.getFirstSheetIndex()-1, refSubRecord.getLastSheetIndex()-1));
} }
} }
} }
/** /**
* return the non static version of the id for this record. * 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 * @param refIndex specifies the n-th refIndex
* *
* @return the index of the SupBookRecord for this index * @return the index of the SupBookRecord for this index
*/ */
public int getExtbookIndexFromRefIndex(int refIndex) { public int getExtbookIndexFromRefIndex(int refIndex) {
@ -197,7 +200,7 @@ public class ExternSheetRecord extends StandardRecord {
/** /**
* @param extBookIndex external sheet reference index * @param extBookIndex external sheet reference index
* *
* @return -1 if not found * @return -1 if not found
*/ */
public int findRefIndexFromExtBookIndex(int extBookIndex) { public int findRefIndexFromExtBookIndex(int extBookIndex) {
@ -214,9 +217,9 @@ public class ExternSheetRecord extends StandardRecord {
* Returns the first sheet that the reference applies to, or * Returns the first sheet that the reference applies to, or
* -1 if the referenced sheet can't be found, or -2 if the * -1 if the referenced sheet can't be found, or -2 if the
* reference is workbook scoped. * reference is workbook scoped.
* *
* @param extRefIndex external sheet reference index * @param extRefIndex external sheet reference index
* *
* @return the first sheet that the reference applies to, or * @return the first sheet that the reference applies to, or
* -1 if the referenced sheet can't be found, or -2 if the * -1 if the referenced sheet can't be found, or -2 if the
* reference is workbook scoped * reference is workbook scoped
@ -231,9 +234,9 @@ public class ExternSheetRecord extends StandardRecord {
* reference is workbook scoped. * reference is workbook scoped.
* For a single sheet reference, the first and last should be * For a single sheet reference, the first and last should be
* the same. * the same.
* *
* @param extRefIndex external sheet reference index * @param extRefIndex external sheet reference index
* *
* @return the last sheet that the reference applies to, or * @return the last sheet that the reference applies to, or
* -1 if the referenced sheet can't be found, or -2 if the * -1 if the referenced sheet can't be found, or -2 if the
* reference is workbook scoped. * reference is workbook scoped.
@ -258,7 +261,7 @@ public class ExternSheetRecord extends StandardRecord {
* see {@link org.apache.poi.hssf.record.SupBookRecord#getSheetNames()}. * 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 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> * 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 * <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 * {@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. * 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) { if (ref.getExtBookIndex() != externalBookIndex) {
continue; continue;
} }
if (ref.getFirstSheetIndex() == firstSheetIndex && if (ref.getFirstSheetIndex() == firstSheetIndex &&
ref.getLastSheetIndex() == lastSheetIndex) { ref.getLastSheetIndex() == lastSheetIndex) {
return i; return i;
} }
@ -301,4 +304,9 @@ public class ExternSheetRecord extends StandardRecord {
} }
return result; return result;
} }
@Override
public ExternSheetRecord copy() {
return new ExternSheetRecord(this);
}
} }

View File

@ -28,7 +28,7 @@ import org.apache.poi.util.StringUtil;
*/ */
public final class ExternalNameRecord extends StandardRecord { 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_BUILTIN_NAME = 0x0001;
private static final int OPT_AUTOMATIC_LINK = 0x0002; // m$ doc calls this fWantAdvise 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 static final int OPT_ICONIFIED_PICTURE_LINK= 0x8000;
private short field_1_option_flag; private short field_1_option_flag;
private short field_2_ixals; private short field_2_ixals;
private short field_3_not_used; private short field_3_not_used;
private String field_4_name; 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' * 'rgoper' / 'Last received results of the DDE link'
@ -60,6 +60,54 @@ public final class ExternalNameRecord extends StandardRecord {
*/ */
private int _nRows; 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 * @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' * For OLE and DDE, links can be either 'automatic' or 'manual'
* *
* @return {@code true} if this is a automatic link * @return {@code true} if this is a automatic link
*/ */
public boolean isAutomaticLink() { public boolean isAutomaticLink() {
@ -76,7 +124,7 @@ public final class ExternalNameRecord extends StandardRecord {
} }
/** /**
* only for OLE and DDE * only for OLE and DDE
* *
* @return {@code true} if this is a picture link * @return {@code true} if this is a picture link
*/ */
public boolean isPicureLink() { public boolean isPicureLink() {
@ -84,7 +132,7 @@ public final class ExternalNameRecord extends StandardRecord {
} }
/** /**
* DDE links only. If <code>true</code>, this denotes the 'StdDocumentName' * DDE links only. If <code>true</code>, this denotes the 'StdDocumentName'
* *
* @return {@code true} if this denotes the 'StdDocumentName' * @return {@code true} if this denotes the 'StdDocumentName'
*/ */
public boolean isStdDocumentNameIdentifier() { public boolean isStdDocumentNameIdentifier() {
@ -102,7 +150,7 @@ public final class ExternalNameRecord extends StandardRecord {
public String getText() { public String getText() {
return field_4_name; return field_4_name;
} }
public void setText(String str) { public void setText(String str) {
field_4_name = 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 * index of the name of the Sheet this refers to, as
* defined in the preceding {@link SupBookRecord}. * defined in the preceding {@link SupBookRecord}.
* If it isn't a local name, then it must be zero. * If it isn't a local name, then it must be zero.
* *
* @return the index of the name of the Sheet this refers to * @return the index of the name of the Sheet this refers to
*/ */
public short getIx() { public short getIx() {
return field_2_ixals; return field_2_ixals;
} }
public void setIx(short ix) { public void setIx(short ix) {
field_2_ixals = ix; field_2_ixals = ix;
} }
@ -134,7 +182,7 @@ public final class ExternalNameRecord extends StandardRecord {
@Override @Override
protected int getDataSize(){ protected int getDataSize(){
int result = 2 + 4; // short and int 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(!isOLELink() && !isStdDocumentNameIdentifier()){
if(isAutomaticLink()){ 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 @Override
public short getSid() { public short getSid() {
return sid; return sid;
@ -228,4 +240,9 @@ public final class ExternalNameRecord extends StandardRecord {
sb.append("[/EXTERNALNAME]\n"); sb.append("[/EXTERNALNAME]\n");
return sb.toString(); return sb.toString();
} }
@Override
public ExternalNameRecord copy() {
return new ExternalNameRecord(this);
}
} }

View File

@ -19,29 +19,30 @@ package org.apache.poi.hssf.record;
import org.apache.poi.hssf.record.common.FtrHeader; import org.apache.poi.hssf.record.common.FtrHeader;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.Removal;
/** /**
* Title: FeatHdr (Feature Header) Record * Title: FeatHdr (Feature Header) Record
* <P> * <P>
* This record specifies common information for Shared Features, and * This record specifies common information for Shared Features, and
* specifies the beginning of a collection of records to define them. * specifies the beginning of a collection of records to define them.
* The collection of data (Globals Substream ABNF, macro sheet substream * The collection of data (Globals Substream ABNF, macro sheet substream
* ABNF or worksheet substream ABNF) specifies Shared Feature data. * 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 * Specifies the enhanced protection type. Used to protect a
* shared workbook by restricting access to some areas of it * shared workbook by restricting access to some areas of it
*/ */
public static final int SHAREDFEATURES_ISFPROTECTION = 0x02; 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; public static final int SHAREDFEATURES_ISFFEC2 = 0x03;
/** /**
* Specifies the smart tag type. Recognises certain * Specifies the smart tag type. Recognises certain
* types of entries (proper names, dates/times etc) and * types of entries (proper names, dates/times etc) and
* flags them for action * flags them for action
*/ */
public static final int SHAREDFEATURES_ISFFACTOID = 0x04; 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 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 int isf_sharedFeatureType; // See SHAREDFEATURES_
private byte reserved; // Should always be one private byte reserved; // Should always be one
/** /**
* 0x00000000 = rgbHdrData not present * 0x00000000 = rgbHdrData not present
* 0xffffffff = rgbHdrData present * 0xffffffff = rgbHdrData present
*/ */
@ -69,13 +70,18 @@ public final class FeatHdrRecord extends StandardRecord implements Cloneable {
futureHeader.setRecordType(sid); futureHeader.setRecordType(sid);
} }
public short getSid() { public FeatHdrRecord(FeatHdrRecord other) {
return sid; 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) { public FeatHdrRecord(RecordInputStream in) {
futureHeader = new FtrHeader(in); futureHeader = new FtrHeader(in);
isf_sharedFeatureType = in.readShort(); isf_sharedFeatureType = in.readShort();
reserved = in.readByte(); reserved = in.readByte();
cbHdrData = in.readInt(); cbHdrData = in.readInt();
@ -83,19 +89,23 @@ public final class FeatHdrRecord extends StandardRecord implements Cloneable {
rgbHdrData = in.readRemainder(); rgbHdrData = in.readRemainder();
} }
public short getSid() {
return sid;
}
public String toString() { public String toString() {
StringBuilder buffer = new StringBuilder(); StringBuilder buffer = new StringBuilder();
buffer.append("[FEATURE HEADER]\n"); buffer.append("[FEATURE HEADER]\n");
// TODO ... // TODO ...
buffer.append("[/FEATURE HEADER]\n"); buffer.append("[/FEATURE HEADER]\n");
return buffer.toString(); return buffer.toString();
} }
public void serialize(LittleEndianOutput out) { public void serialize(LittleEndianOutput out) {
futureHeader.serialize(out); futureHeader.serialize(out);
out.writeShort(isf_sharedFeatureType); out.writeShort(isf_sharedFeatureType);
out.writeByte(reserved); out.writeByte(reserved);
out.writeInt((int)cbHdrData); out.writeInt((int)cbHdrData);
@ -105,12 +115,20 @@ public final class FeatHdrRecord extends StandardRecord implements Cloneable {
protected int getDataSize() { protected int getDataSize() {
return 12 + 2+1+4+rgbHdrData.length; return 12 + 2+1+4+rgbHdrData.length;
} }
@Override @Override
public FeatHdrRecord clone() { @SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public FeatHdrRecord clone() {
return copy();
}
@Override
public FeatHdrRecord copy() {
//HACK: do a "cheat" clone, see Record.java for more information //HACK: do a "cheat" clone, see Record.java for more information
return (FeatHdrRecord)cloneViaReserialise(); return new FeatHdrRecord(this);
} }
} }

View File

@ -17,6 +17,8 @@
package org.apache.poi.hssf.record; 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.FeatFormulaErr2;
import org.apache.poi.hssf.record.common.FeatProtection; import org.apache.poi.hssf.record.common.FeatProtection;
import org.apache.poi.hssf.record.common.FeatSmartTag; 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.LittleEndianOutput;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
import org.apache.poi.util.Removal;
/** /**
* Title: Feat (Feature) Record * Title: Feat (Feature) Record
@ -33,19 +36,17 @@ import org.apache.poi.util.POILogger;
* This record specifies Shared Features data. It is normally paired * This record specifies Shared Features data. It is normally paired
* up with a {@link FeatHdrRecord}. * up with a {@link FeatHdrRecord}.
*/ */
public final class FeatRecord extends StandardRecord implements Cloneable { public final class FeatRecord extends StandardRecord {
private static POILogger logger = POILogFactory.getLogger(FeatRecord.class); private static final POILogger logger = POILogFactory.getLogger(FeatRecord.class);
public final static short sid = 0x0868; public static final short sid = 0x0868;
// SIDs from newer versions // SIDs from newer versions
public final static short v11_sid = 0x0872; public static final short v11_sid = 0x0872;
public final static short v12_sid = 0x0878; public static final short v12_sid = 0x0878;
private FtrHeader futureHeader; private final FtrHeader futureHeader;
/** /** See SHAREDFEATURES_* on {@link FeatHdrRecord} */
* See SHAREDFEATURES_* on {@link FeatHdrRecord} private int isf_sharedFeatureType;
*/
private int isf_sharedFeatureType;
private byte reserved1; // Should always be zero private byte reserved1; // Should always be zero
private long reserved2; // Should always be zero private long reserved2; // Should always be zero
/** Only matters if type is ISFFEC2 */ /** Only matters if type is ISFFEC2 */
@ -55,24 +56,33 @@ public final class FeatRecord extends StandardRecord implements Cloneable {
/** /**
* Contents depends on isf_sharedFeatureType : * Contents depends on isf_sharedFeatureType :
* ISFPROTECTION -> FeatProtection * ISFPROTECTION -> FeatProtection
* ISFFEC2 -> FeatFormulaErr2 * ISFFEC2 -> FeatFormulaErr2
* ISFFACTOID -> FeatSmartTag * ISFFACTOID -> FeatSmartTag
*/ */
private SharedFeature sharedFeature; private SharedFeature sharedFeature;
public FeatRecord() { public FeatRecord() {
futureHeader = new FtrHeader(); futureHeader = new FtrHeader();
futureHeader.setRecordType(sid); futureHeader.setRecordType(sid);
} }
public short getSid() { public FeatRecord(FeatRecord other) {
return sid; 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) { public FeatRecord(RecordInputStream in) {
futureHeader = new FtrHeader(in); futureHeader = new FtrHeader(in);
isf_sharedFeatureType = in.readShort(); isf_sharedFeatureType = in.readShort();
reserved1 = in.readByte(); reserved1 = in.readByte();
reserved2 = in.readInt(); reserved2 = in.readInt();
@ -84,7 +94,7 @@ public final class FeatRecord extends StandardRecord implements Cloneable {
for(int i=0; i<cellRefs.length; i++) { for(int i=0; i<cellRefs.length; i++) {
cellRefs[i] = new CellRangeAddress(in); cellRefs[i] = new CellRangeAddress(in);
} }
switch(isf_sharedFeatureType) { switch(isf_sharedFeatureType) {
case FeatHdrRecord.SHAREDFEATURES_ISFPROTECTION: case FeatHdrRecord.SHAREDFEATURES_ISFPROTECTION:
sharedFeature = new FeatProtection(in); sharedFeature = new FeatProtection(in);
@ -100,30 +110,34 @@ public final class FeatRecord extends StandardRecord implements Cloneable {
} }
} }
public short getSid() {
return sid;
}
public String toString() { public String toString() {
StringBuilder buffer = new StringBuilder(); StringBuilder buffer = new StringBuilder();
buffer.append("[SHARED FEATURE]\n"); buffer.append("[SHARED FEATURE]\n");
// TODO ... // TODO ...
buffer.append("[/SHARED FEATURE]\n"); buffer.append("[/SHARED FEATURE]\n");
return buffer.toString(); return buffer.toString();
} }
public void serialize(LittleEndianOutput out) { public void serialize(LittleEndianOutput out) {
futureHeader.serialize(out); futureHeader.serialize(out);
out.writeShort(isf_sharedFeatureType); out.writeShort(isf_sharedFeatureType);
out.writeByte(reserved1); out.writeByte(reserved1);
out.writeInt((int)reserved2); out.writeInt((int)reserved2);
out.writeShort(cellRefs.length); out.writeShort(cellRefs.length);
out.writeInt((int)cbFeatData); out.writeInt((int)cbFeatData);
out.writeShort(reserved3); out.writeShort(reserved3);
for(int i=0; i<cellRefs.length; i++) { for(int i=0; i<cellRefs.length; i++) {
cellRefs[i].serialize(out); cellRefs[i].serialize(out);
} }
sharedFeature.serialize(out); sharedFeature.serialize(out);
} }
@ -156,7 +170,7 @@ public final class FeatRecord extends StandardRecord implements Cloneable {
} }
public void setSharedFeature(SharedFeature feature) { public void setSharedFeature(SharedFeature feature) {
this.sharedFeature = feature; this.sharedFeature = feature;
if(feature instanceof FeatProtection) { if(feature instanceof FeatProtection) {
isf_sharedFeatureType = FeatHdrRecord.SHAREDFEATURES_ISFPROTECTION; isf_sharedFeatureType = FeatHdrRecord.SHAREDFEATURES_ISFPROTECTION;
} }
@ -166,7 +180,7 @@ public final class FeatRecord extends StandardRecord implements Cloneable {
if(feature instanceof FeatSmartTag) { if(feature instanceof FeatSmartTag) {
isf_sharedFeatureType = FeatHdrRecord.SHAREDFEATURES_ISFFACTOID; isf_sharedFeatureType = FeatHdrRecord.SHAREDFEATURES_ISFFACTOID;
} }
if(isf_sharedFeatureType == FeatHdrRecord.SHAREDFEATURES_ISFFEC2) { if(isf_sharedFeatureType == FeatHdrRecord.SHAREDFEATURES_ISFFEC2) {
cbFeatData = sharedFeature.getDataSize(); cbFeatData = sharedFeature.getDataSize();
} else { } else {
@ -174,12 +188,16 @@ public final class FeatRecord extends StandardRecord implements Cloneable {
} }
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public FeatRecord clone() { public FeatRecord clone() {
//HACK: do a "cheat" clone, see Record.java for more information return copy();
return (FeatRecord)cloneViaReserialise(); }
}
@Override
public FeatRecord copy() {
return new FeatRecord(this);
}
} }

View File

@ -33,13 +33,14 @@ import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndianByteArrayOutputStream; import org.apache.poi.util.LittleEndianByteArrayOutputStream;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.LittleEndianOutputStream; 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; public static final short sid = 0x002F;
private static final int ENCRYPTION_XOR = 0; private static final int ENCRYPTION_XOR = 0;
private static final int ENCRYPTION_OTHER = 1; private static final int ENCRYPTION_OTHER = 1;
@ -48,12 +49,9 @@ public final class FilePassRecord extends StandardRecord implements Cloneable {
private EncryptionInfo encryptionInfo; private EncryptionInfo encryptionInfo;
private FilePassRecord(FilePassRecord other) { private FilePassRecord(FilePassRecord other) {
super(other);
encryptionType = other.encryptionType; encryptionType = other.encryptionType;
try { encryptionInfo = other.encryptionInfo.copy();
encryptionInfo = other.encryptionInfo.clone();
} catch (CloneNotSupportedException e) {
throw new EncryptedDocumentException(e);
}
} }
public FilePassRecord(EncryptionMode encryptionMode) { public FilePassRecord(EncryptionMode encryptionMode) {
@ -138,8 +136,16 @@ public final class FilePassRecord extends StandardRecord implements Cloneable {
return sid; return sid;
} }
@Override @Override
public FilePassRecord clone() { @SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public FilePassRecord clone() {
return copy();
}
@Override
public FilePassRecord copy() {
return new FilePassRecord(this); return new FilePassRecord(this);
} }

View File

@ -18,17 +18,16 @@
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.Removal;
import org.apache.poi.util.StringUtil; import org.apache.poi.util.StringUtil;
/** /**
* Title: FILESHARING (0x005B) <p> * Stores the encrypted readonly for a workbook (write protect).<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'.
* 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)
*/ */
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_1_readonly;
private short field_2_password; private short field_2_password;
private byte field_3_username_unicode_options; private byte field_3_username_unicode_options;
@ -36,14 +35,22 @@ public final class FileSharingRecord extends StandardRecord implements Cloneable
public FileSharingRecord() {} 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) { public FileSharingRecord(RecordInputStream in) {
field_1_readonly = in.readShort(); field_1_readonly = in.readShort();
field_2_password = in.readShort(); field_2_password = in.readShort();
int nameLen = in.readShort(); int nameLen = in.readShort();
if(nameLen > 0) { 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_unicode_options = in.readByte();
field_3_username_value = in.readCompressedUnicode(nameLen); field_3_username_value = in.readCompressedUnicode(nameLen);
} else { } else {
@ -137,11 +144,15 @@ public final class FileSharingRecord extends StandardRecord implements Cloneable
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public FileSharingRecord clone() { public FileSharingRecord clone() {
FileSharingRecord clone = new FileSharingRecord(); return copy();
clone.setReadOnly(field_1_readonly); }
clone.setPassword(field_2_password);
clone.setUsername(field_3_username_value); @Override
return clone; public FileSharingRecord copy() {
return new FileSharingRecord(this);
} }
} }

View File

@ -15,35 +15,32 @@
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
==================================================================== */ ==================================================================== */
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
/** /**
* Title: Function Group Count Record<P> * umber of built in function groups in the current version of the Spreadsheet (probably only used on Windows)
* 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)
* @version 2.0-pre * @version 2.0-pre
*/ */
public final class FnGroupCountRecord extends StandardRecord {
public final class FnGroupCountRecord public static final short sid = 0x9c;
extends StandardRecord
{
public final static short sid = 0x9c;
/** /**
* suggested default (14 dec) * suggested default (14 dec)
*/ */
public final static short COUNT = 14; public static final short COUNT = 14;
private short field_1_count; 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) public FnGroupCountRecord(RecordInputStream in)
@ -96,4 +93,9 @@ public final class FnGroupCountRecord
{ {
return sid; return sid;
} }
@Override
public FnGroupCountRecord copy() {
return new FnGroupCountRecord(this);
}
} }

View File

@ -25,50 +25,68 @@ import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.StringUtil; import org.apache.poi.util.StringUtil;
/** /** Describes a font in the workbook */
* 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)
*/
public final class FontRecord extends StandardRecord { public final class FontRecord extends StandardRecord {
// docs are wrong (0x231 Microsoft Support site article Q184647) // docs are wrong (0x231 Microsoft Support site article Q184647)
public final static short sid = 0x0031; public static final short sid = 0x0031;
public final static short SS_NONE = 0; public static final short SS_NONE = 0;
public final static short SS_SUPER = 1; public static final short SS_SUPER = 1;
public final static short SS_SUB = 2; public static final short SS_SUB = 2;
public final static byte U_NONE = 0; public static final byte U_NONE = 0;
public final static byte U_SINGLE = 1; public static final byte U_SINGLE = 1;
public final static byte U_DOUBLE = 2; public static final byte U_DOUBLE = 2;
public final static byte U_SINGLE_ACCOUNTING = 0x21; public static final byte U_SINGLE_ACCOUNTING = 0x21;
public final static byte U_DOUBLE_ACCOUNTING = 0x22; public static final byte U_DOUBLE_ACCOUNTING = 0x22;
// in units of .05 of a point
private short field_1_font_height;
private short field_2_attributes;
// 0 0x01 - Reserved bit must be 0 // 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 // 2 0x04 - reserved bit must be 0
private static final BitField strikeout =BitFieldFactory.getInstance(0x08); // is this font has a line through the center // 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 strikeout = BitFieldFactory.getInstance(0x08);
private static final BitField macshadow = BitFieldFactory.getInstance(0x20); // some weird macintosh thing....but who understands those mac people anyhow // 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 // 7-6 - reserved bits must be 0
// the rest is unused // the rest is unused
private short field_3_color_palette_index; private short field_3_color_palette_index;
private short field_4_bold_weight; private short field_4_bold_weight;
private short field_5_super_sub_script; // 00none/01super/02sub // 00none/01super/02sub
private byte field_6_underline; // 00none/01single/02double/21singleaccounting/22doubleaccounting private short field_5_super_sub_script;
private byte field_7_family; // ?? defined by windows api logfont structure? // 00none/01single/02double/21singleaccounting/22doubleaccounting
private byte field_8_charset; // ?? defined by windows api logfont structure? private byte field_6_underline;
private byte field_9_zero; // must be 0 // ?? 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> */ /** possibly empty string never <code>null</code> */
private String field_11_font_name; private String field_11_font_name;
public FontRecord() { 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) { public FontRecord(RecordInputStream in) {
field_1_font_height = in.readShort(); field_1_font_height = in.readShort();
field_2_attributes = in.readShort(); field_2_attributes = in.readShort();
@ -490,4 +508,9 @@ public final class FontRecord extends StandardRecord {
public boolean equals(Object o) { public boolean equals(Object o) {
return (o instanceof FontRecord) && sameProperties((FontRecord) o); return (o instanceof FontRecord) && sameProperties((FontRecord) o);
} }
@Override
public FontRecord copy() {
return new FontRecord(this);
}
} }

View File

@ -17,18 +17,22 @@
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import org.apache.poi.util.Removal;
/** /**
* Title: Footer Record (0x0015)<p> * Specifies the footer for a sheet
* Description: Specifies the footer for a sheet<p>
* REFERENCE: PG 317 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)
*/ */
public final class FooterRecord extends HeaderFooterBase implements Cloneable { public final class FooterRecord extends HeaderFooterBase {
public final static short sid = 0x0015; public static final short sid = 0x0015;
public FooterRecord(String text) { public FooterRecord(String text) {
super(text); super(text);
} }
public FooterRecord(FooterRecord other) {
super(other);
}
public FooterRecord(RecordInputStream in) { public FooterRecord(RecordInputStream in) {
super(in); super(in);
} }
@ -47,7 +51,15 @@ public final class FooterRecord extends HeaderFooterBase implements Cloneable {
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public FooterRecord clone() { public FooterRecord clone() {
return new FooterRecord(getText()); return copy();
}
@Override
public FooterRecord copy() {
return new FooterRecord(this);
} }
} }

View File

@ -22,30 +22,29 @@ import org.apache.poi.util.LittleEndianConsts;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
import org.apache.poi.util.Removal;
import org.apache.poi.util.StringUtil; import org.apache.poi.util.StringUtil;
/** /**
* Title: Format Record (0x041E)<p> * Describes a number format -- those goofy strings like $(#,###)
* Description: describes a number format -- those goofy strings like $(#,###)<p>
*
* REFERENCE: PG 317 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)
*/ */
public final class FormatRecord extends StandardRecord implements Cloneable { public final class FormatRecord extends StandardRecord {
private static final POILogger logger = POILogFactory.getLogger(FormatRecord.class); 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 int field_1_index_code;
private final boolean field_3_hasMultibyte; private final boolean field_3_hasMultibyte;
private final String field_4_formatstring; private final String field_4_formatstring;
private FormatRecord(FormatRecord other) { private FormatRecord(FormatRecord other) {
super(other);
field_1_index_code = other.field_1_index_code; field_1_index_code = other.field_1_index_code;
field_3_hasMultibyte = other.field_3_hasMultibyte; field_3_hasMultibyte = other.field_3_hasMultibyte;
field_4_formatstring = other.field_4_formatstring; field_4_formatstring = other.field_4_formatstring;
} }
public FormatRecord(int indexCode, String fs) { public FormatRecord(int indexCode, String fs) {
field_1_index_code = indexCode; field_1_index_code = indexCode;
field_4_formatstring = fs; field_4_formatstring = fs;
@ -114,9 +113,17 @@ public final class FormatRecord extends StandardRecord implements Cloneable {
public short getSid() { public short getSid() {
return sid; return sid;
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public FormatRecord clone() { public FormatRecord clone() {
return copy();
}
@Override
public FormatRecord copy() {
return new FormatRecord(this); return new FormatRecord(this);
} }

View File

@ -18,168 +18,28 @@
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import org.apache.poi.ss.formula.Formula; 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.formula.ptg.Ptg;
import org.apache.poi.ss.usermodel.CellType; 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). * 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) // docs say 406...because of a bug Microsoft support site article #Q184647)
private static int FIXED_SIZE = 14; // double + short + int 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 alwaysCalc = BitFieldFactory.getInstance(0x0001);
private static final BitField calcOnLoad = BitFieldFactory.getInstance(0x0002); private static final BitField calcOnLoad = BitFieldFactory.getInstance(0x0002);
private static final BitField sharedFormula = BitFieldFactory.getInstance(0x0008); 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 double field_4_value;
private short field_5_options; 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 * 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 */ /** Creates new FormulaRecord */
public FormulaRecord() { public FormulaRecord() {
field_8_parsed_expr = Formula.create(Ptg.EMPTY_PTG_ARRAY); 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) { public FormulaRecord(RecordInputStream ris) {
super(ris); super(ris);
long valueLongBits = ris.readLong(); long valueLongBits = ris.readLong();
field_5_options = ris.readShort(); field_5_options = ris.readShort();
specialCachedValue = SpecialCachedValue.create(valueLongBits); specialCachedValue = FormulaSpecialCachedValue.create(valueLongBits);
if (specialCachedValue == null) { if (specialCachedValue == null) {
field_4_value = Double.longBitsToDouble(valueLongBits); field_4_value = Double.longBitsToDouble(valueLongBits);
} }
@ -228,16 +96,16 @@ public final class FormulaRecord extends CellRecord implements Cloneable {
} }
public void setCachedResultTypeEmptyString() { public void setCachedResultTypeEmptyString() {
specialCachedValue = SpecialCachedValue.createCachedEmptyValue(); specialCachedValue = FormulaSpecialCachedValue.createCachedEmptyValue();
} }
public void setCachedResultTypeString() { public void setCachedResultTypeString() {
specialCachedValue = SpecialCachedValue.createForString(); specialCachedValue = FormulaSpecialCachedValue.createForString();
} }
public void setCachedResultErrorCode(int errorCode) { public void setCachedResultErrorCode(int errorCode) {
specialCachedValue = SpecialCachedValue.createCachedErrorCode(errorCode); specialCachedValue = FormulaSpecialCachedValue.createCachedErrorCode(errorCode);
} }
public void setCachedResultBoolean(boolean value) { 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 * @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() { public boolean hasCachedResultString() {
return specialCachedValue != null && return specialCachedValue != null &&
specialCachedValue.getTypeCode() == SpecialCachedValue.STRING; specialCachedValue.getTypeCode() == FormulaSpecialCachedValue.STRING;
} }
public int getCachedResultType() { 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 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); field_8_parsed_expr.serialize(out);
} }
@Override @Override
protected String getRecordName() { protected String getRecordName() {
return "FORMULA"; return "FORMULA";
} }
@Override @Override
protected void appendValueText(StringBuilder sb) { protected void appendValueText(StringBuilder sb) {
sb.append(" .value = "); sb.append(" .value = ");
@ -385,15 +253,16 @@ public final class FormulaRecord extends CellRecord implements Cloneable {
} }
@Override @Override
public FormulaRecord clone() { @SuppressWarnings("squid:S2975")
FormulaRecord rec = new FormulaRecord(); @Deprecated
copyBaseFields(rec); @Removal(version = "5.0.0")
rec.field_4_value = field_4_value; public FormulaRecord clone() {
rec.field_5_options = field_5_options; return copy();
rec.field_6_zero = field_6_zero; }
rec.field_8_parsed_expr = field_8_parsed_expr;
rec.specialCachedValue = specialCachedValue; @Override
return rec; public FormulaRecord copy() {
return new FormulaRecord(this);
} }
} }

View File

@ -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();
}
}

View File

@ -22,28 +22,31 @@ import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianInput;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.RecordFormatException; 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. * 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 class FtCblsSubRecord extends SubRecord {
public final static short sid = 0x0C; public static final short sid = 0x0C;
private static final int ENCODED_SIZE = 20; private static final int ENCODED_SIZE = 20;
private byte[] reserved; private final byte[] reserved;
/** /**
* Construct a new <code>FtCblsSubRecord</code> and * Construct a new <code>FtCblsSubRecord</code> and
* fill its data with the default values * fill its data with the default values
*/ */
public FtCblsSubRecord() public FtCblsSubRecord() {
{
reserved = new byte[ENCODED_SIZE]; reserved = new byte[ENCODED_SIZE];
} }
public FtCblsSubRecord(FtCblsSubRecord other) {
super(other);
reserved = other.reserved.clone();
}
public FtCblsSubRecord(LittleEndianInput in, int size) { public FtCblsSubRecord(LittleEndianInput in, int size) {
if (size != ENCODED_SIZE) { if (size != ENCODED_SIZE) {
throw new RecordFormatException("Unexpected size (" + size + ")"); throw new RecordFormatException("Unexpected size (" + size + ")");
@ -93,12 +96,16 @@ public final class FtCblsSubRecord extends SubRecord implements Cloneable {
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public FtCblsSubRecord clone() { public FtCblsSubRecord clone() {
FtCblsSubRecord rec = new FtCblsSubRecord(); return copy();
byte[] recdata = new byte[reserved.length]; }
System.arraycopy(reserved, 0, recdata, 0, recdata.length);
rec.reserved = recdata; @Override
return rec; public FtCblsSubRecord copy() {
return new FtCblsSubRecord(this);
} }
} }

View File

@ -21,15 +21,16 @@ import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianInput;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.RecordFormatException; 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. * 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 class FtCfSubRecord extends SubRecord {
public final static short sid = 0x07; public static final short sid = 0x07;
public final static short length = 0x02; public static final short length = 0x02;
/** /**
* Specifies the format of the picture is an enhanced metafile. * 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. * Specifies the format of the picture is a bitmap.
*/ */
public static final short BITMAP_BIT = (short)0x0009; public static final short BITMAP_BIT = (short)0x0009;
/** /**
* Specifies the picture is in an unspecified format that is * Specifies the picture is in an unspecified format that is
* neither and enhanced metafile nor a bitmap. * neither and enhanced metafile nor a bitmap.
*/ */
public static final short UNSPECIFIED_BIT = (short)0xFFFF; public static final short UNSPECIFIED_BIT = (short)0xFFFF;
private short flags; private short flags;
/** /**
* Construct a new <code>FtPioGrbitSubRecord</code> and * Construct a new <code>FtPioGrbitSubRecord</code> and
* fill its data with the default values * 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) { public FtCfSubRecord(LittleEndianInput in, int size) {
@ -99,10 +104,16 @@ public final class FtCfSubRecord extends SubRecord implements Cloneable {
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public FtCfSubRecord clone() { public FtCfSubRecord clone() {
FtCfSubRecord rec = new FtCfSubRecord(); return copy();
rec.flags = this.flags; }
return rec;
@Override
public FtCfSubRecord copy() {
return new FtCfSubRecord(this);
} }
public short getFlags() { public short getFlags() {

View File

@ -21,27 +21,28 @@ import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianInput;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.RecordFormatException; 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. * This structure appears as part of an Obj record that represents image display properties.
*/ */
public final class FtPioGrbitSubRecord extends SubRecord implements Cloneable { public final class FtPioGrbitSubRecord extends SubRecord {
public final static short sid = 0x08; public static final short sid = 0x08;
public final static short length = 0x02; 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). * different views (Normal view, Page Break Preview view, Page Layout view and printing).
*/ */
public static final int AUTO_PICT_BIT = 1 << 0; 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. * this FtPioGrbit specifies a DDE reference.
*/ */
public static final int DDE_BIT = 1 << 1; public static final int DDE_BIT = 1 << 1;
/** /**
* A bit that specifies whether this object is expected to be updated on print to * 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. * 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. * A bit that specifies whether the picture is displayed as an icon.
*/ */
public static final int ICON_BIT = 1 << 3; public static final int ICON_BIT = 1 << 3;
/** /**
* A bit that specifies whether this object is an ActiveX control. * 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. * It MUST NOT be the case that both fCtl and fDde are equal to 1.
*/ */
public static final int CTL_BIT = 1 << 4; public static final int CTL_BIT = 1 << 4;
/** /**
* A bit that specifies whether the object data are stored in an * A bit that specifies whether the object data are stored in an
* embedding storage (= 0) or in the controls stream (ctls) (= 1). * embedding storage (= 0) or in the controls stream (ctls) (= 1).
*/ */
public static final int PRSTM_BIT = 1 << 5; public static final int PRSTM_BIT = 1 << 5;
/** /**
* A bit that specifies whether this is a camera picture. * A bit that specifies whether this is a camera picture.
*/ */
public static final int CAMERA_BIT = 1 << 7; public static final int CAMERA_BIT = 1 << 7;
/** /**
* A bit that specifies whether this picture's size has been explicitly set. * 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 * 0 = picture size has been explicitly set, 1 = has not been set
*/ */
public static final int DEFAULT_SIZE_BIT = 1 << 8; public static final int DEFAULT_SIZE_BIT = 1 << 8;
/** /**
* A bit that specifies whether the OLE server for the object is called * 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. * to load the object's data automatically when the parent workbook is opened.
*/ */
public static final int AUTO_LOAD_BIT = 1 << 9; public static final int AUTO_LOAD_BIT = 1 << 9;
private short flags; private short flags;
/** /**
* Construct a new <code>FtPioGrbitSubRecord</code> and * Construct a new <code>FtPioGrbitSubRecord</code> and
* fill its data with the default values * 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) { public FtPioGrbitSubRecord(LittleEndianInput in, int size) {
@ -110,12 +115,12 @@ public final class FtPioGrbitSubRecord extends SubRecord implements Cloneable {
} else { } else {
flags &= (0xFFFF ^ bitmask); flags &= (0xFFFF ^ bitmask);
} }
} }
public boolean getFlagByBit(int bitmask) { public boolean getFlagByBit(int bitmask) {
return ((flags & bitmask) != 0); return ((flags & bitmask) != 0);
} }
/** /**
* Convert this record to string. * Convert this record to string.
* Used by BiffViewer and other utilities. * Used by BiffViewer and other utilities.
@ -153,10 +158,16 @@ public final class FtPioGrbitSubRecord extends SubRecord implements Cloneable {
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public FtPioGrbitSubRecord clone() { public FtPioGrbitSubRecord clone() {
FtPioGrbitSubRecord rec = new FtPioGrbitSubRecord(); return copy();
rec.flags = this.flags; }
return rec;
@Override
public FtPioGrbitSubRecord copy() {
return new FtPioGrbitSubRecord(this);
} }
public short getFlags() { public short getFlags() {

View File

@ -18,28 +18,25 @@
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.Removal;
/** /**
* Title: Gridset Record.<P> * Flag denoting whether the user specified that gridlines are used when printing.
* 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)
* *
* @version 2.0-pre * @version 2.0-pre
*/ */
public final class GridsetRecord extends StandardRecord implements Cloneable { public final class GridsetRecord extends StandardRecord {
public final static short sid = 0x82; public static final short sid = 0x82;
public short field_1_gridset_flag; 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(); field_1_gridset_flag = in.readShort();
} }
@ -87,9 +84,15 @@ public final class GridsetRecord extends StandardRecord implements Cloneable {
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public GridsetRecord clone() { public GridsetRecord clone() {
GridsetRecord rec = new GridsetRecord(); return copy();
rec.field_1_gridset_flag = field_1_gridset_flag; }
return rec;
@Override
public GridsetRecord copy() {
return new GridsetRecord(this);
} }
} }

View File

@ -21,13 +21,14 @@ import org.apache.poi.util.HexDump;
import org.apache.poi.util.IOUtils; import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianInput;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.Removal;
/** /**
* ftGmo (0x0006)<p> * ftGmo (0x0006)<p>
* The group marker record is used as a position holder for groups. * The group marker record is used as a position holder for groups.
*/ */
public final class GroupMarkerSubRecord extends SubRecord implements Cloneable { public final class GroupMarkerSubRecord extends SubRecord {
public final static short sid = 0x0006; public static final short sid = 0x0006;
//arbitrarily selected; may need to increase //arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000; 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; reserved = EMPTY_BYTE_ARRAY;
} }
public GroupMarkerSubRecord(GroupMarkerSubRecord other) {
super(other);
reserved = other.reserved.clone();
}
public GroupMarkerSubRecord(LittleEndianInput in, int size) { public GroupMarkerSubRecord(LittleEndianInput in, int size) {
byte[] buf = IOUtils.safelyAllocate(size, MAX_RECORD_LENGTH); byte[] buf = IOUtils.safelyAllocate(size, MAX_RECORD_LENGTH);
in.readFully(buf); in.readFully(buf);
@ -74,10 +80,15 @@ public final class GroupMarkerSubRecord extends SubRecord implements Cloneable {
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public GroupMarkerSubRecord clone() { public GroupMarkerSubRecord clone() {
GroupMarkerSubRecord rec = new GroupMarkerSubRecord(); return copy();
rec.reserved = new byte[reserved.length]; }
System.arraycopy(reserved, 0, rec.reserved, 0, reserved.length);
return rec; @Override
public GroupMarkerSubRecord copy() {
return new GroupMarkerSubRecord(this);
} }
} }

View File

@ -15,34 +15,41 @@
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
==================================================================== */ ==================================================================== */
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.Removal;
/** /**
* Title: Guts Record <P> * Row/column gutter sizes
* 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)
* @version 2.0-pre * @version 2.0-pre
*/ */
public final class GutsRecord extends StandardRecord implements Cloneable { public final class GutsRecord extends StandardRecord {
public final static short sid = 0x80; public static final short sid = 0x80;
private short field_1_left_row_gutter; // size of the row gutter to the left of the rows /** 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_1_left_row_gutter;
private short field_3_row_level_max; // maximum outline level for row gutters /** size of the column gutter above the columns */
private short field_4_col_level_max; // maximum outline level for column gutters 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() {}
{
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_1_left_row_gutter = in.readShort();
field_2_top_col_gutter = in.readShort(); field_2_top_col_gutter = in.readShort();
field_3_row_level_max = in.readShort(); field_3_row_level_max = in.readShort();
@ -171,12 +178,15 @@ public final class GutsRecord extends StandardRecord implements Cloneable {
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public GutsRecord clone() { public GutsRecord clone() {
GutsRecord rec = new GutsRecord(); return copy();
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; @Override
rec.field_4_col_level_max = field_4_col_level_max; public GutsRecord copy() {
return rec; return new GutsRecord(this);
} }
} }

View File

@ -17,24 +17,25 @@
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.Removal;
/** /**
* Title: HCenter record (0x0083)<P> * Whether to center between horizontal margins
* 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)
* @version 2.0-pre * @version 2.0-pre
*/ */
public final class HCenterRecord extends StandardRecord implements Cloneable { public final class HCenterRecord extends StandardRecord {
public final static short sid = 0x0083; public static final short sid = 0x0083;
private short field_1_hcenter; 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(); field_1_hcenter = in.readShort();
} }
@ -43,11 +44,7 @@ public final class HCenterRecord extends StandardRecord implements Cloneable {
* @param hc center - t/f * @param hc center - t/f
*/ */
public void setHCenter(boolean hc) { public void setHCenter(boolean hc) {
if (hc) { field_1_hcenter = (short)(hc ? 1 : 0);
field_1_hcenter = 1;
} else {
field_1_hcenter = 0;
}
} }
/** /**
@ -80,9 +77,15 @@ public final class HCenterRecord extends StandardRecord implements Cloneable {
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public HCenterRecord clone() { public HCenterRecord clone() {
HCenterRecord rec = new HCenterRecord(); return copy();
rec.field_1_hcenter = field_1_hcenter; }
return rec;
@Override
public HCenterRecord copy() {
return new HCenterRecord(this);
} }
} }

View File

@ -22,8 +22,6 @@ import org.apache.poi.util.StringUtil;
/** /**
* Common header/footer base class * Common header/footer base class
*
* @author Josh Micich
*/ */
public abstract class HeaderFooterBase extends StandardRecord { public abstract class HeaderFooterBase extends StandardRecord {
private boolean field_2_hasMultibyte; private boolean field_2_hasMultibyte;
@ -33,6 +31,12 @@ public abstract class HeaderFooterBase extends StandardRecord {
setText(text); 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) { protected HeaderFooterBase(RecordInputStream in) {
if (in.remaining() > 0) { if (in.remaining() > 0) {
int field_1_footer_len = in.readShort(); 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); return 3 + getTextLength() * (field_2_hasMultibyte ? 2 : 1);
} }
@Override
public abstract HeaderFooterBase copy();
} }

View File

@ -17,28 +17,31 @@
package org.apache.poi.hssf.record; 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.Arrays;
import java.util.Locale; 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. * 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]; private static final byte[] BLANK_GUID = new byte[16];
public final static short sid = 0x089C;
private byte[] _rawData; private byte[] _rawData;
public HeaderFooterRecord(byte[] data) { public HeaderFooterRecord(byte[] data) {
_rawData = 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 * construct a HeaderFooterRecord record. No fields are interpreted and the record will
* be serialized in its original form more or less * be serialized in its original form more or less
@ -58,7 +61,7 @@ public final class HeaderFooterRecord extends StandardRecord implements Cloneabl
protected int getDataSize() { protected int getDataSize() {
return _rawData.length; return _rawData.length;
} }
public short getSid() public short getSid()
{ {
return sid; 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(){ public boolean isCurrentSheet(){
return Arrays.equals(getGuid(), BLANK_GUID); return Arrays.equals(getGuid(), BLANK_GUID);
@ -96,10 +99,17 @@ public final class HeaderFooterRecord extends StandardRecord implements Cloneabl
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public HeaderFooterRecord clone() { public HeaderFooterRecord clone() {
//HACK: do a "cheat" clone, see Record.java for more information return copy();
return (HeaderFooterRecord)cloneViaReserialise();
} }
@Override
public HeaderFooterRecord copy() {
return new HeaderFooterRecord(this);
}
} }

View File

@ -17,21 +17,22 @@
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import org.apache.poi.util.Removal;
/** /**
* Title: Header Record<P> * Specifies a header for a sheet
* 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)
*/ */
public final class HeaderRecord extends HeaderFooterBase implements Cloneable { public final class HeaderRecord extends HeaderFooterBase {
public final static short sid = 0x0014; public static final short sid = 0x0014;
public HeaderRecord(String text) { public HeaderRecord(String text) {
super(text); super(text);
} }
public HeaderRecord(HeaderRecord other) {
super(other);
}
public HeaderRecord(RecordInputStream in) { public HeaderRecord(RecordInputStream in) {
super(in); super(in);
} }
@ -50,7 +51,15 @@ public final class HeaderRecord extends HeaderFooterBase implements Cloneable {
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public HeaderRecord clone() { public HeaderRecord clone() {
return new HeaderRecord(getText()); return copy();
}
@Override
public HeaderRecord copy() {
return new HeaderRecord(this);
} }
} }

View File

@ -15,35 +15,33 @@
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
==================================================================== */ ==================================================================== */
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
/** /**
* Title: Hide Object Record<P> * Flag defines whether to hide placeholders and object
* 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)
* @version 2.0-pre * @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 private short field_1_hide_obj;
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;
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(); field_1_hide_obj = in.readShort();
} }
@ -98,4 +96,9 @@ public final class HideObjRecord
{ {
return sid; return sid;
} }
@Override
public HideObjRecord copy() {
return new HideObjRecord(this);
}
} }

View File

@ -17,21 +17,24 @@
package org.apache.poi.hssf.record; 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 * HorizontalPageBreak (0x001B) record that stores page breaks at rows
* *
* @see PageBreakRecord * @see PageBreakRecord
*/ */
public final class HorizontalPageBreakRecord extends PageBreakRecord implements Cloneable { public final class HorizontalPageBreakRecord extends PageBreakRecord {
public static final short sid = 0x001B; public static final short sid = 0x001B;
/** /**
* Creates an empty horizontal page break record * 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 @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public PageBreakRecord clone() { public PageBreakRecord clone() {
PageBreakRecord result = new HorizontalPageBreakRecord(); return copy();
Iterator<Break> iterator = getBreaksIterator(); }
while (iterator.hasNext()) {
Break original = iterator.next(); @Override
result.addBreak(original.main, original.subFrom, original.subTo); public HorizontalPageBreakRecord copy() {
} return new HorizontalPageBreakRecord(this);
return result;
} }
} }

View File

@ -27,6 +27,7 @@ import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
import org.apache.poi.util.RecordFormatException; import org.apache.poi.util.RecordFormatException;
import org.apache.poi.util.Removal;
import org.apache.poi.util.StringUtil; import org.apache.poi.util.StringUtil;
/** /**
@ -34,13 +35,14 @@ import org.apache.poi.util.StringUtil;
* from the Excel-97 format. * from the Excel-97 format.
* Supports only external links for now (eg http://) * Supports only external links for now (eg http://)
*/ */
public final class HyperlinkRecord extends StandardRecord implements Cloneable { public final class HyperlinkRecord extends StandardRecord {
public final static short sid = 0x01B8; public static final short sid = 0x01B8;
private static POILogger logger = POILogFactory.getLogger(HyperlinkRecord.class); private static POILogger logger = POILogFactory.getLogger(HyperlinkRecord.class);
//arbitrarily selected; may need to increase //arbitrarily selected; may need to increase
private static final int MAX_RECORD_LENGTH = 100_000; private static final int MAX_RECORD_LENGTH = 100_000;
// TODO: replace with ClassID
static final class GUID { static final class GUID {
/* /*
* this class is currently only used here, but could be moved to a * 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; private final long _d4;
public GUID(GUID other) {
_d1 = other._d1;
_d2 = other._d2;
_d3 = other._d3;
_d4 = other._d4;
}
public GUID(LittleEndianInput in) { public GUID(LittleEndianInput in) {
this(in.readInt(), in.readUShort(), in.readUShort(), in.readLong()); this(in.readInt(), in.readUShort(), in.readUShort(), in.readLong());
} }
@ -199,24 +208,24 @@ public final class HyperlinkRecord extends StandardRecord implements Cloneable {
} }
} }
/** /*
* Link flags * Link flags
*/ */
static final int HLINK_URL = 0x01; // File link or URL. static final int HLINK_URL = 0x01; // File link or URL.
static final int HLINK_ABS = 0x02; // Absolute path. static final int HLINK_ABS = 0x02; // Absolute path.
static final int HLINK_LABEL = 0x14; // Has label/description. static final int HLINK_LABEL = 0x14; // Has label/description.
/** Place in worksheet. If set, the {@link #_textMark} field will be present */ /** 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_TARGET_FRAME = 0x80; // has 'target frame'
private static final int HLINK_UNC_PATH = 0x100; // has UNC path private static final int HLINK_UNC_PATH = 0x100; // has UNC path
final static GUID STD_MONIKER = GUID.parse("79EAC9D0-BAF9-11CE-8C82-00AA004BA90B"); static final GUID STD_MONIKER = GUID.parse("79EAC9D0-BAF9-11CE-8C82-00AA004BA90B");
final static GUID URL_MONIKER = GUID.parse("79EAC9E0-BAF9-11CE-8C82-00AA004BA90B"); static final 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 FILE_MONIKER = GUID.parse("00000303-0000-0000-C000-000000000046");
/** expected Tail of a URL link */ /** 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 */ /** 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; 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. * This field is optional. If present, the {@link #HLINK_PLACE} must be set.
*/ */
private String _textMark; private String _textMark;
private byte[] _uninterpretedTail; private byte[] _uninterpretedTail;
/** /**
* Create a new hyperlink * 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 * @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 * Set the first column (zero-based) of the range that contains this hyperlink
* *
* @param firstCol the first column (zero-based) * @param firstCol the first column (zero-based)
*/ */
public void setFirstColumn(int firstCol) { 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 * Set the last column (zero-based) of the range that contains this hyperlink
* *
* @param lastCol the last column (zero-based) * @param lastCol the last column (zero-based)
*/ */
public void setLastColumn(int lastCol) { 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 * Set the first row (zero-based) of the range that contains this hyperlink
* *
* @param firstRow the first row (zero-based) * @param firstRow the first row (zero-based)
*/ */
public void setFirstRow(int firstRow) { 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 * Set the last row (zero-based) of the range that contains this hyperlink
* *
* @param lastRow the last row (zero-based) * @param lastRow the last row (zero-based)
*/ */
public void setLastRow(int lastRow) { 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. * Link options. Must be a combination of HLINK_* constants.
* For testing only * For testing only
* *
* @return Link options * @return Link options
*/ */
int getLinkOptions(){ int getLinkOptions(){
@ -541,7 +564,7 @@ public final class HyperlinkRecord extends StandardRecord implements Cloneable {
} }
if (in.remaining() > 0) { if (in.remaining() > 0) {
logger.log(POILogger.WARN, logger.log(POILogger.WARN,
"Hyperlink data remains: " + in.remaining() + "Hyperlink data remains: " + in.remaining() +
" : " +HexDump.toHex(in.readRemainder()) " : " +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? * Based on the link options, is this a url?
* *
* @return true, if this is a url link * @return true, if this is a url link
*/ */
public boolean isUrlLink() { public boolean isUrlLink() {
return (_linkOpts & HLINK_URL) > 0 return (_linkOpts & HLINK_URL) > 0
&& (_linkOpts & HLINK_ABS) > 0; && (_linkOpts & HLINK_ABS) > 0;
} }
/** /**
* Based on the link options, is this a file? * Based on the link options, is this a file?
* *
* @return true, if this is a file link * @return true, if this is a file link
*/ */
public boolean isFileLink() { public boolean isFileLink() {
return (_linkOpts & HLINK_URL) > 0 return (_linkOpts & HLINK_URL) > 0
&& (_linkOpts & HLINK_ABS) == 0; && (_linkOpts & HLINK_ABS) == 0;
} }
/** /**
* Based on the link options, is this a document? * Based on the link options, is this a document?
* *
* @return true, if this is a docment link * @return true, if this is a docment link
*/ */
public boolean isDocumentLink() { public boolean isDocumentLink() {
return (_linkOpts & HLINK_PLACE) > 0; return (_linkOpts & HLINK_PLACE) > 0;
} }
/** /**
* Initialize a new url link * Initialize a new url link
*/ */
@ -766,19 +789,15 @@ public final class HyperlinkRecord extends StandardRecord implements Cloneable {
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public HyperlinkRecord clone() { public HyperlinkRecord clone() {
HyperlinkRecord rec = new HyperlinkRecord(); return copy();
rec._range = _range.copy(); }
rec._guid = _guid;
rec._linkOpts = _linkOpts; @Override
rec._fileOpts = _fileOpts; public HyperlinkRecord copy() {
rec._label = _label; return new HyperlinkRecord(this);
rec._address = _address;
rec._moniker = _moniker;
rec._shortFilename = _shortFilename;
rec._targetFrame = _targetFrame;
rec._textMark = _textMark;
rec._uninterpretedTail = _uninterpretedTail;
return rec;
} }
} }

View File

@ -20,27 +20,29 @@ package org.apache.poi.hssf.record;
import org.apache.poi.util.IntList; import org.apache.poi.util.IntList;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.RecordFormatException; import org.apache.poi.util.RecordFormatException;
import org.apache.poi.util.Removal;
/** /**
* Title: Index Record (0x020B)<p> * Occurs right after BOF, tells you where the DBCELL records are for a sheet Important for locating cells
* 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)
*/ */
public final class IndexRecord extends StandardRecord implements Cloneable { public final class IndexRecord extends StandardRecord {
public final static short sid = 0x020B; public static final short sid = 0x020B;
private int field_2_first_row; // first row on the sheet private int field_2_first_row; // first row on the sheet
private int field_3_last_row_add1; // last row private int field_3_last_row_add1; // last row
private int field_4_zero; // supposed to be zero private int field_4_zero; // supposed to be zero
private IntList field_5_dbcells; // array of offsets to DBCELL records 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(); int field_1_zero = in.readInt();
if (field_1_zero != 0) { if (field_1_zero != 0) {
throw new RecordFormatException("Expected zero for field 1 but got " + field_1_zero); 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_2_first_row = in.readInt();
field_3_last_row_add1 = in.readInt(); field_3_last_row_add1 = in.readInt();
field_4_zero = in.readInt(); field_4_zero = in.readInt();
int nCells = in.remaining() / 4; int nCells = in.remaining() / 4;
field_5_dbcells = new IntList(nCells); field_5_dbcells = new IntList(nCells);
for(int i=0; i<nCells; i++) { for(int i=0; i<nCells; i++) {
@ -139,14 +141,14 @@ public final class IndexRecord extends StandardRecord implements Cloneable {
return 16 // 4 ints return 16 // 4 ints
+ getNumDbcells() * 4; + getNumDbcells() * 4;
} }
/** /**
* @param blockCount the number of blocks to be indexed * @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 * @return the size of an IndexRecord when it needs to index the specified number of blocks
*/ */
public static int getRecordSizeForBlockCount(int blockCount) { public static int getRecordSizeForBlockCount(int blockCount) {
return 20 + 4 * blockCount; return 20 + 4 * blockCount;
} }
@Override @Override
public short getSid() { public short getSid() {
@ -154,13 +156,15 @@ public final class IndexRecord extends StandardRecord implements Cloneable {
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public IndexRecord clone() { public IndexRecord clone() {
IndexRecord rec = new IndexRecord(); return copy();
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; @Override
rec.field_5_dbcells = new IntList(); public IndexRecord copy() {
rec.field_5_dbcells.addAll(field_5_dbcells); return new IndexRecord(this);
return rec;
} }
} }

View File

@ -21,11 +21,7 @@ import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.RecordFormatException; import org.apache.poi.util.RecordFormatException;
/** /**
* Title: Interface End Record (0x00E2)<P> * Shows where the Interface Records ends (MMS)
* 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)
*/ */
public final class InterfaceEndRecord extends StandardRecord { public final class InterfaceEndRecord extends StandardRecord {
@ -61,4 +57,9 @@ public final class InterfaceEndRecord extends StandardRecord {
public short getSid() { public short getSid() {
return sid; return sid;
} }
@Override
public InterfaceEndRecord copy() {
return instance;
}
} }

View File

@ -21,19 +21,22 @@ import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
/** /**
* Title: Interface Header Record (0x00E1)<P> * Defines the beginning of Interface records (MMS)
* 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)
*/ */
public final class InterfaceHdrRecord extends StandardRecord { public final class InterfaceHdrRecord extends StandardRecord {
public final static short sid = 0x00E1; public static final short sid = 0x00E1;
private final int _codepage;
/** /**
* suggested (and probably correct) default * 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) { public InterfaceHdrRecord(int codePage) {
_codepage = codePage; _codepage = codePage;
@ -63,4 +66,9 @@ public final class InterfaceHdrRecord extends StandardRecord {
public short getSid() { public short getSid() {
return sid; return sid;
} }
@Override
public InterfaceHdrRecord copy() {
return new InterfaceHdrRecord(this);
}
} }

View File

@ -21,28 +21,30 @@ import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.BitFieldFactory;
import org.apache.poi.util.HexDump; import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.Removal;
/** /**
* Title: Iteration Record (0x0011)<p> * Tells whether to iterate over formula calculations or not.
* Description: Tells whether to iterate over formula calculations or not * If a formula is dependent upon another formula's result.
* (if a formula is dependent upon another formula's result) * (odd feature for something that can only have 32 elements in a formula!)
* (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)
*/ */
public final class IterationRecord extends StandardRecord implements Cloneable { public final class IterationRecord extends StandardRecord {
public final static short sid = 0x0011; public static final short sid = 0x0011;
private static final BitField iterationOn = BitFieldFactory.getInstance(0x0001); private static final BitField iterationOn = BitFieldFactory.getInstance(0x0001);
private int _flags; private int _flags;
public IterationRecord(IterationRecord other) {
super(other);
_flags = other._flags;
}
public IterationRecord(boolean iterateOn) { public IterationRecord(boolean iterateOn) {
_flags = iterationOn.setBoolean(0, iterateOn); _flags = iterationOn.setBoolean(0, iterateOn);
} }
public IterationRecord(RecordInputStream in) public IterationRecord(RecordInputStream in) {
{
_flags = in.readShort(); _flags = in.readShort();
} }
@ -85,7 +87,15 @@ public final class IterationRecord extends StandardRecord implements Cloneable {
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public IterationRecord clone() { public IterationRecord clone() {
return new IterationRecord(getIteration()); return copy();
}
@Override
public IterationRecord copy() {
return new IterationRecord(this);
} }
} }

View File

@ -21,36 +21,43 @@ import org.apache.poi.util.HexDump;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
import org.apache.poi.util.RecordFormatException; 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... * Label Record (0x0204) - read only support for strings stored directly in the cell...
* Don't use this (except to read), use LabelSST instead <P> * Don't use this (except to read), use LabelSST instead
* REFERENCE: PG 325 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) *
*
* @see org.apache.poi.hssf.record.LabelSSTRecord * @see org.apache.poi.hssf.record.LabelSSTRecord
*/ */
public final class LabelRecord extends Record implements CellValueRecordInterface, Cloneable { public final class LabelRecord extends Record implements CellValueRecordInterface {
private final static POILogger logger = POILogFactory.getLogger(LabelRecord.class); 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 int field_1_row;
private short field_2_column; private short field_2_column;
private short field_3_xf_index; private short field_3_xf_index;
private short field_4_string_len; private short field_4_string_len;
private byte field_5_unicode_flag; private byte field_5_unicode_flag;
private String field_6_value; private String field_6_value;
/** Creates new LabelRecord */ /** 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 * @param in the RecordInputstream to read the record from
*/ */
public LabelRecord(RecordInputStream in) public LabelRecord(RecordInputStream in) {
{
field_1_row = in.readUShort(); field_1_row = in.readUShort();
field_2_column = in.readShort(); field_2_column = in.readShort();
field_3_xf_index = in.readShort(); field_3_xf_index = in.readShort();
@ -182,14 +189,15 @@ public final class LabelRecord extends Record implements CellValueRecordInterfac
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public LabelRecord clone() { public LabelRecord clone() {
LabelRecord rec = new LabelRecord(); return copy();
rec.field_1_row = field_1_row; }
rec.field_2_column = field_2_column;
rec.field_3_xf_index = field_3_xf_index; @Override
rec.field_4_string_len = field_4_string_len; public LabelRecord copy() {
rec.field_5_unicode_flag = field_5_unicode_flag; return new LabelRecord(this);
rec.field_6_value = field_6_value;
return rec;
} }
} }

View File

@ -19,18 +19,20 @@ package org.apache.poi.hssf.record;
import org.apache.poi.util.HexDump; import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.Removal;
/** /**
* Title: Label SST Record<P> * Refers to a string in the shared string table and is a column value.
* 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)
*/ */
public final class LabelSSTRecord extends CellRecord implements Cloneable { public final class LabelSSTRecord extends CellRecord {
public final static short sid = 0xfd; public static final short sid = 0xfd;
private int field_4_sst_index; private int field_4_sst_index;
public LabelSSTRecord() { public LabelSSTRecord() {}
// fields uninitialised
public LabelSSTRecord(LabelSSTRecord other) {
super(other);
field_4_sst_index = other.field_4_sst_index;
} }
public LabelSSTRecord(RecordInputStream in) { public LabelSSTRecord(RecordInputStream in) {
@ -58,7 +60,7 @@ public final class LabelSSTRecord extends CellRecord implements Cloneable {
public int getSSTIndex() { public int getSSTIndex() {
return field_4_sst_index; return field_4_sst_index;
} }
@Override @Override
protected String getRecordName() { protected String getRecordName() {
return "LABELSST"; return "LABELSST";
@ -85,10 +87,15 @@ public final class LabelSSTRecord extends CellRecord implements Cloneable {
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public LabelSSTRecord clone() { public LabelSSTRecord clone() {
LabelSSTRecord rec = new LabelSSTRecord(); return copy();
copyBaseFields(rec); }
rec.field_4_sst_index = field_4_sst_index;
return rec; @Override
public LabelSSTRecord copy() {
return new LabelSSTRecord(this);
} }
} }

View File

@ -16,11 +16,13 @@
==================================================================== */ ==================================================================== */
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import org.apache.poi.common.Duplicatable;
import org.apache.poi.ss.formula.ptg.Ptg; import org.apache.poi.ss.formula.ptg.Ptg;
import org.apache.poi.util.HexDump; import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianInput;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.RecordFormatException; import org.apache.poi.util.RecordFormatException;
import org.apache.poi.util.Removal;
import org.apache.poi.util.StringUtil; import org.apache.poi.util.StringUtil;
/** /**
@ -89,6 +91,24 @@ public class LbsDataSubRecord extends SubRecord {
*/ */
private boolean[] _bsels; 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 in the stream to read data from
* @param cbFContinued the seconf short in the record header * @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 * @return a new instance of LbsDataSubRecord to construct auto-filters
@ -259,9 +275,16 @@ public class LbsDataSubRecord extends SubRecord {
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public LbsDataSubRecord clone() { public LbsDataSubRecord clone() {
// TODO: is immutable ??? return copy();
return this; }
@Override
public LbsDataSubRecord copy() {
return new LbsDataSubRecord(this);
} }
@Override @Override
@ -303,7 +326,7 @@ public class LbsDataSubRecord extends SubRecord {
/** /**
* This structure specifies properties of the dropdown list control * This structure specifies properties of the dropdown list control
*/ */
public static class LbsDropData { public static class LbsDropData implements Duplicatable {
/** /**
* Combo dropdown control * Combo dropdown control
*/ */
@ -318,7 +341,7 @@ public class LbsDataSubRecord extends SubRecord {
public static final int STYLE_COMBO_SIMPLE_DROPDOWN = 2; 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; private int _wStyle;
@ -343,12 +366,20 @@ public class LbsDataSubRecord extends SubRecord {
*/ */
private Byte _unused; private Byte _unused;
public LbsDropData(){ public LbsDropData() {
_str = ""; _str = "";
_unused = 0; _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(); _wStyle = in.readUShort();
_cLine = in.readUShort(); _cLine = in.readUShort();
_dxMin = in.readUShort(); _dxMin = in.readUShort();
@ -367,7 +398,7 @@ public class LbsDataSubRecord extends SubRecord {
* <li>1: Combo Edit dropdown control</li> * <li>1: Combo Edit dropdown control</li>
* <li>2: Simple dropdown control (just the dropdown button)</li> * <li>2: Simple dropdown control (just the dropdown button)</li>
* </ul> * </ul>
* *
* @param style the style - see possible values * @param style the style - see possible values
*/ */
public void setStyle(int style){ 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. * Set the number of lines to be displayed in the dropdown.
* *
* @param num 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){ public void setNumLines(int num){
@ -417,5 +448,10 @@ public class LbsDataSubRecord extends SubRecord {
return sb.toString(); return sb.toString();
} }
@Override
public LbsDropData copy() {
return new LbsDropData(this);
}
} }
} }

View File

@ -18,18 +18,23 @@
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.Removal;
/** /**
* Record for the left margin. * Record for the left margin.
*/ */
public final class LeftMarginRecord extends StandardRecord implements Margin, Cloneable { public final class LeftMarginRecord extends StandardRecord implements Margin {
public final static short sid = 0x0026; public static final short sid = 0x0026;
private double field_1_margin; 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(); field_1_margin = in.readDouble();
} }
@ -70,9 +75,15 @@ public final class LeftMarginRecord extends StandardRecord implements Margin, Cl
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public LeftMarginRecord clone() { public LeftMarginRecord clone() {
LeftMarginRecord rec = new LeftMarginRecord(); return copy();
rec.field_1_margin = this.field_1_margin;
return rec;
} }
}
@Override
public LeftMarginRecord copy() {
return new LeftMarginRecord(this);
}
}

View File

@ -15,38 +15,36 @@
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
==================================================================== */ ==================================================================== */
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
/** /**
* Title: MMS Record<P> * defines how many add menu and del menu options are stored in the file.
* Description: defines how many add menu and del menu options are stored * Should always be set to 0 for HSSF workbooks.
* 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)
* @version 2.0-pre * @version 2.0-pre
*/ */
public final class MMSRecord public final class MMSRecord extends StandardRecord {
extends StandardRecord public static final short sid = 0xC1;
{ private byte field_1_addMenuCount;
public final static short sid = 0xC1; private byte field_2_delMenuCount;
private byte field_1_addMenuCount; // = 0;
private byte field_2_delMenuCount; // = 0;
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) { if (in.remaining()==0) {
return; return;
} }
field_1_addMenuCount = in.readByte(); field_1_addMenuCount = in.readByte();
field_2_delMenuCount = in.readByte(); field_2_delMenuCount = in.readByte();
} }
@ -117,4 +115,9 @@ public final class MMSRecord
{ {
return sid; return sid;
} }
@Override
public MMSRecord copy() {
return new MMSRecord(this);
}
} }

View File

@ -17,22 +17,33 @@
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import java.util.stream.Stream;
import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList; import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.Removal;
/** /**
* Title: Merged Cells Record (0x00E5)<p> * Optional record defining a square area of cells to "merged" into one cell.
*
* Description: Optional record defining a square area of cells to "merged" into one cell.
*/ */
public final class MergeCellsRecord extends StandardRecord implements Cloneable { public final class MergeCellsRecord extends StandardRecord {
public final static short sid = 0x00E5; public static final short sid = 0x00E5;
/** sometimes the regions array is shared with other MergedCellsRecords */
/** sometimes the regions array is shared with other MergedCellsRecords */
private final CellRangeAddress[] _regions; private final CellRangeAddress[] _regions;
private final int _startIndex; private final int _startIndex;
private final int _numberOfRegions; 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) { public MergeCellsRecord(CellRangeAddress[] regions, int startIndex, int numberOfRegions) {
_regions = regions; _regions = regions;
_startIndex = startIndex; _startIndex = startIndex;
@ -63,7 +74,7 @@ public final class MergeCellsRecord extends StandardRecord implements Cloneable
/** /**
* @param index the n-th MergedRegion * @param index the n-th MergedRegion
* *
* @return MergedRegion at the given index representing the area that is Merged (r1,c1 - r2,c2) * @return MergedRegion at the given index representing the area that is Merged (r1,c1 - r2,c2)
*/ */
public CellRangeAddress getAreaAt(int index) { public CellRangeAddress getAreaAt(int index) {
@ -107,12 +118,15 @@ public final class MergeCellsRecord extends StandardRecord implements Cloneable
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public MergeCellsRecord clone() { public MergeCellsRecord clone() {
int nRegions = _numberOfRegions; return copy();
CellRangeAddress[] clonedRegions = new CellRangeAddress[nRegions]; }
for (int i = 0; i < clonedRegions.length; i++) {
clonedRegions[i] = _regions[_startIndex + i].copy(); @Override
} public MergeCellsRecord copy() {
return new MergeCellsRecord(clonedRegions, 0, nRegions); return new MergeCellsRecord(this);
} }
} }

View File

@ -18,17 +18,15 @@
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.Removal;
/** /**
* Title: Multiple Blank cell record(0x00BE)<p> * Represents a set of columns in a row with no value but with styling.
* Description: Represents a set of columns in a row with no value but with styling.<p>
* *
* REFERENCE: PG 329 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)
*
* @see BlankRecord * @see BlankRecord
*/ */
public final class MulBlankRecord extends StandardRecord { 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 _row;
private final int _firstCol; private final int _firstCol;
@ -55,7 +53,7 @@ public final class MulBlankRecord extends StandardRecord {
public int getFirstColumn() { public int getFirstColumn() {
return _firstCol; return _firstCol;
} }
/** /**
* @return ending column (last cell this holds in the row). Zero based * @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(_row);
out.writeShort(_firstCol); out.writeShort(_firstCol);
int nItems = _xfs.length; int nItems = _xfs.length;
for (int i = 0; i < nItems; i++) { for (short xf : _xfs) {
out.writeShort(_xfs[i]); out.writeShort(xf);
} }
out.writeShort(_lastCol); out.writeShort(_lastCol);
} }
@ -134,7 +132,15 @@ public final class MulBlankRecord extends StandardRecord {
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public MulBlankRecord clone() { public MulBlankRecord clone() {
return copy();
}
@Override
public MulBlankRecord copy() {
// immutable - so OK to return this // immutable - so OK to return this
return this; return this;
} }

View File

@ -23,18 +23,15 @@ import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.RecordFormatException; import org.apache.poi.util.RecordFormatException;
/** /**
* MULRK (0x00BD)<p>
*
* Used to store multiple RK numbers on a row. 1 MulRk = Multiple Cell values. * 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> * HSSF just converts this into multiple NUMBER records. READ-ONLY SUPPORT!
* REFERENCE: PG 330 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2) *
*
* @since 2.0-pre * @since 2.0-pre
*/ */
public final class MulRKRecord extends StandardRecord { 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 short field_2_first_col;
private final RkRec[] field_3_rks; private final RkRec[] field_3_rks;
private final short field_4_last_col; 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) * returns the xf index for column (coffset = column - field_2_first_col)
* *
* @param coffset the coffset = column - field_2_first_col * @param coffset the coffset = column - field_2_first_col
* *
* @return the XF index for the column * @return the XF index for the column
*/ */
public short getXFAt(int coffset) { 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) * returns the rk number for column (coffset = column - field_2_first_col)
* *
* @param coffset the coffset = column - field_2_first_col * @param coffset the coffset = column - field_2_first_col
* *
* @return the value (decoded into a double) * @return the value (decoded into a double)
*/ */
public double getRKNumberAt(int coffset) { public double getRKNumberAt(int coffset) {
@ -151,4 +148,10 @@ public final class MulRKRecord extends StandardRecord {
return retval; return retval;
} }
} }
@Override
public MulRKRecord copy() {
// immutable - so OK to return this
return this;
}
} }

View File

@ -18,145 +18,154 @@
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import org.apache.poi.util.HexDump; import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndianInput;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.StringUtil; import org.apache.poi.util.StringUtil;
/** /**
* Title: NAMECMT Record (0x0894)<p> * Defines a comment associated with a specified name.
*
* Description: Defines a comment associated with a specified name.
*/ */
public final class NameCommentRecord extends StandardRecord { public final class NameCommentRecord extends StandardRecord {
public final static short sid = 0x0894; public static final short sid = 0x0894;
private final short field_1_record_type; private final short field_1_record_type;
private final short field_2_frt_cell_ref_flag; private final short field_2_frt_cell_ref_flag;
private final long field_3_reserved; private final long field_3_reserved;
//private short field_4_name_length; //private short field_4_name_length;
//private short field_5_comment_length; //private short field_5_comment_length;
private String field_6_name_text; private String field_6_name_text;
private String field_7_comment_text; private String field_7_comment_text;
public NameCommentRecord(final String name, final String comment) { public NameCommentRecord(NameCommentRecord other) {
field_1_record_type = 0; field_1_record_type = other.field_1_record_type;
field_2_frt_cell_ref_flag = 0; field_2_frt_cell_ref_flag = other.field_2_frt_cell_ref_flag;
field_3_reserved = 0; field_3_reserved = other.field_3_reserved;
field_6_name_text = name; field_6_name_text = other.field_6_name_text;
field_7_comment_text = comment; field_7_comment_text = other.field_7_comment_text;
}
@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); public NameCommentRecord(final String name, final String comment) {
if (isCommentMultiByte) { field_1_record_type = 0;
StringUtil.putUnicodeLE(field_7_comment_text, out); field_2_frt_cell_ref_flag = 0;
} else { field_3_reserved = 0;
StringUtil.putCompressedUnicode(field_7_comment_text, out); field_6_name_text = name;
field_7_comment_text = comment;
} }
}
@Override /**
protected int getDataSize() { * @param ris the RecordInputstream to read the record from
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()) public NameCommentRecord(final RecordInputStream ris) {
+ (StringUtil.hasMultibyte(field_7_comment_text) ? field_7_comment_text.length()*2 : field_7_comment_text.length()); 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) {
* @param ris the RecordInputstream to read the record from field_6_name_text = StringUtil.readCompressedUnicode(ris, field_4_name_length);
*/ } else {
public NameCommentRecord(final RecordInputStream ris) { field_6_name_text = StringUtil.readUnicodeLE(ris, field_4_name_length);
field_1_record_type = ris.readShort(); }
field_2_frt_cell_ref_flag = ris.readShort(); if (ris.readByte() == 0) {
field_3_reserved = ris.readLong(); field_7_comment_text = StringUtil.readCompressedUnicode(ris, field_5_comment_length);
final int field_4_name_length = ris.readShort(); } else {
final int field_5_comment_length = ris.readShort(); field_7_comment_text = StringUtil.readUnicodeLE(ris, field_5_comment_length);
}
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
* return the non static version of the id for this record. public void serialize(final LittleEndianOutput out) {
*/ final int field_4_name_length = field_6_name_text.length();
@Override final int field_5_comment_length = field_7_comment_text.length();
public short getSid() {
return sid;
}
@Override out.writeShort(field_1_record_type);
public String toString() { out.writeShort(field_2_frt_cell_ref_flag);
final StringBuilder sb = new StringBuilder(); out.writeLong(field_3_reserved);
out.writeShort(field_4_name_length);
out.writeShort(field_5_comment_length);
sb.append("[NAMECMT]\n"); boolean isNameMultiByte = StringUtil.hasMultibyte(field_6_name_text);
sb.append(" .record type = ").append(HexDump.shortToHex(field_1_record_type)).append("\n"); out.writeByte(isNameMultiByte ? 1 : 0);
sb.append(" .frt cell ref flag = ").append(HexDump.byteToHex(field_2_frt_cell_ref_flag)).append("\n"); if (isNameMultiByte) {
sb.append(" .reserved = ").append(field_3_reserved).append("\n"); StringUtil.putUnicodeLE(field_6_name_text, out);
sb.append(" .name length = ").append(field_6_name_text.length()).append("\n"); } else {
sb.append(" .comment length = ").append(field_7_comment_text.length()).append("\n"); StringUtil.putCompressedUnicode(field_6_name_text, out);
sb.append(" .name = ").append(field_6_name_text).append("\n"); }
sb.append(" .comment = ").append(field_7_comment_text).append("\n"); boolean isCommentMultiByte = StringUtil.hasMultibyte(field_7_comment_text);
sb.append("[/NAMECMT]\n"); out.writeByte(isCommentMultiByte ? 1 : 0);
if (isCommentMultiByte) {
StringUtil.putUnicodeLE(field_7_comment_text, out);
} else {
StringUtil.putCompressedUnicode(field_7_comment_text, out);
}
}
return sb.toString(); @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());
}
/** /**
* @return the name of the NameRecord to which this comment applies. * return the non static version of the id for this record.
*/ */
public String getNameText() { @Override
return field_6_name_text; public short getSid() {
} return sid;
}
/**
* 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;
}
/** @Override
* @return the text of the comment. public String toString() {
*/ final StringBuilder sb = new StringBuilder();
public String getCommentText() {
return field_7_comment_text;
}
public void setCommentText(String comment) {
field_7_comment_text = comment;
}
public short getRecordType() { sb.append("[NAMECMT]\n");
return field_1_record_type; 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);
}
} }

View File

@ -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.ContinuableRecord;
import org.apache.poi.hssf.record.cont.ContinuableRecordOutput; 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.Area3DPtg;
import org.apache.poi.ss.formula.ptg.Ptg; import org.apache.poi.ss.formula.ptg.Ptg;
import org.apache.poi.ss.formula.ptg.Ref3DPtg; import org.apache.poi.ss.formula.ptg.Ref3DPtg;
import org.apache.poi.ss.formula.Formula; import org.apache.poi.util.HexDump;
import org.apache.poi.util.*; import org.apache.poi.util.LittleEndianByteArrayInputStream;
import org.apache.poi.util.LittleEndianInput;
import org.apache.poi.util.StringUtil;
/** /**
* Title: DEFINEDNAME Record (0x0018)<p> * Defines a named range within a workbook.
* Description: Defines a named range within a workbook.
*/ */
public final class NameRecord extends ContinuableRecord { public final class NameRecord extends ContinuableRecord {
public final static short sid = 0x0018; public static final short sid = 0x0018;
/**Included for completeness sake, not implemented */ /**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 */ /**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 */ /**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 */ /**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 */ /**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 static final byte BUILTIN_PRINT_AREA = 6;
public final static byte BUILTIN_PRINT_TITLE = 7; public static final byte BUILTIN_PRINT_TITLE = 7;
/**Included for completeness sake, not implemented */ /**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 */ /**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 */ /**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 */ /**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 */ /**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 { private static final class Option {
public static final int OPT_HIDDEN_NAME = 0x0001; public static final int OPT_HIDDEN_NAME = 0x0001;
@ -98,10 +100,26 @@ public final class NameRecord extends ContinuableRecord {
field_17_status_bar_text = ""; 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 * Constructor to create a built-in named region
* @param builtin Built-in byte representation for the name record, use the public constants * @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) 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 * Convenience Function to determine if the name is a built-in name
* *
* @return true, if the name is a built-in name * @return true, if the name is a built-in name
*/ */
public boolean isBuiltInName() public boolean isBuiltInName()
@ -590,4 +608,9 @@ public final class NameRecord extends ContinuableRecord {
return "Unknown"; return "Unknown";
} }
@Override
public NameRecord copy() {
return new NameRecord(this);
}
} }

View File

@ -18,27 +18,28 @@
package org.apache.poi.hssf.record; package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.Removal;
import org.apache.poi.util.StringUtil; import org.apache.poi.util.StringUtil;
/** /**
* NOTE: Comment Associated with a Cell (0x001C) * NOTE: Comment Associated with a Cell (0x001C)
*/ */
public final class NoteRecord extends StandardRecord implements Cloneable { public final class NoteRecord extends StandardRecord {
public final static short sid = 0x001C; public static final short sid = 0x001C;
public static final NoteRecord[] EMPTY_ARRAY = { }; public static final NoteRecord[] EMPTY_ARRAY = { };
/** /**
* Flag indicating that the comment is hidden (default) * Flag indicating that the comment is hidden (default)
*/ */
public final static short NOTE_HIDDEN = 0x0; public static final short NOTE_HIDDEN = 0x0;
/** /**
* Flag indicating that the comment is visible * Flag indicating that the comment is visible
*/ */
public final static short NOTE_VISIBLE = 0x2; public static final short NOTE_VISIBLE = 0x2;
private static final Byte DEFAULT_PADDING = Byte.valueOf((byte)0); private static final Byte DEFAULT_PADDING = (byte) 0;
private int field_1_row; private int field_1_row;
private int field_2_col; private int field_2_col;
@ -46,6 +47,7 @@ public final class NoteRecord extends StandardRecord implements Cloneable {
private int field_4_shapeid; private int field_4_shapeid;
private boolean field_5_hasMultibyte; private boolean field_5_hasMultibyte;
private String field_6_author; private String field_6_author;
/** /**
* Saves padding byte value to reduce delta during round-trip serialization.<br> * Saves padding byte value to reduce delta during round-trip serialization.<br>
* *
@ -64,6 +66,17 @@ public final class NoteRecord extends StandardRecord implements Cloneable {
field_7_padding = DEFAULT_PADDING; // seems to be always present regardless of author text field_7_padding = DEFAULT_PADDING; // seems to be always present regardless of author text
} }
public NoteRecord(NoteRecord other) {
super(other);
field_1_row = other.field_1_row;
field_2_col = other.field_2_col;
field_3_flags = other.field_3_flags;
field_4_shapeid = other.field_4_shapeid;
field_5_hasMultibyte = other.field_5_hasMultibyte;
field_6_author = other.field_6_author;
field_7_padding = other.field_7_padding;
}
/** /**
* @return id of this record. * @return id of this record.
*/ */
@ -73,7 +86,7 @@ public final class NoteRecord extends StandardRecord implements Cloneable {
/** /**
* Read the record data from the supplied <code>RecordInputStream</code> * Read the record data from the supplied <code>RecordInputStream</code>
* *
* @param in the RecordInputStream to read from * @param in the RecordInputStream to read from
*/ */
public NoteRecord(RecordInputStream in) { public NoteRecord(RecordInputStream in) {
@ -194,10 +207,10 @@ public final class NoteRecord extends StandardRecord implements Cloneable {
public void setFlags(short flags) { public void setFlags(short flags) {
field_3_flags = flags; field_3_flags = flags;
} }
/** /**
* For unit testing only! * For unit testing only!
* *
* @return true, if author element uses multi byte * @return true, if author element uses multi byte
*/ */
protected boolean authorIsMultibyte() { protected boolean authorIsMultibyte() {
@ -206,7 +219,7 @@ public final class NoteRecord extends StandardRecord implements Cloneable {
/** /**
* Object id for OBJ record that contains the comment * Object id for OBJ record that contains the comment
* *
* @return the Object id for OBJ record that contains the comment * @return the Object id for OBJ record that contains the comment
*/ */
public int getShapeId() { public int getShapeId() {
@ -215,7 +228,7 @@ public final class NoteRecord extends StandardRecord implements Cloneable {
/** /**
* Object id for OBJ record that contains the comment * Object id for OBJ record that contains the comment
* *
* @param id the Object id for OBJ record that contains the comment * @param id the Object id for OBJ record that contains the comment
*/ */
public void setShapeId(int id) { public void setShapeId(int id) {
@ -242,13 +255,15 @@ public final class NoteRecord extends StandardRecord implements Cloneable {
} }
@Override @Override
@SuppressWarnings("squid:S2975")
@Deprecated
@Removal(version = "5.0.0")
public NoteRecord clone() { public NoteRecord clone() {
NoteRecord rec = new NoteRecord(); return copy();
rec.field_1_row = field_1_row; }
rec.field_2_col = field_2_col;
rec.field_3_flags = field_3_flags; @Override
rec.field_4_shapeid = field_4_shapeid; public NoteRecord copy() {
rec.field_6_author = field_6_author; return new NoteRecord(this);
return rec;
} }
} }

Some files were not shown because too many files have changed in this diff Show More