You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by ki...@apache.org on 2015/07/19 21:00:38 UTC
svn commit: r1691843 [4/30] - in /poi/branches/common_sl: ./ .settings/
legal/ osgi/ osgi/src/ src/examples/src/org/apache/poi/hpsf/examples/
src/examples/src/org/apache/poi/hssf/usermodel/examples/
src/examples/src/org/apache/poi/ss/examples/ src/exam...
Modified: poi/branches/common_sl/src/java/org/apache/poi/hssf/record/CFHeaderRecord.java
URL: http://svn.apache.org/viewvc/poi/branches/common_sl/src/java/org/apache/poi/hssf/record/CFHeaderRecord.java?rev=1691843&r1=1691842&r2=1691843&view=diff
==============================================================================
--- poi/branches/common_sl/src/java/org/apache/poi/hssf/record/CFHeaderRecord.java (original)
+++ poi/branches/common_sl/src/java/org/apache/poi/hssf/record/CFHeaderRecord.java Sun Jul 19 19:00:32 2015
@@ -17,144 +17,39 @@
package org.apache.poi.hssf.record;
-import org.apache.poi.hssf.record.cf.CellRangeUtil;
import org.apache.poi.ss.util.CellRangeAddress;
-import org.apache.poi.ss.util.CellRangeAddressList;
-import org.apache.poi.util.LittleEndianOutput;
/**
- * Conditional Formatting Header record CFHEADER (0x01B0)
- *
- * @author Dmitriy Kumshayev
+ * Conditional Formatting Header record CFHEADER (0x01B0).
+ * Used to describe a {@link CFRuleRecord}.
+ * @see CFHeader12Record
*/
-public final class CFHeaderRecord extends StandardRecord {
- public static final short sid = 0x01B0;
+public final class CFHeaderRecord extends CFHeaderBase {
+ public static final short sid = 0x01B0;
- private int field_1_numcf;
- private int field_2_need_recalculation;
- private CellRangeAddress field_3_enclosing_cell_range;
- private CellRangeAddressList field_4_cell_ranges;
-
- /** Creates new CFHeaderRecord */
- public CFHeaderRecord()
- {
- field_4_cell_ranges = new CellRangeAddressList();
- }
- public CFHeaderRecord(CellRangeAddress[] regions, int nRules) {
- CellRangeAddress[] unmergedRanges = regions;
- CellRangeAddress[] mergeCellRanges = CellRangeUtil.mergeCellRanges(unmergedRanges);
- setCellRanges(mergeCellRanges);
- field_1_numcf = nRules;
- }
-
- public CFHeaderRecord(RecordInputStream in)
- {
- field_1_numcf = in.readShort();
- field_2_need_recalculation = in.readShort();
- field_3_enclosing_cell_range = new CellRangeAddress(in);
- field_4_cell_ranges = new CellRangeAddressList(in);
- }
-
- public int getNumberOfConditionalFormats()
- {
- return field_1_numcf;
- }
- public void setNumberOfConditionalFormats(int n)
- {
- field_1_numcf=n;
- }
-
- public boolean getNeedRecalculation()
- {
- return field_2_need_recalculation==1?true:false;
- }
-
- public void setNeedRecalculation(boolean b)
- {
- field_2_need_recalculation=b?1:0;
- }
-
- public CellRangeAddress getEnclosingCellRange()
- {
- return field_3_enclosing_cell_range;
- }
-
- public void setEnclosingCellRange(CellRangeAddress cr)
- {
- field_3_enclosing_cell_range = cr;
- }
-
- /**
- * Set cell ranges list to a single cell range and
- * modify the enclosing cell range accordingly.
- * @param cellRanges - list of CellRange objects
- */
- public void setCellRanges(CellRangeAddress[] cellRanges)
- {
- if(cellRanges == null)
- {
- throw new IllegalArgumentException("cellRanges must not be null");
- }
- CellRangeAddressList cral = new CellRangeAddressList();
- CellRangeAddress enclosingRange = null;
- for (int i = 0; i < cellRanges.length; i++)
- {
- CellRangeAddress cr = cellRanges[i];
- enclosingRange = CellRangeUtil.createEnclosingCellRange(cr, enclosingRange);
- cral.addCellRangeAddress(cr);
- }
- field_3_enclosing_cell_range = enclosingRange;
- field_4_cell_ranges = cral;
- }
-
- public CellRangeAddress[] getCellRanges() {
- return field_4_cell_ranges.getCellRangeAddresses();
- }
-
- public String toString()
- {
- StringBuffer buffer = new StringBuffer();
-
- buffer.append("[CFHEADER]\n");
- buffer.append(" .id = ").append(Integer.toHexString(sid)).append("\n");
- buffer.append(" .numCF = ").append(getNumberOfConditionalFormats()).append("\n");
- buffer.append(" .needRecalc = ").append(getNeedRecalculation()).append("\n");
- buffer.append(" .enclosingCellRange= ").append(getEnclosingCellRange()).append("\n");
- buffer.append(" .cfranges=[");
- for( int i=0; i<field_4_cell_ranges.countRanges(); i++)
- {
- buffer.append(i==0?"":",").append(field_4_cell_ranges.getCellRangeAddress(i).toString());
- }
- buffer.append("]\n");
- buffer.append("[/CFHEADER]\n");
- return buffer.toString();
- }
-
- protected int getDataSize() {
- return 4 // 2 short fields
- + CellRangeAddress.ENCODED_SIZE
- + field_4_cell_ranges.getSize();
- }
-
- public void serialize(LittleEndianOutput out) {
-
- out.writeShort(field_1_numcf);
- out.writeShort(field_2_need_recalculation);
- field_3_enclosing_cell_range.serialize(out);
- field_4_cell_ranges.serialize(out);
- }
-
- public short getSid() {
- return sid;
- }
-
- public Object clone()
- {
- CFHeaderRecord result = new CFHeaderRecord();
- result.field_1_numcf = field_1_numcf;
- result.field_2_need_recalculation = field_2_need_recalculation;
- result.field_3_enclosing_cell_range = field_3_enclosing_cell_range;
- result.field_4_cell_ranges = field_4_cell_ranges.copy();
- return result;
- }
+ /** Creates new CFHeaderRecord */
+ public CFHeaderRecord() {
+ createEmpty();
+ }
+ public CFHeaderRecord(CellRangeAddress[] regions, int nRules) {
+ super(regions, nRules);
+ }
+
+ public CFHeaderRecord(RecordInputStream in) {
+ read(in);
+ }
+
+ protected String getRecordName() {
+ return "CFHEADER";
+ }
+
+ public short getSid() {
+ return sid;
+ }
+
+ public Object clone() {
+ CFHeaderRecord result = new CFHeaderRecord();
+ super.copyTo(result);
+ return result;
+ }
}
Modified: poi/branches/common_sl/src/java/org/apache/poi/hssf/record/CFRuleRecord.java
URL: http://svn.apache.org/viewvc/poi/branches/common_sl/src/java/org/apache/poi/hssf/record/CFRuleRecord.java?rev=1691843&r1=1691842&r2=1691843&view=diff
==============================================================================
--- poi/branches/common_sl/src/java/org/apache/poi/hssf/record/CFRuleRecord.java (original)
+++ poi/branches/common_sl/src/java/org/apache/poi/hssf/record/CFRuleRecord.java Sun Jul 19 19:00:32 2015
@@ -19,512 +19,129 @@ package org.apache.poi.hssf.record;
import java.util.Arrays;
-import org.apache.poi.hssf.model.HSSFFormulaParser;
-import org.apache.poi.hssf.record.cf.BorderFormatting;
-import org.apache.poi.hssf.record.cf.FontFormatting;
-import org.apache.poi.hssf.record.cf.PatternFormatting;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.ss.formula.Formula;
-import org.apache.poi.ss.formula.FormulaType;
import org.apache.poi.ss.formula.ptg.Ptg;
-import org.apache.poi.util.BitField;
-import org.apache.poi.util.BitFieldFactory;
import org.apache.poi.util.LittleEndianOutput;
/**
- * Conditional Formatting Rule Record (0x01B1).<br/>
- *
- * @author Dmitriy Kumshayev
+ * Conditional Formatting Rule Record (0x01B1).
+ *
+ * <p>This is for the older-style Excel conditional formattings,
+ * new-style (Excel 2007+) also make use of {@link CFRule12Record}
+ * and {@link CFExRuleRecord} for their rules.
*/
-public final class CFRuleRecord extends StandardRecord {
+public final class CFRuleRecord extends CFRuleBase {
+ public static final short sid = 0x01B1;
- public static final short sid = 0x01B1;
+ /** Creates new CFRuleRecord */
+ private CFRuleRecord(byte conditionType, byte comparisonOperation) {
+ super(conditionType, comparisonOperation);
+ setDefaults();
+ }
- public static final class ComparisonOperator {
- public static final byte NO_COMPARISON = 0;
- public static final byte BETWEEN = 1;
- public static final byte NOT_BETWEEN = 2;
- public static final byte EQUAL = 3;
- public static final byte NOT_EQUAL = 4;
- public static final byte GT = 5;
- public static final byte LT = 6;
- public static final byte GE = 7;
- public static final byte LE = 8;
- }
-
- private byte field_1_condition_type;
- public static final byte CONDITION_TYPE_CELL_VALUE_IS = 1;
- public static final byte CONDITION_TYPE_FORMULA = 2;
-
- private byte field_2_comparison_operator;
-
- private int field_5_options;
-
- private static final BitField modificationBits = bf(0x003FFFFF); // Bits: font,align,bord,patt,prot
- private static final BitField alignHor = bf(0x00000001); // 0 = Horizontal alignment modified
- private static final BitField alignVer = bf(0x00000002); // 0 = Vertical alignment modified
- private static final BitField alignWrap = bf(0x00000004); // 0 = Text wrapped flag modified
- private static final BitField alignRot = bf(0x00000008); // 0 = Text rotation modified
- private static final BitField alignJustLast = bf(0x00000010); // 0 = Justify last line flag modified
- private static final BitField alignIndent = bf(0x00000020); // 0 = Indentation modified
- private static final BitField alignShrin = bf(0x00000040); // 0 = Shrink to fit flag modified
- private static final BitField notUsed1 = bf(0x00000080); // Always 1
- private static final BitField protLocked = bf(0x00000100); // 0 = Cell locked flag modified
- private static final BitField protHidden = bf(0x00000200); // 0 = Cell hidden flag modified
- private static final BitField bordLeft = bf(0x00000400); // 0 = Left border style and colour modified
- private static final BitField bordRight = bf(0x00000800); // 0 = Right border style and colour modified
- private static final BitField bordTop = bf(0x00001000); // 0 = Top border style and colour modified
- private static final BitField bordBot = bf(0x00002000); // 0 = Bottom border style and colour modified
- private static final BitField bordTlBr = bf(0x00004000); // 0 = Top-left to bottom-right border flag modified
- private static final BitField bordBlTr = bf(0x00008000); // 0 = Bottom-left to top-right border flag modified
- private static final BitField pattStyle = bf(0x00010000); // 0 = Pattern style modified
- private static final BitField pattCol = bf(0x00020000); // 0 = Pattern colour modified
- private static final BitField pattBgCol = bf(0x00040000); // 0 = Pattern background colour modified
- private static final BitField notUsed2 = bf(0x00380000); // Always 111
- private static final BitField undocumented = bf(0x03C00000); // Undocumented bits
- private static final BitField fmtBlockBits = bf(0x7C000000); // Bits: font,align,bord,patt,prot
- private static final BitField font = bf(0x04000000); // 1 = Record contains font formatting block
- private static final BitField align = bf(0x08000000); // 1 = Record contains alignment formatting block
- private static final BitField bord = bf(0x10000000); // 1 = Record contains border formatting block
- private static final BitField patt = bf(0x20000000); // 1 = Record contains pattern formatting block
- private static final BitField prot = bf(0x40000000); // 1 = Record contains protection formatting block
- private static final BitField alignTextDir = bf(0x80000000); // 0 = Text direction modified
-
-
- private static BitField bf(int i) {
- return BitFieldFactory.getInstance(i);
- }
-
- private short field_6_not_used;
-
- private FontFormatting _fontFormatting;
-
- private BorderFormatting _borderFormatting;
-
- private PatternFormatting _patternFormatting;
-
- private Formula field_17_formula1;
- private Formula field_18_formula2;
-
- /** Creates new CFRuleRecord */
- private CFRuleRecord(byte conditionType, byte comparisonOperation)
- {
- field_1_condition_type=conditionType;
- field_2_comparison_operator=comparisonOperation;
-
- // Set modification flags to 1: by default options are not modified
- field_5_options = modificationBits.setValue(field_5_options, -1);
- // Set formatting block flags to 0 (no formatting blocks)
- field_5_options = fmtBlockBits.setValue(field_5_options, 0);
- field_5_options = undocumented.clear(field_5_options);
-
- field_6_not_used = (short)0x8002; // Excel seems to write this value, but it doesn't seem to care what it reads
- _fontFormatting=null;
- _borderFormatting=null;
- _patternFormatting=null;
- field_17_formula1=Formula.create(Ptg.EMPTY_PTG_ARRAY);
- field_18_formula2=Formula.create(Ptg.EMPTY_PTG_ARRAY);
- }
-
- private CFRuleRecord(byte conditionType, byte comparisonOperation, Ptg[] formula1, Ptg[] formula2) {
- this(conditionType, comparisonOperation);
- field_17_formula1 = Formula.create(formula1);
- field_18_formula2 = Formula.create(formula2);
- }
-
- /**
- * Creates a new comparison operation rule
- */
+ private CFRuleRecord(byte conditionType, byte comparisonOperation, Ptg[] formula1, Ptg[] formula2) {
+ super(conditionType, comparisonOperation, formula1, formula2);
+ setDefaults();
+ }
+ private void setDefaults() {
+ // Set modification flags to 1: by default options are not modified
+ formatting_options = modificationBits.setValue(formatting_options, -1);
+ // Set formatting block flags to 0 (no formatting blocks)
+ formatting_options = fmtBlockBits.setValue(formatting_options, 0);
+ formatting_options = undocumented.clear(formatting_options);
+
+ formatting_not_used = (short)0x8002; // Excel seems to write this value, but it doesn't seem to care what it reads
+ _fontFormatting = null;
+ _borderFormatting = null;
+ _patternFormatting = null;
+ }
+
+ /**
+ * Creates a new comparison operation rule
+ */
public static CFRuleRecord create(HSSFSheet sheet, String formulaText) {
Ptg[] formula1 = parseFormula(formulaText, sheet);
return new CFRuleRecord(CONDITION_TYPE_FORMULA, ComparisonOperator.NO_COMPARISON,
formula1, null);
}
- /**
- * Creates a new comparison operation rule
- */
- public static CFRuleRecord create(HSSFSheet sheet, byte comparisonOperation,
- String formulaText1, String formulaText2) {
- Ptg[] formula1 = parseFormula(formulaText1, sheet);
- Ptg[] formula2 = parseFormula(formulaText2, sheet);
- return new CFRuleRecord(CONDITION_TYPE_CELL_VALUE_IS, comparisonOperation, formula1, formula2);
- }
-
- public CFRuleRecord(RecordInputStream in) {
- field_1_condition_type = in.readByte();
- field_2_comparison_operator = in.readByte();
- int field_3_formula1_len = in.readUShort();
- int field_4_formula2_len = in.readUShort();
- field_5_options = in.readInt();
- field_6_not_used = in.readShort();
-
- if (containsFontFormattingBlock()) {
- _fontFormatting = new FontFormatting(in);
- }
-
- if (containsBorderFormattingBlock()) {
- _borderFormatting = new BorderFormatting(in);
- }
-
- if (containsPatternFormattingBlock()) {
- _patternFormatting = new PatternFormatting(in);
- }
-
- // "You may not use unions, intersections or array constants in Conditional Formatting criteria"
- field_17_formula1 = Formula.read(field_3_formula1_len, in);
- field_18_formula2 = Formula.read(field_4_formula2_len, in);
- }
-
- public byte getConditionType()
- {
- return field_1_condition_type;
- }
-
- public boolean containsFontFormattingBlock()
- {
- return getOptionFlag(font);
- }
- public void setFontFormatting(FontFormatting fontFormatting)
- {
- _fontFormatting = fontFormatting;
- setOptionFlag(fontFormatting != null, font);
- }
- public FontFormatting getFontFormatting()
- {
- if( containsFontFormattingBlock())
- {
- return _fontFormatting;
- }
- return null;
- }
-
- public boolean containsAlignFormattingBlock()
- {
- return getOptionFlag(align);
- }
- public void setAlignFormattingUnchanged()
- {
- setOptionFlag(false,align);
- }
-
- public boolean containsBorderFormattingBlock()
- {
- return getOptionFlag(bord);
- }
- public void setBorderFormatting(BorderFormatting borderFormatting)
- {
- _borderFormatting = borderFormatting;
- setOptionFlag(borderFormatting != null, bord);
- }
- public BorderFormatting getBorderFormatting()
- {
- if( containsBorderFormattingBlock())
- {
- return _borderFormatting;
- }
- return null;
- }
-
- public boolean containsPatternFormattingBlock()
- {
- return getOptionFlag(patt);
- }
- public void setPatternFormatting(PatternFormatting patternFormatting)
- {
- _patternFormatting = patternFormatting;
- setOptionFlag(patternFormatting!=null, patt);
- }
- public PatternFormatting getPatternFormatting()
- {
- if( containsPatternFormattingBlock())
- {
- return _patternFormatting;
- }
- return null;
- }
-
- public boolean containsProtectionFormattingBlock()
- {
- return getOptionFlag(prot);
- }
- public void setProtectionFormattingUnchanged()
- {
- setOptionFlag(false,prot);
- }
-
- public void setComparisonOperation(byte operation)
- {
- field_2_comparison_operator = operation;
- }
-
- public byte getComparisonOperation()
- {
- return field_2_comparison_operator;
- }
-
-
- /**
- * get the option flags
- *
- * @return bit mask
- */
- public int getOptions()
- {
- return field_5_options;
- }
-
- private boolean isModified(BitField field)
- {
- return !field.isSet(field_5_options);
- }
-
- private void setModified(boolean modified, BitField field)
- {
- field_5_options = field.setBoolean(field_5_options, !modified);
- }
-
- public boolean isLeftBorderModified()
- {
- return isModified(bordLeft);
- }
-
- public void setLeftBorderModified(boolean modified)
- {
- setModified(modified,bordLeft);
- }
-
- public boolean isRightBorderModified()
- {
- return isModified(bordRight);
- }
-
- public void setRightBorderModified(boolean modified)
- {
- setModified(modified,bordRight);
- }
-
- public boolean isTopBorderModified()
- {
- return isModified(bordTop);
- }
-
- public void setTopBorderModified(boolean modified)
- {
- setModified(modified,bordTop);
- }
-
- public boolean isBottomBorderModified()
- {
- return isModified(bordBot);
- }
-
- public void setBottomBorderModified(boolean modified)
- {
- setModified(modified,bordBot);
- }
-
- public boolean isTopLeftBottomRightBorderModified()
- {
- return isModified(bordTlBr);
- }
-
- public void setTopLeftBottomRightBorderModified(boolean modified)
- {
- setModified(modified,bordTlBr);
- }
-
- public boolean isBottomLeftTopRightBorderModified()
- {
- return isModified(bordBlTr);
- }
-
- public void setBottomLeftTopRightBorderModified(boolean modified)
- {
- setModified(modified,bordBlTr);
- }
-
- public boolean isPatternStyleModified()
- {
- return isModified(pattStyle);
- }
-
- public void setPatternStyleModified(boolean modified)
- {
- setModified(modified,pattStyle);
- }
-
- public boolean isPatternColorModified()
- {
- return isModified(pattCol);
- }
-
- public void setPatternColorModified(boolean modified)
- {
- setModified(modified,pattCol);
- }
-
- public boolean isPatternBackgroundColorModified()
- {
- return isModified(pattBgCol);
- }
-
- public void setPatternBackgroundColorModified(boolean modified)
- {
- setModified(modified,pattBgCol);
- }
-
- private boolean getOptionFlag(BitField field)
- {
- return field.isSet(field_5_options);
- }
-
- private void setOptionFlag(boolean flag, BitField field)
- {
- field_5_options = field.setBoolean(field_5_options, flag);
- }
-
- /**
- * get the stack of the 1st expression as a list
- *
- * @return list of tokens (casts stack to a list and returns it!)
- * this method can return null is we are unable to create Ptgs from
- * existing excel file
- * callers should check for null!
- */
-
- public Ptg[] getParsedExpression1()
- {
- return field_17_formula1.getTokens();
- }
- public void setParsedExpression1(Ptg[] ptgs) {
- field_17_formula1 = Formula.create(ptgs);
- }
-
- /**
- * get the stack of the 2nd expression as a list
- *
- * @return array of {@link Ptg}s, possibly <code>null</code>
- */
- public Ptg[] getParsedExpression2() {
- return Formula.getTokens(field_18_formula2);
- }
- public void setParsedExpression2(Ptg[] ptgs) {
- field_18_formula2 = Formula.create(ptgs);
- }
-
- public short getSid()
- {
- return sid;
- }
-
- /**
- * @param ptgs must not be <code>null</code>
- * @return encoded size of the formula tokens (does not include 2 bytes for ushort length)
- */
- private static int getFormulaSize(Formula formula) {
- return formula.getEncodedTokenSize();
- }
-
- /**
- * called by the class that is responsible for writing this sucker.
- * Subclasses should implement this so that their data is passed back in a
- * byte array.
- *
- * @param out the stream to write to
- */
- public void serialize(LittleEndianOutput out) {
-
- int formula1Len=getFormulaSize(field_17_formula1);
- int formula2Len=getFormulaSize(field_18_formula2);
-
- out.writeByte(field_1_condition_type);
- out.writeByte(field_2_comparison_operator);
- out.writeShort(formula1Len);
- out.writeShort(formula2Len);
- out.writeInt(field_5_options);
- out.writeShort(field_6_not_used);
-
- if (containsFontFormattingBlock()) {
- byte[] fontFormattingRawRecord = _fontFormatting.getRawRecord();
- out.write(fontFormattingRawRecord);
- }
-
- if (containsBorderFormattingBlock()) {
- _borderFormatting.serialize(out);
- }
-
- if (containsPatternFormattingBlock()) {
- _patternFormatting.serialize(out);
- }
-
- field_17_formula1.serializeTokens(out);
- field_18_formula2.serializeTokens(out);
- }
-
- protected int getDataSize() {
- int i = 12 +
- (containsFontFormattingBlock()?_fontFormatting.getRawRecord().length:0)+
- (containsBorderFormattingBlock()?8:0)+
- (containsPatternFormattingBlock()?4:0)+
- getFormulaSize(field_17_formula1)+
- getFormulaSize(field_18_formula2);
- return i
- ;
- }
-
-
- public String toString() {
- StringBuffer buffer = new StringBuffer();
- buffer.append("[CFRULE]\n");
- buffer.append(" .condition_type =").append(field_1_condition_type).append("\n");
- buffer.append(" OPTION FLAGS=0x").append(Integer.toHexString(getOptions())).append("\n");
- if (containsFontFormattingBlock()) {
- buffer.append(_fontFormatting.toString()).append("\n");
- }
- if (containsBorderFormattingBlock()) {
- buffer.append(_borderFormatting.toString()).append("\n");
- }
- if (containsPatternFormattingBlock()) {
- buffer.append(_patternFormatting.toString()).append("\n");
- }
- buffer.append(" Formula 1 =").append(Arrays.toString(field_17_formula1.getTokens())).append("\n");
- buffer.append(" Formula 2 =").append(Arrays.toString(field_18_formula2.getTokens())).append("\n");
- buffer.append("[/CFRULE]\n");
- return buffer.toString();
- }
-
- public Object clone() {
- CFRuleRecord rec = new CFRuleRecord(field_1_condition_type, field_2_comparison_operator);
- rec.field_5_options = field_5_options;
- rec.field_6_not_used = field_6_not_used;
- if (containsFontFormattingBlock()) {
- rec._fontFormatting = (FontFormatting) _fontFormatting.clone();
- }
- if (containsBorderFormattingBlock()) {
- rec._borderFormatting = (BorderFormatting) _borderFormatting.clone();
- }
- if (containsPatternFormattingBlock()) {
- rec._patternFormatting = (PatternFormatting) _patternFormatting.clone();
- }
- rec.field_17_formula1 = field_17_formula1.copy();
- rec.field_18_formula2 = field_18_formula2.copy();
-
- return rec;
- }
-
- /**
- * TODO - parse conditional format formulas properly i.e. produce tRefN and tAreaN instead of tRef and tArea
- * this call will produce the wrong results if the formula contains any cell references
- * One approach might be to apply the inverse of SharedFormulaRecord.convertSharedFormulas(Stack, int, int)
- * Note - two extra parameters (rowIx & colIx) will be required. They probably come from one of the Region objects.
- *
- * @return <code>null</code> if <tt>formula</tt> was null.
- */
- private static Ptg[] parseFormula(String formula, HSSFSheet sheet) {
- if(formula == null) {
- return null;
+ /**
+ * Creates a new comparison operation rule
+ */
+ public static CFRuleRecord create(HSSFSheet sheet, byte comparisonOperation,
+ String formulaText1, String formulaText2) {
+ Ptg[] formula1 = parseFormula(formulaText1, sheet);
+ Ptg[] formula2 = parseFormula(formulaText2, sheet);
+ return new CFRuleRecord(CONDITION_TYPE_CELL_VALUE_IS, comparisonOperation, formula1, formula2);
+ }
+
+ public CFRuleRecord(RecordInputStream in) {
+ setConditionType(in.readByte());
+ setComparisonOperation(in.readByte());
+ int field_3_formula1_len = in.readUShort();
+ int field_4_formula2_len = in.readUShort();
+ readFormatOptions(in);
+
+ // "You may not use unions, intersections or array constants in Conditional Formatting criteria"
+ setFormula1(Formula.read(field_3_formula1_len, in));
+ setFormula2(Formula.read(field_4_formula2_len, in));
+ }
+
+ public short getSid() {
+ return sid;
+ }
+
+ /**
+ * called by the class that is responsible for writing this sucker.
+ * Subclasses should implement this so that their data is passed back in a
+ * byte array.
+ *
+ * @param out the stream to write to
+ */
+ public void serialize(LittleEndianOutput out) {
+ int formula1Len=getFormulaSize(getFormula1());
+ int formula2Len=getFormulaSize(getFormula2());
+
+ out.writeByte(getConditionType());
+ out.writeByte(getComparisonOperation());
+ out.writeShort(formula1Len);
+ out.writeShort(formula2Len);
+
+ serializeFormattingBlock(out);
+
+ getFormula1().serializeTokens(out);
+ getFormula2().serializeTokens(out);
+ }
+
+ protected int getDataSize() {
+ return 6 + getFormattingBlockSize() +
+ getFormulaSize(getFormula1())+
+ getFormulaSize(getFormula2());
+ }
+
+ public String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("[CFRULE]\n");
+ buffer.append(" .condition_type =").append(getConditionType()).append("\n");
+ buffer.append(" OPTION FLAGS=0x").append(Integer.toHexString(getOptions())).append("\n");
+ if (containsFontFormattingBlock()) {
+ buffer.append(_fontFormatting.toString()).append("\n");
}
- int sheetIndex = sheet.getWorkbook().getSheetIndex(sheet);
- return HSSFFormulaParser.parse(formula, sheet.getWorkbook(), FormulaType.CELL, sheetIndex);
+ if (containsBorderFormattingBlock()) {
+ buffer.append(_borderFormatting.toString()).append("\n");
+ }
+ if (containsPatternFormattingBlock()) {
+ buffer.append(_patternFormatting.toString()).append("\n");
+ }
+ buffer.append(" Formula 1 =").append(Arrays.toString(getFormula1().getTokens())).append("\n");
+ buffer.append(" Formula 2 =").append(Arrays.toString(getFormula2().getTokens())).append("\n");
+ buffer.append("[/CFRULE]\n");
+ return buffer.toString();
+ }
+
+ public Object clone() {
+ CFRuleRecord rec = new CFRuleRecord(getConditionType(), getComparisonOperation());
+ super.copyTo(rec);
+ return rec;
}
}
Modified: poi/branches/common_sl/src/java/org/apache/poi/hssf/record/FeatRecord.java
URL: http://svn.apache.org/viewvc/poi/branches/common_sl/src/java/org/apache/poi/hssf/record/FeatRecord.java?rev=1691843&r1=1691842&r2=1691843&view=diff
==============================================================================
--- poi/branches/common_sl/src/java/org/apache/poi/hssf/record/FeatRecord.java (original)
+++ poi/branches/common_sl/src/java/org/apache/poi/hssf/record/FeatRecord.java Sun Jul 19 19:00:32 2015
@@ -34,8 +34,11 @@ import org.apache.poi.util.POILogger;
* up with a {@link FeatHdrRecord}.
*/
public final class FeatRecord extends StandardRecord {
- private static POILogger logger = POILogFactory.getLogger(FeatRecord.class);
- public final static short sid = 0x0868;
+ private static POILogger logger = POILogFactory.getLogger(FeatRecord.class);
+ public final static short sid = 0x0868;
+ // SIDs from newer versions
+ public final static short v11_sid = 0x0872;
+ public final static short v12_sid = 0x0878;
private FtrHeader futureHeader;
Modified: poi/branches/common_sl/src/java/org/apache/poi/hssf/record/NameCommentRecord.java
URL: http://svn.apache.org/viewvc/poi/branches/common_sl/src/java/org/apache/poi/hssf/record/NameCommentRecord.java?rev=1691843&r1=1691842&r2=1691843&view=diff
==============================================================================
--- poi/branches/common_sl/src/java/org/apache/poi/hssf/record/NameCommentRecord.java (original)
+++ poi/branches/common_sl/src/java/org/apache/poi/hssf/record/NameCommentRecord.java Sun Jul 19 19:00:32 2015
@@ -62,17 +62,27 @@ public final class NameCommentRecord ext
out.writeShort(field_4_name_length);
out.writeShort(field_5_comment_length);
- out.writeByte(0);
- StringUtil.putCompressedUnicode(field_6_name_text, out);
- out.writeByte(0);
- StringUtil.putCompressedUnicode(field_7_comment_text, out);
+ boolean isNameMultiByte = StringUtil.hasMultibyte(field_6_name_text);
+ out.writeByte(isNameMultiByte ? 1 : 0);
+ if (isNameMultiByte) {
+ StringUtil.putUnicodeLE(field_6_name_text, out);
+ } else {
+ StringUtil.putCompressedUnicode(field_6_name_text, out);
+ }
+ boolean isCommentMultiByte = StringUtil.hasMultibyte(field_7_comment_text);
+ out.writeByte(isCommentMultiByte ? 1 : 0);
+ if (isCommentMultiByte) {
+ StringUtil.putUnicodeLE(field_7_comment_text, out);
+ } else {
+ StringUtil.putCompressedUnicode(field_7_comment_text, out);
+ }
}
@Override
protected int getDataSize() {
return 18 // 4 shorts + 1 long + 2 spurious 'nul's
- + field_6_name_text.length()
- + field_7_comment_text.length();
+ + (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());
}
/**
@@ -86,10 +96,16 @@ public final class NameCommentRecord ext
final int field_4_name_length = in.readShort();
final int field_5_comment_length = in.readShort();
- in.readByte(); //spurious NUL
- field_6_name_text = StringUtil.readCompressedUnicode(in, field_4_name_length);
- in.readByte(); //spurious NUL
- field_7_comment_text = StringUtil.readCompressedUnicode(in, field_5_comment_length);
+ if (in.readByte() == 0) {
+ field_6_name_text = StringUtil.readCompressedUnicode(in, field_4_name_length);
+ } else {
+ field_6_name_text = StringUtil.readUnicodeLE(in, field_4_name_length);
+ }
+ if (in.readByte() == 0) {
+ field_7_comment_text = StringUtil.readCompressedUnicode(in, field_5_comment_length);
+ } else {
+ field_7_comment_text = StringUtil.readUnicodeLE(in, field_5_comment_length);
+ }
}
/**
Modified: poi/branches/common_sl/src/java/org/apache/poi/hssf/record/NameRecord.java
URL: http://svn.apache.org/viewvc/poi/branches/common_sl/src/java/org/apache/poi/hssf/record/NameRecord.java?rev=1691843&r1=1691842&r2=1691843&view=diff
==============================================================================
--- poi/branches/common_sl/src/java/org/apache/poi/hssf/record/NameRecord.java (original)
+++ poi/branches/common_sl/src/java/org/apache/poi/hssf/record/NameRecord.java Sun Jul 19 19:00:32 2015
@@ -411,11 +411,12 @@ public final class NameRecord extends Co
* @return extern sheet index
*/
public int getExternSheetNumber(){
- if (field_13_name_definition.getEncodedSize() < 1) {
+ Ptg[] tokens = field_13_name_definition.getTokens();
+ if (tokens.length == 0) {
return 0;
}
- Ptg ptg = field_13_name_definition.getTokens()[0];
+ Ptg ptg = tokens[0];
if (ptg.getClass() == Area3DPtg.class){
return ((Area3DPtg) ptg).getExternSheetIndex();
Modified: poi/branches/common_sl/src/java/org/apache/poi/hssf/record/RecordFactory.java
URL: http://svn.apache.org/viewvc/poi/branches/common_sl/src/java/org/apache/poi/hssf/record/RecordFactory.java?rev=1691843&r1=1691842&r2=1691843&view=diff
==============================================================================
--- poi/branches/common_sl/src/java/org/apache/poi/hssf/record/RecordFactory.java (original)
+++ poi/branches/common_sl/src/java/org/apache/poi/hssf/record/RecordFactory.java Sun Jul 19 19:00:32 2015
@@ -62,425 +62,420 @@ import org.apache.poi.hssf.record.pivott
* Description: Takes a stream and outputs an array of Record objects.<P>
*
* @see org.apache.poi.hssf.eventmodel.EventRecordFactory
- * @author Andrew C. Oliver (acoliver at apache dot org)
- * @author Marc Johnson (mjohnson at apache dot org)
- * @author Glen Stampoultzis (glens at apache.org)
- * @author Csaba Nagy (ncsaba at yahoo dot com)
*/
public final class RecordFactory {
- private static final int NUM_RECORDS = 512;
+ private static final int NUM_RECORDS = 512;
- private interface I_RecordCreator {
- Record create(RecordInputStream in);
+ private interface I_RecordCreator {
+ Record create(RecordInputStream in);
- Class<? extends Record> getRecordClass();
- }
- private static final class ReflectionConstructorRecordCreator implements I_RecordCreator {
-
- private final Constructor<? extends Record> _c;
- public ReflectionConstructorRecordCreator(Constructor<? extends Record> c) {
- _c = c;
- }
- public Record create(RecordInputStream in) {
- Object[] args = { in, };
- try {
- return _c.newInstance(args);
- } catch (IllegalArgumentException e) {
- throw new RuntimeException(e);
- } catch (InstantiationException e) {
- throw new RuntimeException(e);
- } catch (IllegalAccessException e) {
- throw new RuntimeException(e);
- } catch (InvocationTargetException e) {
- Throwable t = e.getTargetException();
- if (t instanceof RecordFormatException) {
- throw (RecordFormatException)t;
- } else if (t instanceof EncryptedDocumentException) {
- throw (EncryptedDocumentException)t;
- } else {
- throw new RecordFormatException("Unable to construct record instance" , t);
- }
- }
- }
- public Class<? extends Record> getRecordClass() {
- return _c.getDeclaringClass();
- }
- }
- /**
- * A "create" method is used instead of the usual constructor if the created record might
- * be of a different class to the declaring class.
- */
- private static final class ReflectionMethodRecordCreator implements I_RecordCreator {
-
- private final Method _m;
- public ReflectionMethodRecordCreator(Method m) {
- _m = m;
- }
- public Record create(RecordInputStream in) {
- Object[] args = { in, };
- try {
- return (Record) _m.invoke(null, args);
- } catch (IllegalArgumentException e) {
- throw new RuntimeException(e);
- } catch (IllegalAccessException e) {
- throw new RuntimeException(e);
- } catch (InvocationTargetException e) {
- throw new RecordFormatException("Unable to construct record instance" , e.getTargetException());
- }
- }
- @SuppressWarnings("unchecked")
- public Class<? extends Record> getRecordClass() {
- return (Class<? extends Record>) _m.getDeclaringClass();
- }
- }
-
-
- private static final Class<?>[] CONSTRUCTOR_ARGS = { RecordInputStream.class, };
-
- /**
- * contains the classes for all the records we want to parse.<br/>
- * Note - this most but not *every* subclass of Record.
- */
- @SuppressWarnings("unchecked")
- private static final Class<? extends Record>[] recordClasses = new Class[] {
- ArrayRecord.class,
+ Class<? extends Record> getRecordClass();
+ }
+ private static final class ReflectionConstructorRecordCreator implements I_RecordCreator {
+
+ private final Constructor<? extends Record> _c;
+ public ReflectionConstructorRecordCreator(Constructor<? extends Record> c) {
+ _c = c;
+ }
+ public Record create(RecordInputStream in) {
+ Object[] args = { in, };
+ try {
+ return _c.newInstance(args);
+ } catch (IllegalArgumentException e) {
+ throw new RuntimeException(e);
+ } catch (InstantiationException e) {
+ throw new RuntimeException(e);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ } catch (InvocationTargetException e) {
+ Throwable t = e.getTargetException();
+ if (t instanceof RecordFormatException) {
+ throw (RecordFormatException)t;
+ } else if (t instanceof EncryptedDocumentException) {
+ throw (EncryptedDocumentException)t;
+ } else {
+ throw new RecordFormatException("Unable to construct record instance" , t);
+ }
+ }
+ }
+ public Class<? extends Record> getRecordClass() {
+ return _c.getDeclaringClass();
+ }
+ }
+ /**
+ * A "create" method is used instead of the usual constructor if the created record might
+ * be of a different class to the declaring class.
+ */
+ private static final class ReflectionMethodRecordCreator implements I_RecordCreator {
+ private final Method _m;
+ public ReflectionMethodRecordCreator(Method m) {
+ _m = m;
+ }
+ public Record create(RecordInputStream in) {
+ Object[] args = { in, };
+ try {
+ return (Record) _m.invoke(null, args);
+ } catch (IllegalArgumentException e) {
+ throw new RuntimeException(e);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ } catch (InvocationTargetException e) {
+ throw new RecordFormatException("Unable to construct record instance" , e.getTargetException());
+ }
+ }
+ @SuppressWarnings("unchecked")
+ public Class<? extends Record> getRecordClass() {
+ return (Class<? extends Record>) _m.getDeclaringClass();
+ }
+ }
+
+ private static final Class<?>[] CONSTRUCTOR_ARGS = { RecordInputStream.class, };
+
+ /**
+ * contains the classes for all the records we want to parse.<br/>
+ * Note - this most but not *every* subclass of Record.
+ */
+ @SuppressWarnings("unchecked")
+ private static final Class<? extends Record>[] recordClasses = new Class[] {
+ ArrayRecord.class,
AutoFilterInfoRecord.class,
BackupRecord.class,
- BlankRecord.class,
- BOFRecord.class,
- BookBoolRecord.class,
- BoolErrRecord.class,
- BottomMarginRecord.class,
- BoundSheetRecord.class,
- CalcCountRecord.class,
- CalcModeRecord.class,
- CFHeaderRecord.class,
- CFRuleRecord.class,
- ChartRecord.class,
- ChartTitleFormatRecord.class,
- CodepageRecord.class,
- ColumnInfoRecord.class,
- ContinueRecord.class,
- CountryRecord.class,
- CRNCountRecord.class,
- CRNRecord.class,
- DateWindow1904Record.class,
- DBCellRecord.class,
- DConRefRecord.class,
- DefaultColWidthRecord.class,
- DefaultRowHeightRecord.class,
- DeltaRecord.class,
- DimensionsRecord.class,
- DrawingGroupRecord.class,
- DrawingRecord.class,
- DrawingSelectionRecord.class,
- DSFRecord.class,
- DVALRecord.class,
- DVRecord.class,
- EOFRecord.class,
- ExtendedFormatRecord.class,
- ExternalNameRecord.class,
- ExternSheetRecord.class,
- ExtSSTRecord.class,
- FeatRecord.class,
- FeatHdrRecord.class,
- FilePassRecord.class,
- FileSharingRecord.class,
- FnGroupCountRecord.class,
- FontRecord.class,
- FooterRecord.class,
- FormatRecord.class,
- FormulaRecord.class,
- GridsetRecord.class,
- GutsRecord.class,
- HCenterRecord.class,
- HeaderRecord.class,
+ BlankRecord.class,
+ BOFRecord.class,
+ BookBoolRecord.class,
+ BoolErrRecord.class,
+ BottomMarginRecord.class,
+ BoundSheetRecord.class,
+ CalcCountRecord.class,
+ CalcModeRecord.class,
+ CFHeaderRecord.class,
+ CFHeader12Record.class,
+ CFRuleRecord.class,
+ CFRule12Record.class,
+ ChartRecord.class,
+ ChartTitleFormatRecord.class,
+ CodepageRecord.class,
+ ColumnInfoRecord.class,
+ ContinueRecord.class,
+ CountryRecord.class,
+ CRNCountRecord.class,
+ CRNRecord.class,
+ DateWindow1904Record.class,
+ DBCellRecord.class,
+ DConRefRecord.class,
+ DefaultColWidthRecord.class,
+ DefaultRowHeightRecord.class,
+ DeltaRecord.class,
+ DimensionsRecord.class,
+ DrawingGroupRecord.class,
+ DrawingRecord.class,
+ DrawingSelectionRecord.class,
+ DSFRecord.class,
+ DVALRecord.class,
+ DVRecord.class,
+ EOFRecord.class,
+ ExtendedFormatRecord.class,
+ ExternalNameRecord.class,
+ ExternSheetRecord.class,
+ ExtSSTRecord.class,
+ FeatRecord.class,
+ FeatHdrRecord.class,
+ FilePassRecord.class,
+ FileSharingRecord.class,
+ FnGroupCountRecord.class,
+ FontRecord.class,
+ FooterRecord.class,
+ FormatRecord.class,
+ FormulaRecord.class,
+ GridsetRecord.class,
+ GutsRecord.class,
+ HCenterRecord.class,
+ HeaderRecord.class,
HeaderFooterRecord.class,
- HideObjRecord.class,
- HorizontalPageBreakRecord.class,
- HyperlinkRecord.class,
- IndexRecord.class,
- InterfaceEndRecord.class,
- InterfaceHdrRecord.class,
- IterationRecord.class,
- LabelRecord.class,
- LabelSSTRecord.class,
- LeftMarginRecord.class,
- LegendRecord.class,
- MergeCellsRecord.class,
- MMSRecord.class,
- MulBlankRecord.class,
- MulRKRecord.class,
- NameRecord.class,
- NameCommentRecord.class,
- NoteRecord.class,
- NumberRecord.class,
- ObjectProtectRecord.class,
- ObjRecord.class,
- PaletteRecord.class,
- PaneRecord.class,
- PasswordRecord.class,
- PasswordRev4Record.class,
- PrecisionRecord.class,
- PrintGridlinesRecord.class,
- PrintHeadersRecord.class,
- PrintSetupRecord.class,
- ProtectionRev4Record.class,
- ProtectRecord.class,
- RecalcIdRecord.class,
- RefModeRecord.class,
- RefreshAllRecord.class,
- RightMarginRecord.class,
- RKRecord.class,
- RowRecord.class,
- SaveRecalcRecord.class,
- ScenarioProtectRecord.class,
- SelectionRecord.class,
- SeriesRecord.class,
- SeriesTextRecord.class,
- SharedFormulaRecord.class,
- SSTRecord.class,
- StringRecord.class,
- StyleRecord.class,
- SupBookRecord.class,
- TabIdRecord.class,
- TableRecord.class,
- TableStylesRecord.class,
- TextObjectRecord.class,
- TopMarginRecord.class,
- UncalcedRecord.class,
- UseSelFSRecord.class,
- UserSViewBegin.class,
- UserSViewEnd.class,
- ValueRangeRecord.class,
- VCenterRecord.class,
- VerticalPageBreakRecord.class,
- WindowOneRecord.class,
- WindowProtectRecord.class,
- WindowTwoRecord.class,
- WriteAccessRecord.class,
- WriteProtectRecord.class,
- WSBoolRecord.class,
-
- // chart records
- BeginRecord.class,
- ChartFRTInfoRecord.class,
- ChartStartBlockRecord.class,
- ChartEndBlockRecord.class,
-// TODO ChartFormatRecord.class,
- ChartStartObjectRecord.class,
- ChartEndObjectRecord.class,
- CatLabRecord.class,
- DataFormatRecord.class,
- EndRecord.class,
- LinkedDataRecord.class,
- SeriesToChartGroupRecord.class,
-
- // pivot table records
- DataItemRecord.class,
- ExtendedPivotTableViewFieldsRecord.class,
- PageItemRecord.class,
- StreamIDRecord.class,
- ViewDefinitionRecord.class,
- ViewFieldsRecord.class,
- ViewSourceRecord.class,
- };
-
- /**
- * cache of the recordsToMap();
- */
- private static final Map<Integer, I_RecordCreator> _recordCreatorsById = recordsToMap(recordClasses);
-
- private static short[] _allKnownRecordSIDs;
-
- /**
- * Debug / diagnosis method<br/>
- * Gets the POI implementation class for a given <tt>sid</tt>. Only a subset of the any BIFF
- * records are actually interpreted by POI. A few others are known but not interpreted
- * (see {@link UnknownRecord#getBiffName(int)}).
- * @return the POI implementation class for the specified record <tt>sid</tt>.
- * <code>null</code> if the specified record is not interpreted by POI.
- */
- public static Class<? extends Record> getRecordClass(int sid) {
- I_RecordCreator rc = _recordCreatorsById.get(Integer.valueOf(sid));
- if (rc == null) {
- return null;
- }
- return rc.getRecordClass();
- }
- /**
- * create a record, if there are MUL records than multiple records
- * are returned digested into the non-mul form.
- */
- public static Record [] createRecord(RecordInputStream in) {
-
- Record record = createSingleRecord(in);
- if (record instanceof DBCellRecord) {
- // Not needed by POI. Regenerated from scratch by POI when spreadsheet is written
- return new Record[] { null, };
- }
- if (record instanceof RKRecord) {
- return new Record[] { convertToNumberRecord((RKRecord) record), };
- }
- if (record instanceof MulRKRecord) {
- return convertRKRecords((MulRKRecord)record);
- }
- return new Record[] { record, };
- }
-
- public static Record createSingleRecord(RecordInputStream in) {
- I_RecordCreator constructor = _recordCreatorsById.get(Integer.valueOf(in.getSid()));
-
- if (constructor == null) {
- return new UnknownRecord(in);
- }
-
- return constructor.create(in);
- }
-
- /**
- * RK record is a slightly smaller alternative to NumberRecord
- * POI likes NumberRecord better
- */
- public static NumberRecord convertToNumberRecord(RKRecord rk) {
- NumberRecord num = new NumberRecord();
-
- num.setColumn(rk.getColumn());
- num.setRow(rk.getRow());
- num.setXFIndex(rk.getXFIndex());
- num.setValue(rk.getRKNumber());
- return num;
- }
-
- /**
- * Converts a {@link MulRKRecord} into an equivalent array of {@link NumberRecord}s
- */
- public static NumberRecord[] convertRKRecords(MulRKRecord mrk) {
- NumberRecord[] mulRecs = new NumberRecord[mrk.getNumColumns()];
- for (int k = 0; k < mrk.getNumColumns(); k++) {
- NumberRecord nr = new NumberRecord();
-
- nr.setColumn((short) (k + mrk.getFirstColumn()));
- nr.setRow(mrk.getRow());
- nr.setXFIndex(mrk.getXFAt(k));
- nr.setValue(mrk.getRKNumberAt(k));
- mulRecs[k] = nr;
- }
- return mulRecs;
- }
-
- /**
- * Converts a {@link MulBlankRecord} into an equivalent array of {@link BlankRecord}s
- */
- public static BlankRecord[] convertBlankRecords(MulBlankRecord mbk) {
- BlankRecord[] mulRecs = new BlankRecord[mbk.getNumColumns()];
- for (int k = 0; k < mbk.getNumColumns(); k++) {
- BlankRecord br = new BlankRecord();
-
- br.setColumn((short) (k + mbk.getFirstColumn()));
- br.setRow(mbk.getRow());
- br.setXFIndex(mbk.getXFAt(k));
- mulRecs[k] = br;
- }
- return mulRecs;
- }
-
- /**
- * @return an array of all the SIDS for all known records
- */
- public static short[] getAllKnownRecordSIDs() {
- if (_allKnownRecordSIDs == null) {
- short[] results = new short[ _recordCreatorsById.size() ];
- int i = 0;
-
- for (Iterator<Integer> iterator = _recordCreatorsById.keySet().iterator(); iterator.hasNext(); ) {
- Integer sid = iterator.next();
-
- results[i++] = sid.shortValue();
- }
- Arrays.sort(results);
- _allKnownRecordSIDs = results;
- }
-
- return _allKnownRecordSIDs.clone();
- }
-
- /**
- * gets the record constructors and sticks them in the map by SID
- * @return map of SIDs to short,short,byte[] constructors for Record classes
- * most of org.apache.poi.hssf.record.*
- */
- private static Map<Integer, I_RecordCreator> recordsToMap(Class<? extends Record> [] records) {
- Map<Integer, I_RecordCreator> result = new HashMap<Integer, I_RecordCreator>();
- Set<Class<?>> uniqueRecClasses = new HashSet<Class<?>>(records.length * 3 / 2);
-
- for (int i = 0; i < records.length; i++) {
-
- Class<? extends Record> recClass = records[ i ];
- if(!Record.class.isAssignableFrom(recClass)) {
- throw new RuntimeException("Invalid record sub-class (" + recClass.getName() + ")");
- }
- if(Modifier.isAbstract(recClass.getModifiers())) {
- throw new RuntimeException("Invalid record class (" + recClass.getName() + ") - must not be abstract");
- }
- if(!uniqueRecClasses.add(recClass)) {
- throw new RuntimeException("duplicate record class (" + recClass.getName() + ")");
- }
-
- int sid;
- try {
- sid = recClass.getField("sid").getShort(null);
- } catch (Exception illegalArgumentException) {
- throw new RecordFormatException(
- "Unable to determine record types");
- }
- Integer key = Integer.valueOf(sid);
- if (result.containsKey(key)) {
- Class<?> prevClass = result.get(key).getRecordClass();
- throw new RuntimeException("duplicate record sid 0x" + Integer.toHexString(sid).toUpperCase()
- + " for classes (" + recClass.getName() + ") and (" + prevClass.getName() + ")");
- }
- result.put(key, getRecordCreator(recClass));
- }
-// result.put(Integer.valueOf(0x0406), result.get(Integer.valueOf(0x06)));
- return result;
- }
-
- private static I_RecordCreator getRecordCreator(Class<? extends Record> recClass) {
- try {
- Constructor<? extends Record> constructor;
- constructor = recClass.getConstructor(CONSTRUCTOR_ARGS);
- return new ReflectionConstructorRecordCreator(constructor);
- } catch (NoSuchMethodException e) {
- // fall through and look for other construction methods
- }
- try {
- Method m = recClass.getDeclaredMethod("create", CONSTRUCTOR_ARGS);
- return new ReflectionMethodRecordCreator(m);
- } catch (NoSuchMethodException e) {
- throw new RuntimeException("Failed to find constructor or create method for (" + recClass.getName() + ").");
- }
- }
- /**
- * Create an array of records from an input stream
- *
- * @param in the InputStream from which the records will be obtained
- *
- * @return an array of Records created from the InputStream
- *
- * @exception RecordFormatException on error processing the InputStream
- */
- public static List<Record> createRecords(InputStream in) throws RecordFormatException {
-
- List<Record> records = new ArrayList<Record>(NUM_RECORDS);
-
- RecordFactoryInputStream recStream = new RecordFactoryInputStream(in, true);
-
- Record record;
- while ((record = recStream.nextRecord())!=null) {
- records.add(record);
- }
+ HideObjRecord.class,
+ HorizontalPageBreakRecord.class,
+ HyperlinkRecord.class,
+ IndexRecord.class,
+ InterfaceEndRecord.class,
+ InterfaceHdrRecord.class,
+ IterationRecord.class,
+ LabelRecord.class,
+ LabelSSTRecord.class,
+ LeftMarginRecord.class,
+ LegendRecord.class,
+ MergeCellsRecord.class,
+ MMSRecord.class,
+ MulBlankRecord.class,
+ MulRKRecord.class,
+ NameRecord.class,
+ NameCommentRecord.class,
+ NoteRecord.class,
+ NumberRecord.class,
+ ObjectProtectRecord.class,
+ ObjRecord.class,
+ PaletteRecord.class,
+ PaneRecord.class,
+ PasswordRecord.class,
+ PasswordRev4Record.class,
+ PrecisionRecord.class,
+ PrintGridlinesRecord.class,
+ PrintHeadersRecord.class,
+ PrintSetupRecord.class,
+ ProtectionRev4Record.class,
+ ProtectRecord.class,
+ RecalcIdRecord.class,
+ RefModeRecord.class,
+ RefreshAllRecord.class,
+ RightMarginRecord.class,
+ RKRecord.class,
+ RowRecord.class,
+ SaveRecalcRecord.class,
+ ScenarioProtectRecord.class,
+ SelectionRecord.class,
+ SeriesRecord.class,
+ SeriesTextRecord.class,
+ SharedFormulaRecord.class,
+ SSTRecord.class,
+ StringRecord.class,
+ StyleRecord.class,
+ SupBookRecord.class,
+ TabIdRecord.class,
+ TableRecord.class,
+ TableStylesRecord.class,
+ TextObjectRecord.class,
+ TopMarginRecord.class,
+ UncalcedRecord.class,
+ UseSelFSRecord.class,
+ UserSViewBegin.class,
+ UserSViewEnd.class,
+ ValueRangeRecord.class,
+ VCenterRecord.class,
+ VerticalPageBreakRecord.class,
+ WindowOneRecord.class,
+ WindowProtectRecord.class,
+ WindowTwoRecord.class,
+ WriteAccessRecord.class,
+ WriteProtectRecord.class,
+ WSBoolRecord.class,
+
+ // chart records
+ BeginRecord.class,
+ ChartFRTInfoRecord.class,
+ ChartStartBlockRecord.class,
+ ChartEndBlockRecord.class,
+ // TODO ChartFormatRecord.class,
+ ChartStartObjectRecord.class,
+ ChartEndObjectRecord.class,
+ CatLabRecord.class,
+ DataFormatRecord.class,
+ EndRecord.class,
+ LinkedDataRecord.class,
+ SeriesToChartGroupRecord.class,
+
+ // pivot table records
+ DataItemRecord.class,
+ ExtendedPivotTableViewFieldsRecord.class,
+ PageItemRecord.class,
+ StreamIDRecord.class,
+ ViewDefinitionRecord.class,
+ ViewFieldsRecord.class,
+ ViewSourceRecord.class,
+ };
+
+ /**
+ * cache of the recordsToMap();
+ */
+ private static final Map<Integer, I_RecordCreator> _recordCreatorsById = recordsToMap(recordClasses);
+
+ private static short[] _allKnownRecordSIDs;
+
+ /**
+ * Debug / diagnosis method<br/>
+ * Gets the POI implementation class for a given <tt>sid</tt>. Only a subset of the any BIFF
+ * records are actually interpreted by POI. A few others are known but not interpreted
+ * (see {@link UnknownRecord#getBiffName(int)}).
+ * @return the POI implementation class for the specified record <tt>sid</tt>.
+ * <code>null</code> if the specified record is not interpreted by POI.
+ */
+ public static Class<? extends Record> getRecordClass(int sid) {
+ I_RecordCreator rc = _recordCreatorsById.get(Integer.valueOf(sid));
+ if (rc == null) {
+ return null;
+ }
+ return rc.getRecordClass();
+ }
+ /**
+ * create a record, if there are MUL records than multiple records
+ * are returned digested into the non-mul form.
+ */
+ public static Record [] createRecord(RecordInputStream in) {
+ Record record = createSingleRecord(in);
+ if (record instanceof DBCellRecord) {
+ // Not needed by POI. Regenerated from scratch by POI when spreadsheet is written
+ return new Record[] { null, };
+ }
+ if (record instanceof RKRecord) {
+ return new Record[] { convertToNumberRecord((RKRecord) record), };
+ }
+ if (record instanceof MulRKRecord) {
+ return convertRKRecords((MulRKRecord)record);
+ }
+ return new Record[] { record, };
+ }
+
+ public static Record createSingleRecord(RecordInputStream in) {
+ I_RecordCreator constructor = _recordCreatorsById.get(Integer.valueOf(in.getSid()));
+
+ if (constructor == null) {
+ return new UnknownRecord(in);
+ }
+
+ return constructor.create(in);
+ }
+
+ /**
+ * RK record is a slightly smaller alternative to NumberRecord
+ * POI likes NumberRecord better
+ */
+ public static NumberRecord convertToNumberRecord(RKRecord rk) {
+ NumberRecord num = new NumberRecord();
+
+ num.setColumn(rk.getColumn());
+ num.setRow(rk.getRow());
+ num.setXFIndex(rk.getXFIndex());
+ num.setValue(rk.getRKNumber());
+ return num;
+ }
+
+ /**
+ * Converts a {@link MulRKRecord} into an equivalent array of {@link NumberRecord}s
+ */
+ public static NumberRecord[] convertRKRecords(MulRKRecord mrk) {
+ NumberRecord[] mulRecs = new NumberRecord[mrk.getNumColumns()];
+ for (int k = 0; k < mrk.getNumColumns(); k++) {
+ NumberRecord nr = new NumberRecord();
+
+ nr.setColumn((short) (k + mrk.getFirstColumn()));
+ nr.setRow(mrk.getRow());
+ nr.setXFIndex(mrk.getXFAt(k));
+ nr.setValue(mrk.getRKNumberAt(k));
+ mulRecs[k] = nr;
+ }
+ return mulRecs;
+ }
+
+ /**
+ * Converts a {@link MulBlankRecord} into an equivalent array of {@link BlankRecord}s
+ */
+ public static BlankRecord[] convertBlankRecords(MulBlankRecord mbk) {
+ BlankRecord[] mulRecs = new BlankRecord[mbk.getNumColumns()];
+ for (int k = 0; k < mbk.getNumColumns(); k++) {
+ BlankRecord br = new BlankRecord();
+
+ br.setColumn((short) (k + mbk.getFirstColumn()));
+ br.setRow(mbk.getRow());
+ br.setXFIndex(mbk.getXFAt(k));
+ mulRecs[k] = br;
+ }
+ return mulRecs;
+ }
+
+ /**
+ * @return an array of all the SIDS for all known records
+ */
+ public static short[] getAllKnownRecordSIDs() {
+ if (_allKnownRecordSIDs == null) {
+ short[] results = new short[ _recordCreatorsById.size() ];
+ int i = 0;
+
+ for (Iterator<Integer> iterator = _recordCreatorsById.keySet().iterator(); iterator.hasNext(); ) {
+ Integer sid = iterator.next();
+
+ results[i++] = sid.shortValue();
+ }
+ Arrays.sort(results);
+ _allKnownRecordSIDs = results;
+ }
+
+ return _allKnownRecordSIDs.clone();
+ }
+
+ /**
+ * gets the record constructors and sticks them in the map by SID
+ * @return map of SIDs to short,short,byte[] constructors for Record classes
+ * most of org.apache.poi.hssf.record.*
+ */
+ private static Map<Integer, I_RecordCreator> recordsToMap(Class<? extends Record> [] records) {
+ Map<Integer, I_RecordCreator> result = new HashMap<Integer, I_RecordCreator>();
+ Set<Class<?>> uniqueRecClasses = new HashSet<Class<?>>(records.length * 3 / 2);
+
+ for (int i = 0; i < records.length; i++) {
+
+ Class<? extends Record> recClass = records[ i ];
+ if(!Record.class.isAssignableFrom(recClass)) {
+ throw new RuntimeException("Invalid record sub-class (" + recClass.getName() + ")");
+ }
+ if(Modifier.isAbstract(recClass.getModifiers())) {
+ throw new RuntimeException("Invalid record class (" + recClass.getName() + ") - must not be abstract");
+ }
+ if(!uniqueRecClasses.add(recClass)) {
+ throw new RuntimeException("duplicate record class (" + recClass.getName() + ")");
+ }
+
+ int sid;
+ try {
+ sid = recClass.getField("sid").getShort(null);
+ } catch (Exception illegalArgumentException) {
+ throw new RecordFormatException(
+ "Unable to determine record types");
+ }
+ Integer key = Integer.valueOf(sid);
+ if (result.containsKey(key)) {
+ Class<?> prevClass = result.get(key).getRecordClass();
+ throw new RuntimeException("duplicate record sid 0x" + Integer.toHexString(sid).toUpperCase()
+ + " for classes (" + recClass.getName() + ") and (" + prevClass.getName() + ")");
+ }
+ result.put(key, getRecordCreator(recClass));
+ }
+ // result.put(Integer.valueOf(0x0406), result.get(Integer.valueOf(0x06)));
+ return result;
+ }
+
+ private static I_RecordCreator getRecordCreator(Class<? extends Record> recClass) {
+ try {
+ Constructor<? extends Record> constructor;
+ constructor = recClass.getConstructor(CONSTRUCTOR_ARGS);
+ return new ReflectionConstructorRecordCreator(constructor);
+ } catch (NoSuchMethodException e) {
+ // fall through and look for other construction methods
+ }
+ try {
+ Method m = recClass.getDeclaredMethod("create", CONSTRUCTOR_ARGS);
+ return new ReflectionMethodRecordCreator(m);
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException("Failed to find constructor or create method for (" + recClass.getName() + ").");
+ }
+ }
+ /**
+ * Create an array of records from an input stream
+ *
+ * @param in the InputStream from which the records will be obtained
+ *
+ * @return an array of Records created from the InputStream
+ *
+ * @exception RecordFormatException on error processing the InputStream
+ */
+ public static List<Record> createRecords(InputStream in) throws RecordFormatException {
+
+ List<Record> records = new ArrayList<Record>(NUM_RECORDS);
+
+ RecordFactoryInputStream recStream = new RecordFactoryInputStream(in, true);
+
+ Record record;
+ while ((record = recStream.nextRecord())!=null) {
+ records.add(record);
+ }
- return records;
- }
+ return records;
+ }
}
Modified: poi/branches/common_sl/src/java/org/apache/poi/hssf/record/RecordInputStream.java
URL: http://svn.apache.org/viewvc/poi/branches/common_sl/src/java/org/apache/poi/hssf/record/RecordInputStream.java?rev=1691843&r1=1691842&r2=1691843&view=diff
==============================================================================
--- poi/branches/common_sl/src/java/org/apache/poi/hssf/record/RecordInputStream.java (original)
+++ poi/branches/common_sl/src/java/org/apache/poi/hssf/record/RecordInputStream.java Sun Jul 19 19:00:32 2015
@@ -52,8 +52,17 @@ public final class RecordInputStream imp
public static final class LeftoverDataException extends RuntimeException {
public LeftoverDataException(int sid, int remainingByteCount) {
super("Initialisation of record 0x" + Integer.toHexString(sid).toUpperCase()
- + " left " + remainingByteCount + " bytes remaining still to be read.");
+ + "(" + getRecordName(sid) + ") left " + remainingByteCount
+ + " bytes remaining still to be read.");
}
+
+ private static String getRecordName(int sid) {
+ Class<? extends Record> recordClass = RecordFactory.getRecordClass(sid);
+ if(recordClass == null) {
+ return null;
+ }
+ return recordClass.getSimpleName();
+ }
}
/** Header {@link LittleEndianInput} facet of the wrapped {@link InputStream} */
Modified: poi/branches/common_sl/src/java/org/apache/poi/hssf/record/RowRecord.java
URL: http://svn.apache.org/viewvc/poi/branches/common_sl/src/java/org/apache/poi/hssf/record/RowRecord.java?rev=1691843&r1=1691842&r2=1691843&view=diff
==============================================================================
--- poi/branches/common_sl/src/java/org/apache/poi/hssf/record/RowRecord.java (original)
+++ poi/branches/common_sl/src/java/org/apache/poi/hssf/record/RowRecord.java Sun Jul 19 19:00:32 2015
@@ -64,6 +64,9 @@ public final class RowRecord extends Sta
// bit 15 is unused
public RowRecord(int rowNumber) {
+ if(rowNumber < 0) {
+ throw new IllegalArgumentException("Invalid row number (" + rowNumber + ")");
+ }
field_1_row_number = rowNumber;
field_4_height = (short)0xFF;
field_5_optimize = ( short ) 0;
@@ -76,6 +79,9 @@ public final class RowRecord extends Sta
public RowRecord(RecordInputStream in) {
field_1_row_number = in.readUShort();
+ if(field_1_row_number < 0) {
+ throw new IllegalArgumentException("Invalid row number " + field_1_row_number + " found in InputStream");
+ }
field_2_first_col = in.readShort();
field_3_last_col = in.readShort();
field_4_height = in.readShort();
Modified: poi/branches/common_sl/src/java/org/apache/poi/hssf/record/UnknownRecord.java
URL: http://svn.apache.org/viewvc/poi/branches/common_sl/src/java/org/apache/poi/hssf/record/UnknownRecord.java?rev=1691843&r1=1691842&r2=1691843&view=diff
==============================================================================
--- poi/branches/common_sl/src/java/org/apache/poi/hssf/record/UnknownRecord.java (original)
+++ poi/branches/common_sl/src/java/org/apache/poi/hssf/record/UnknownRecord.java Sun Jul 19 19:00:32 2015
@@ -179,8 +179,10 @@ public final class UnknownRecord extends
case SHEETPROTECTION_0867: return "SHEETPROTECTION";
case 0x086B: return "DATALABEXTCONTENTS";
case 0x086C: return "CELLWATCH";
+ case FeatRecord.v11_sid: return "SHARED FEATURE v11";
case 0x0874: return "DROPDOWNOBJIDS";
case 0x0876: return "DCONN";
+ case FeatRecord.v12_sid: return "SHARED FEATURE v12";
case 0x087B: return "CFEX";
case 0x087C: return "XFCRC";
case 0x087D: return "XFEXT";
@@ -194,15 +196,21 @@ public final class UnknownRecord extends
case 0x089A: return "MTRSETTINGS";
case 0x089B: return "COMPRESSPICTURES";
case HEADER_FOOTER_089C: return "HEADERFOOTER";
+ case 0x089D: return "CRTLAYOUT12";
+ case 0x089E: return "CRTMLFRT";
+ case 0x089F: return "CRTMLFRTCONTINUE";
case 0x08A1: return "SHAPEPROPSSTREAM";
case 0x08A3: return "FORCEFULLCALCULATION";
case 0x08A4: return "SHAPEPROPSSTREAM";
case 0x08A5: return "TEXTPROPSSTREAM";
case 0x08A6: return "RICHTEXTSTREAM";
+ case 0x08A7: return "CRTLAYOUT12A";
case 0x08C8: return "PLV{Mac Excel}";
-
-
+
+ case 0x1001: return "UNITS";
+ case 0x1006: return "CHARTDATAFORMAT";
+ case 0x1007: return "CHARTLINEFORMAT";
}
if (isObservedButUnknown(sid)) {
return "UNKNOWN-" + Integer.toHexString(sid).toUpperCase();
@@ -215,6 +223,7 @@ public final class UnknownRecord extends
* @return <code>true</code> if the unknown record id has been observed in POI unit tests
*/
private static boolean isObservedButUnknown(int sid) {
+ // TODO Look up more of these in the latest [MS-XLS] doc and move to getBiffName
switch (sid) {
case 0x0033:
// contains 2 bytes of data: 0x0001 or 0x0003
@@ -227,13 +236,7 @@ public final class UnknownRecord extends
// Written by Excel 2007
// rawData is multiple of 12 bytes long
// appears after last cell value record and before WINDOW2 or drawing records
- case 0x089D:
- case 0x089E:
- case 0x08A7:
- case 0x1001:
- case 0x1006:
- case 0x1007:
case 0x1009:
case 0x100A:
case 0x100B:
Modified: poi/branches/common_sl/src/java/org/apache/poi/hssf/record/aggregates/CFRecordsAggregate.java
URL: http://svn.apache.org/viewvc/poi/branches/common_sl/src/java/org/apache/poi/hssf/record/aggregates/CFRecordsAggregate.java?rev=1691843&r1=1691842&r2=1691843&view=diff
==============================================================================
--- poi/branches/common_sl/src/java/org/apache/poi/hssf/record/aggregates/CFRecordsAggregate.java (original)
+++ poi/branches/common_sl/src/java/org/apache/poi/hssf/record/aggregates/CFRecordsAggregate.java Sun Jul 19 19:00:32 2015
@@ -21,7 +21,11 @@ import java.util.ArrayList;
import java.util.List;
import org.apache.poi.hssf.model.RecordStream;
+import org.apache.poi.hssf.record.CFHeader12Record;
+import org.apache.poi.hssf.record.CFHeaderBase;
import org.apache.poi.hssf.record.CFHeaderRecord;
+import org.apache.poi.hssf.record.CFRule12Record;
+import org.apache.poi.hssf.record.CFRuleBase;
import org.apache.poi.hssf.record.CFRuleRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.ss.formula.FormulaShifter;
@@ -38,212 +42,240 @@ import org.apache.poi.util.POILogger;
* <p>Note that Excel versions before 2007 can only cope with a maximum of 3
* Conditional Formatting rules per sheet. Excel 2007 or newer can cope with
* unlimited numbers, as can Apache OpenOffice. This is an Excel limitation,
- * not a file format one.</p>
+ * not a file format one.</p>
*/
public final class CFRecordsAggregate extends RecordAggregate {
- /** Excel 97-2003 allows up to 3 conditional formating rules */
- private static final int MAX_97_2003_CONDTIONAL_FORMAT_RULES = 3;
- private static final POILogger logger = POILogFactory.getLogger(CFRecordsAggregate.class);
-
- private final CFHeaderRecord header;
-
- /** List of CFRuleRecord objects */
- private final List<CFRuleRecord> rules;
-
- private CFRecordsAggregate(CFHeaderRecord pHeader, CFRuleRecord[] pRules) {
- if(pHeader == null) {
- throw new IllegalArgumentException("header must not be null");
- }
- if(pRules == null) {
- throw new IllegalArgumentException("rules must not be null");
- }
- if(pRules.length > MAX_97_2003_CONDTIONAL_FORMAT_RULES) {
- logger.log(POILogger.WARN, "Excel versions before 2007 require that "
- + "No more than " + MAX_97_2003_CONDTIONAL_FORMAT_RULES
- + " rules may be specified, " + pRules.length + " were found,"
- + " this file will cause problems with old Excel versions");
- }
- if (pRules.length != pHeader.getNumberOfConditionalFormats()) {
- throw new RuntimeException("Mismatch number of rules");
- }
- header = pHeader;
- rules = new ArrayList<CFRuleRecord>(3);
- for (int i = 0; i < pRules.length; i++) {
- rules.add(pRules[i]);
- }
- }
-
- public CFRecordsAggregate(CellRangeAddress[] regions, CFRuleRecord[] rules) {
- this(new CFHeaderRecord(regions, rules.length), rules);
- }
-
- /**
- * Create CFRecordsAggregate from a list of CF Records
- * @param rs - the stream to read from
- * @return CFRecordsAggregate object
- */
- public static CFRecordsAggregate createCFAggregate(RecordStream rs) {
- Record rec = rs.getNext();
- if (rec.getSid() != CFHeaderRecord.sid) {
- throw new IllegalStateException("next record sid was " + rec.getSid()
- + " instead of " + CFHeaderRecord.sid + " as expected");
- }
-
- CFHeaderRecord header = (CFHeaderRecord)rec;
- int nRules = header.getNumberOfConditionalFormats();
-
- CFRuleRecord[] rules = new CFRuleRecord[nRules];
- for (int i = 0; i < rules.length; i++) {
- rules[i] = (CFRuleRecord) rs.getNext();
- }
-
- return new CFRecordsAggregate(header, rules);
- }
-
- /**
- * Create a deep clone of the record
- */
- public CFRecordsAggregate cloneCFAggregate()
- {
-
- CFRuleRecord[] newRecs = new CFRuleRecord[rules.size()];
- for (int i = 0; i < newRecs.length; i++) {
- newRecs[i] = (CFRuleRecord) getRule(i).clone();
- }
- return new CFRecordsAggregate((CFHeaderRecord) header.clone(), newRecs);
- }
-
- /**
- * @return the header. Never <code>null</code>.
- */
- public CFHeaderRecord getHeader()
- {
- return header;
- }
-
- private void checkRuleIndex(int idx) {
- if(idx < 0 || idx >= rules.size()) {
- throw new IllegalArgumentException("Bad rule record index (" + idx
- + ") nRules=" + rules.size());
- }
- }
- public CFRuleRecord getRule(int idx) {
- checkRuleIndex(idx);
- return rules.get(idx);
- }
- public void setRule(int idx, CFRuleRecord r) {
- if (r == null) {
- throw new IllegalArgumentException("r must not be null");
- }
- checkRuleIndex(idx);
- rules.set(idx, r);
- }
- public void addRule(CFRuleRecord r) {
- if (r == null) {
- throw new IllegalArgumentException("r must not be null");
- }
- if(rules.size() >= MAX_97_2003_CONDTIONAL_FORMAT_RULES) {
+ /** Excel 97-2003 allows up to 3 conditional formating rules */
+ private static final int MAX_97_2003_CONDTIONAL_FORMAT_RULES = 3;
+ private static final POILogger logger = POILogFactory.getLogger(CFRecordsAggregate.class);
+
+ private final CFHeaderBase header;
+
+ /** List of CFRuleRecord objects */
+ private final List<CFRuleBase> rules;
+
+ private CFRecordsAggregate(CFHeaderBase pHeader, CFRuleBase[] pRules) {
+ if(pHeader == null) {
+ throw new IllegalArgumentException("header must not be null");
+ }
+ if(pRules == null) {
+ throw new IllegalArgumentException("rules must not be null");
+ }
+ if(pRules.length > MAX_97_2003_CONDTIONAL_FORMAT_RULES) {
+ logger.log(POILogger.WARN, "Excel versions before 2007 require that "
+ + "No more than " + MAX_97_2003_CONDTIONAL_FORMAT_RULES
+ + " rules may be specified, " + pRules.length + " were found,"
+ + " this file will cause problems with old Excel versions");
+ }
+ if (pRules.length != pHeader.getNumberOfConditionalFormats()) {
+ throw new RuntimeException("Mismatch number of rules");
+ }
+ header = pHeader;
+ rules = new ArrayList<CFRuleBase>(pRules.length);
+ for (int i = 0; i < pRules.length; i++) {
+ checkRuleType(pRules[i]);
+ rules.add(pRules[i]);
+ }
+ }
+
+ public CFRecordsAggregate(CellRangeAddress[] regions, CFRuleBase[] rules) {
+ this(createHeader(regions, rules), rules);
+ }
+ private static CFHeaderBase createHeader(CellRangeAddress[] regions, CFRuleBase[] rules) {
+ if (rules.length == 0 || rules[0] instanceof CFRuleRecord) {
+ return new CFHeaderRecord(regions, rules.length);
+ }
+ return new CFHeader12Record(regions, rules.length);
+ }
+
+ /**
+ * Create CFRecordsAggregate from a list of CF Records
+ * @param rs - the stream to read from
+ * @return CFRecordsAggregate object
+ */
+ public static CFRecordsAggregate createCFAggregate(RecordStream rs) {
+ Record rec = rs.getNext();
+ if (rec.getSid() != CFHeaderRecord.sid &&
+ rec.getSid() != CFHeader12Record.sid) {
+ throw new IllegalStateException("next record sid was " + rec.getSid()
+ + " instead of " + CFHeaderRecord.sid + " or " +
+ CFHeader12Record.sid + " as expected");
+ }
+
+ CFHeaderBase header = (CFHeaderBase)rec;
+ int nRules = header.getNumberOfConditionalFormats();
+
+ CFRuleBase[] rules = new CFRuleBase[nRules];
+ for (int i = 0; i < rules.length; i++) {
+ rules[i] = (CFRuleBase) rs.getNext();
+ }
+
+ return new CFRecordsAggregate(header, rules);
+ }
+
+ /**
+ * Create a deep clone of the record
+ */
+ public CFRecordsAggregate cloneCFAggregate() {
+ CFRuleBase[] newRecs = new CFRuleBase[rules.size()];
+ for (int i = 0; i < newRecs.length; i++) {
+ newRecs[i] = (CFRuleRecord) getRule(i).clone();
+ }
+ return new CFRecordsAggregate((CFHeaderBase)header.clone(), newRecs);
+ }
+
+ /**
+ * @return the header. Never <code>null</code>.
+ */
+ public CFHeaderBase getHeader() {
+ return header;
+ }
+
+ private void checkRuleIndex(int idx) {
+ if(idx < 0 || idx >= rules.size()) {
+ throw new IllegalArgumentException("Bad rule record index (" + idx
+ + ") nRules=" + rules.size());
+ }
+ }
+ private void checkRuleType(CFRuleBase r) {
+ if (header instanceof CFHeaderRecord &&
+ r instanceof CFRuleRecord) {
+ return;
+ }
+ if (header instanceof CFHeader12Record &&
+ r instanceof CFRule12Record) {
+ return;
+ }
+ throw new IllegalArgumentException("Header and Rule must both be CF or both be CF12, can't mix");
+ }
+
+ public CFRuleBase getRule(int idx) {
+ checkRuleIndex(idx);
+ return rules.get(idx);
+ }
+ public void setRule(int idx, CFRuleBase r) {
+ if (r == null) {
+ throw new IllegalArgumentException("r must not be null");
+ }
+ checkRuleIndex(idx);
+ checkRuleType(r);
+ rules.set(idx, r);
+ }
+ public void addRule(CFRuleBase r) {
+ if (r == null) {
+ throw new IllegalArgumentException("r must not be null");
+ }
+ if(rules.size() >= MAX_97_2003_CONDTIONAL_FORMAT_RULES) {
logger.log(POILogger.WARN, "Excel versions before 2007 cannot cope with"
- + " any more than " + MAX_97_2003_CONDTIONAL_FORMAT_RULES
+ + " any more than " + MAX_97_2003_CONDTIONAL_FORMAT_RULES
+ " - this file will cause problems with old Excel versions");
- }
- rules.add(r);
- header.setNumberOfConditionalFormats(rules.size());
- }
- public int getNumberOfRules() {
- return rules.size();
- }
-
- /**
- * String representation of CFRecordsAggregate
- */
- public String toString()
- {
- StringBuffer buffer = new StringBuffer();
-
- buffer.append("[CF]\n");
- if( header != null )
- {
- buffer.append(header.toString());
- }
- for(int i=0; i<rules.size(); i++)
- {
- CFRuleRecord cfRule = rules.get(i);
- buffer.append(cfRule.toString());
- }
- buffer.append("[/CF]\n");
- return buffer.toString();
- }
-
- public void visitContainedRecords(RecordVisitor rv) {
- rv.visitRecord(header);
- for(int i=0; i<rules.size(); i++) {
- CFRuleRecord rule = rules.get(i);
- rv.visitRecord(rule);
- }
- }
-
- /**
- * @return <code>false</code> if this whole {@link CFHeaderRecord} / {@link CFRuleRecord}s should be deleted
- */
- public boolean updateFormulasAfterCellShift(FormulaShifter shifter, int currentExternSheetIx) {
- CellRangeAddress[] cellRanges = header.getCellRanges();
- boolean changed = false;
- List<CellRangeAddress> temp = new ArrayList<CellRangeAddress>();
- for (int i = 0; i < cellRanges.length; i++) {
- CellRangeAddress craOld = cellRanges[i];
- CellRangeAddress craNew = shiftRange(shifter, craOld, currentExternSheetIx);
- if (craNew == null) {
- changed = true;
- continue;
- }
- temp.add(craNew);
- if (craNew != craOld) {
- changed = true;
- }
- }
-
- if (changed) {
- int nRanges = temp.size();
- if (nRanges == 0) {
- return false;
- }
- CellRangeAddress[] newRanges = new CellRangeAddress[nRanges];
- temp.toArray(newRanges);
- header.setCellRanges(newRanges);
- }
-
- for(int i=0; i<rules.size(); i++) {
- CFRuleRecord rule = rules.get(i);
- Ptg[] ptgs;
- ptgs = rule.getParsedExpression1();
- if (ptgs != null && shifter.adjustFormula(ptgs, currentExternSheetIx)) {
- rule.setParsedExpression1(ptgs);
- }
- ptgs = rule.getParsedExpression2();
- if (ptgs != null && shifter.adjustFormula(ptgs, currentExternSheetIx)) {
- rule.setParsedExpression2(ptgs);
- }
- }
- return true;
- }
-
- private static CellRangeAddress shiftRange(FormulaShifter shifter, CellRangeAddress cra, int currentExternSheetIx) {
- // FormulaShifter works well in terms of Ptgs - so convert CellRangeAddress to AreaPtg (and back) here
- AreaPtg aptg = new AreaPtg(cra.getFirstRow(), cra.getLastRow(), cra.getFirstColumn(), cra.getLastColumn(), false, false, false, false);
- Ptg[] ptgs = { aptg, };
-
- if (!shifter.adjustFormula(ptgs, currentExternSheetIx)) {
- return cra;
- }
- Ptg ptg0 = ptgs[0];
- if (ptg0 instanceof AreaPtg) {
- AreaPtg bptg = (AreaPtg) ptg0;
- return new CellRangeAddress(bptg.getFirstRow(), bptg.getLastRow(), bptg.getFirstColumn(), bptg.getLastColumn());
- }
- if (ptg0 instanceof AreaErrPtg) {
- return null;
- }
- throw new IllegalStateException("Unexpected shifted ptg class (" + ptg0.getClass().getName() + ")");
- }
+ }
+ checkRuleType(r);
+ rules.add(r);
+ header.setNumberOfConditionalFormats(rules.size());
+ }
+ public int getNumberOfRules() {
+ return rules.size();
+ }
+
+ /**
+ * String representation of CFRecordsAggregate
+ */
+ public String toString() {
+ StringBuffer buffer = new StringBuffer();
+ String type = "CF";
+ if (header instanceof CFHeader12Record) {
+ type = "CF12";
+ }
+
+ buffer.append("[").append(type).append("]\n");
+ if( header != null ) {
+ buffer.append(header.toString());
+ }
+ for(int i=0; i<rules.size(); i++) {
+ CFRuleBase cfRule = rules.get(i);
+ buffer.append(cfRule.toString());
+ }
+ buffer.append("[/").append(type).append("]\n");
+ return buffer.toString();
+ }
+
+ public void visitContainedRecords(RecordVisitor rv) {
+ rv.visitRecord(header);
+ for(int i=0; i<rules.size(); i++) {
+ CFRuleBase rule = rules.get(i);
+ rv.visitRecord(rule);
+ }
+ }
+
+ /**
+ * @return <code>false</code> if this whole {@link CFHeaderRecord} / {@link CFRuleRecord}s should be deleted
+ */
+ public boolean updateFormulasAfterCellShift(FormulaShifter shifter, int currentExternSheetIx) {
+ CellRangeAddress[] cellRanges = header.getCellRanges();
+ boolean changed = false;
+ List<CellRangeAddress> temp = new ArrayList<CellRangeAddress>();
+ for (int i = 0; i < cellRanges.length; i++) {
+ CellRangeAddress craOld = cellRanges[i];
+ CellRangeAddress craNew = shiftRange(shifter, craOld, currentExternSheetIx);
+ if (craNew == null) {
+ changed = true;
+ continue;
+ }
+ temp.add(craNew);
+ if (craNew != craOld) {
+ changed = true;
+ }
+ }
+
+ if (changed) {
+ int nRanges = temp.size();
+ if (nRanges == 0) {
+ return false;
+ }
+ CellRangeAddress[] newRanges = new CellRangeAddress[nRanges];
+ temp.toArray(newRanges);
+ header.setCellRanges(newRanges);
+ }
+
+ for(int i=0; i<rules.size(); i++) {
+ CFRuleBase rule = rules.get(i);
+ Ptg[] ptgs;
+ ptgs = rule.getParsedExpression1();
+ if (ptgs != null && shifter.adjustFormula(ptgs, currentExternSheetIx)) {
+ rule.setParsedExpression1(ptgs);
+ }
+ ptgs = rule.getParsedExpression2();
+ if (ptgs != null && shifter.adjustFormula(ptgs, currentExternSheetIx)) {
+ rule.setParsedExpression2(ptgs);
+ }
+ if (rule instanceof CFRule12Record) {
+ CFRule12Record rule12 = (CFRule12Record)rule;
+ ptgs = rule12.getParsedExpressionScale();
+ if (ptgs != null && shifter.adjustFormula(ptgs, currentExternSheetIx)) {
+ rule12.setParsedExpressionScale(ptgs);
+ }
+ }
+ }
+ return true;
+ }
+
+ private static CellRangeAddress shiftRange(FormulaShifter shifter, CellRangeAddress cra, int currentExternSheetIx) {
+ // FormulaShifter works well in terms of Ptgs - so convert CellRangeAddress to AreaPtg (and back) here
+ AreaPtg aptg = new AreaPtg(cra.getFirstRow(), cra.getLastRow(), cra.getFirstColumn(), cra.getLastColumn(), false, false, false, false);
+ Ptg[] ptgs = { aptg, };
+
+ if (!shifter.adjustFormula(ptgs, currentExternSheetIx)) {
+ return cra;
+ }
+ Ptg ptg0 = ptgs[0];
+ if (ptg0 instanceof AreaPtg) {
+ AreaPtg bptg = (AreaPtg) ptg0;
+ return new CellRangeAddress(bptg.getFirstRow(), bptg.getLastRow(), bptg.getFirstColumn(), bptg.getLastColumn());
+ }
+ if (ptg0 instanceof AreaErrPtg) {
+ return null;
+ }
+ throw new IllegalStateException("Unexpected shifted ptg class (" + ptg0.getClass().getName() + ")");
+ }
}
Modified: poi/branches/common_sl/src/java/org/apache/poi/hssf/record/aggregates/ConditionalFormattingTable.java
URL: http://svn.apache.org/viewvc/poi/branches/common_sl/src/java/org/apache/poi/hssf/record/aggregates/ConditionalFormattingTable.java?rev=1691843&r1=1691842&r2=1691843&view=diff
==============================================================================
--- poi/branches/common_sl/src/java/org/apache/poi/hssf/record/aggregates/ConditionalFormattingTable.java (original)
+++ poi/branches/common_sl/src/java/org/apache/poi/hssf/record/aggregates/ConditionalFormattingTable.java Sun Jul 19 19:00:32 2015
@@ -21,6 +21,7 @@ import java.util.ArrayList;
import java.util.List;
import org.apache.poi.hssf.model.RecordStream;
+import org.apache.poi.hssf.record.CFHeader12Record;
import org.apache.poi.hssf.record.CFHeaderRecord;
import org.apache.poi.ss.formula.FormulaShifter;
@@ -28,11 +29,8 @@ import org.apache.poi.ss.formula.Formula
* Holds all the conditional formatting for a workbook sheet.<p/>
*
* See OOO exelfileformat.pdf sec 4.12 'Conditional Formatting Table'
- *
- * @author Josh Micich
*/
public final class ConditionalFormattingTable extends RecordAggregate {
-
private final List<CFRecordsAggregate> _cfHeaders;
/**
@@ -45,7 +43,8 @@ public final class ConditionalFormatting
public ConditionalFormattingTable(RecordStream rs) {
List<CFRecordsAggregate> temp = new ArrayList<CFRecordsAggregate>();
- while (rs.peekNextClass() == CFHeaderRecord.class) {
+ while (rs.peekNextClass() == CFHeaderRecord.class ||
+ rs.peekNextClass() == CFHeader12Record.class) {
temp.add(CFRecordsAggregate.createCFAggregate(rs));
}
_cfHeaders = temp;
@@ -62,6 +61,7 @@ public final class ConditionalFormatting
* @return index of the newly added CF header aggregate
*/
public int add(CFRecordsAggregate cfAggregate) {
+ cfAggregate.getHeader().setID(_cfHeaders.size());
_cfHeaders.add(cfAggregate);
return _cfHeaders.size() - 1;
}
Modified: poi/branches/common_sl/src/java/org/apache/poi/hssf/record/cf/BorderFormatting.java
URL: http://svn.apache.org/viewvc/poi/branches/common_sl/src/java/org/apache/poi/hssf/record/cf/BorderFormatting.java?rev=1691843&r1=1691842&r2=1691843&view=diff
==============================================================================
--- poi/branches/common_sl/src/java/org/apache/poi/hssf/record/cf/BorderFormatting.java (original)
+++ poi/branches/common_sl/src/java/org/apache/poi/hssf/record/cf/BorderFormatting.java Sun Jul 19 19:00:32 2015
@@ -25,11 +25,8 @@ import org.apache.poi.util.LittleEndianO
/**
* Border Formatting Block of the Conditional Formatting Rule Record.
- *
- * @author Dmitriy Kumshayev
*/
public final class BorderFormatting {
-
/** No border */
public final static short BORDER_NONE = 0x0;
/** Thin border */
@@ -89,6 +86,9 @@ public final class BorderFormatting {
field_14_border_styles2 = in.readInt();
}
+ public int getDataLength() {
+ return 8;
+ }
/**
* set the type of border to use for the left border of the cell
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org