/** * Creates a {@link Formula} object from a supplied {@link Ptg} array. Handles <code>null</code>s * OK. * * @param ptgs may be <code>null</code> * @return Never <code>null</code> (Possibly empty if the supplied <tt>ptgs</tt> is <code>null * </code>) */ public static Formula create(Ptg[] ptgs) { if (ptgs == null || ptgs.length < 1) { return EMPTY; } int totalSize = Ptg.getEncodedSize(ptgs); byte[] encodedData = new byte[totalSize]; Ptg.serializePtgs(ptgs, encodedData, 0); int encodedTokenLen = Ptg.getEncodedSizeWithoutArrayData(ptgs); return new Formula(encodedData, encodedTokenLen); }
public String toString() { StringBuffer sb = new StringBuffer(); sb.append("[ftPictFmla]\n"); sb.append(" .f2unknown = ").append(HexDump.intToHex(field_1_unknown_int)).append("\n"); if (field_2_refPtg == null) { sb.append(" .f3unknown = ") .append(HexDump.toHex(field_2_unknownFormulaData)) .append("\n"); } else { sb.append(" .formula = ").append(field_2_refPtg.toString()).append("\n"); } if (field_4_ole_classname != null) { sb.append(" .unicodeFlag = ").append(field_3_unicode_flag).append("\n"); sb.append(" .oleClassname = ").append(field_4_ole_classname).append("\n"); } if (field_4_unknownByte != null) { sb.append(" .f4unknown = ") .append(HexDump.byteToHex(field_4_unknownByte.intValue())) .append("\n"); } if (field_5_stream_id != null) { sb.append(" .streamId = ") .append(HexDump.intToHex(field_5_stream_id.intValue())) .append("\n"); } if (field_6_unknown.length > 0) { sb.append(" .f7unknown = ").append(HexDump.toHex(field_6_unknown)).append("\n"); } sb.append("[/ftPictFmla]"); return sb.toString(); }
@Override protected void appendValueText(StringBuilder sb) { sb.append(" .value = "); if (specialCachedValue == null) { sb.append(field_4_value).append("\n"); } else { sb.append(specialCachedValue.formatDebugString()).append("\n"); } sb.append(" .options = ").append(HexDump.shortToHex(getOptions())).append("\n"); sb.append(" .alwaysCalc= ").append(isAlwaysCalc()).append("\n"); sb.append(" .calcOnLoad= ").append(isCalcOnLoad()).append("\n"); sb.append(" .shared = ").append(isSharedFormula()).append("\n"); sb.append(" .zero = ").append(HexDump.intToHex(field_6_zero)).append("\n"); Ptg[] ptgs = field_8_parsed_expr.getTokens(); for (int k = 0; k < ptgs.length; k++) { if (k > 0) { sb.append("\n"); } sb.append(" Ptg[").append(k).append("]="); Ptg ptg = ptgs[k]; sb.append(ptg.toString()).append(ptg.getRVAType()); } }
private Formula(byte[] byteEncoding, int encodedTokenLen) { _byteEncoding = byteEncoding; _encodedTokenLen = encodedTokenLen; if (false) { // set to true to eagerly check Ptg decoding LittleEndianByteArrayInputStream in = new LittleEndianByteArrayInputStream(byteEncoding); Ptg.readTokens(encodedTokenLen, in); int nUnusedBytes = _byteEncoding.length - in.getReadIndex(); if (nUnusedBytes > 0) { // TODO - this seems to occur when IntersectionPtg is present // This example file "IntersectionPtg.xls" // used by test: TestIntersectionPtg.testReading() // has 10 bytes unused at the end of the formula // 10 extra bytes are just 0x01 and 0x00 System.out.println(nUnusedBytes + " unused bytes at end of formula"); } } }
public void serialize(LittleEndianOutput out) { int formulaSize = field_2_refPtg == null ? field_2_unknownFormulaData.length : field_2_refPtg.getSize(); int idOffset = getStreamIDOffset(formulaSize); int dataSize = getDataSize(idOffset); out.writeShort(sid); out.writeShort(dataSize); out.writeShort(idOffset); out.writeShort(formulaSize); out.writeInt(field_1_unknown_int); int pos = 12; if (field_2_refPtg == null) { out.write(field_2_unknownFormulaData); } else { field_2_refPtg.write(out); } pos += formulaSize; int stringLen; if (field_4_ole_classname == null) { // don't write 0x03, stringLen, flag, text stringLen = 0; } else { out.writeByte(0x03); pos += 1; stringLen = field_4_ole_classname.length(); out.writeShort(stringLen); pos += 2; if (stringLen > 0) { out.writeByte(field_3_unicode_flag ? 0x01 : 0x00); pos += 1; if (field_3_unicode_flag) { StringUtil.putUnicodeLE(field_4_ole_classname, out); pos += stringLen * 2; } else { StringUtil.putCompressedUnicode(field_4_ole_classname, out); pos += stringLen; } } } // pad to next 2-byte boundary (requires 0 or 1 bytes) switch (idOffset - (pos - 6)) { // 6 for 3 shorts: sid, dataSize, idOffset case 1: out.writeByte(field_4_unknownByte == null ? 0x00 : field_4_unknownByte.intValue()); pos++; case 0: break; default: throw new IllegalStateException("Bad padding calculation (" + idOffset + ", " + pos + ")"); } if (field_5_stream_id != null) { out.writeInt(field_5_stream_id.intValue()); pos += 4; } out.write(field_6_unknown); }
protected int getDataSize() { int formulaSize = field_2_refPtg == null ? field_2_unknownFormulaData.length : field_2_refPtg.getSize(); int idOffset = getStreamIDOffset(formulaSize); return getDataSize(idOffset); }
public Ptg[] getTokens() { LittleEndianInput in = new LittleEndianByteArrayInputStream(_byteEncoding); return Ptg.readTokens(_encodedTokenLen, in); }