public void TestSSTRecordBug() { // create an SSTRecord and Write a certain pattern of strings // to it ... then Serialize it and verify the content SSTRecord record = new SSTRecord(); // the record will start with two integers, then this string // ... that will eat up 16 of the 8224 bytes that the record // can hold record.AddString(new UnicodeString("Hello")); // now we have an additional 8208 bytes, which is1 an exact // multiple of 16 bytes long testvalue = 1000000000000L; for (int k = 0; k < 2000; k++) { record.AddString(new UnicodeString((testvalue++).ToString())); } byte[] content = new byte[record.RecordSize]; record.Serialize(0, content); Assert.AreEqual(8224, LittleEndian.GetShort(content, 2)); Assert.AreEqual(ContinueRecord.sid, LittleEndian.GetShort(content, 8228)); Assert.AreEqual(8224, LittleEndian.GetShort(content, 8228 + 2)); Assert.AreEqual((byte)13, content[4 + 8228]); Assert.AreEqual(ContinueRecord.sid, LittleEndian.GetShort(content, 2 * 8228)); Assert.AreEqual(8224, LittleEndian.GetShort(content, 8228 * 2 + 2)); Assert.AreEqual((byte)13, content[4 + 8228 * 2]); Assert.AreEqual(ContinueRecord.sid, LittleEndian.GetShort(content, 3 * 8228)); Assert.AreEqual((byte)13, content[4 + 8228 * 3]); }
/// <summary> /// Creates a stub Workbook from the supplied records, /// suitable for use with the {@link HSSFFormulaParser} /// </summary> /// <param name="externs">The ExternSheetRecords in your file</param> /// <param name="bounds">The BoundSheetRecords in your file</param> /// <param name="sst">TThe SSTRecord in your file.</param> /// <returns>A stub Workbook suitable for use with HSSFFormulaParser</returns> public static InternalWorkbook CreateStubWorkbook(ExternSheetRecord[] externs, BoundSheetRecord[] bounds, SSTRecord sst) { List <Record> wbRecords = new List <Record>(); // Core Workbook records go first if (bounds != null) { for (int i = 0; i < bounds.Length; i++) { wbRecords.Add(bounds[i]); } } if (sst != null) { wbRecords.Add(sst); } // Now we can have the ExternSheetRecords, // preceded by a SupBookRecord if (externs != null) { wbRecords.Add(SupBookRecord.CreateInternalReferences( (short)externs.Length)); for (int i = 0; i < externs.Length; i++) { wbRecords.Add(externs[i]); } } // Finally we need an EoF record wbRecords.Add(EOFRecord.instance); return(InternalWorkbook.CreateWorkbook(wbRecords)); }
/// <summary> /// Process the record ourselves, but do not /// pass it on to the child Listener. /// </summary> /// <param name="record">The record.</param> public void ProcessRecordInternally(Record record) { if (record is BoundSheetRecord) { boundSheetRecords.Add(record); } else if (record is ExternSheetRecord) { externSheetRecords.Add(record); } else if (record is SSTRecord) { sstRecord = (SSTRecord)record; } }
public void TestSimpleAddString() { SSTRecord record = new SSTRecord(); UnicodeString s1 = new UnicodeString("Hello world"); // \u2122 is1 the encoding of the trademark symbol ... UnicodeString s2 = new UnicodeString("Hello world\u2122"); Assert.AreEqual(0, record.AddString(s1)); Assert.AreEqual(s1, record.GetString(0)); Assert.AreEqual(1, record.CountStrings); Assert.AreEqual(1, record.NumStrings); Assert.AreEqual(1, record.NumUniqueStrings); Assert.AreEqual(0, record.AddString(s1)); Assert.AreEqual(s1, record.GetString(0)); Assert.AreEqual(1, record.CountStrings); Assert.AreEqual(2, record.NumStrings); Assert.AreEqual(1, record.NumUniqueStrings); Assert.AreEqual(1, record.AddString(s2)); Assert.AreEqual(s2, record.GetString(1)); Assert.AreEqual(2, record.CountStrings); Assert.AreEqual(3, record.NumStrings); Assert.AreEqual(2, record.NumUniqueStrings); System.Collections.IEnumerator iter = record.GetStrings(); while (iter.MoveNext()) { UnicodeString ucs = (UnicodeString)iter.Current; if (ucs.Equals(s1)) { Assert.AreEqual((byte)0, ucs.OptionFlags); } else if (ucs.Equals(s2)) { Assert.AreEqual((byte)1, ucs.OptionFlags); } else { Assert.Fail("cannot match string: " + ucs.String); } } }
public void TestSimpleConstructor() { SSTRecord record = new SSTRecord(); Assert.AreEqual(0, record.NumStrings); Assert.AreEqual(0, record.NumUniqueStrings); Assert.AreEqual(0, record.CountStrings); byte[] output = record.Serialize(); byte[] expected = { (byte)record.Sid, (byte)(record.Sid >> 8), (byte)8, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0 }; Assert.AreEqual(expected.Length, output.Length); for (int k = 0; k < expected.Length; k++) { Assert.AreEqual(expected[k], output[k], k.ToString()); } }
/** * Writes out the shared string table * * @param outputFile the binary output file * @exception IOException */ public void write(File outputFile) { // Thanks to Guenther for contributing the ExtSST implementation portion // of this method int charsLeft = 0; string curString = null; SSTRecord sst = new SSTRecord(totalOccurrences, stringList.Count); ExtendedSSTRecord extsst = new ExtendedSSTRecord(stringList.Count); int bucketSize = extsst.getNumberOfStringsPerBucket(); int stringIndex = 0; // CML: this one is nasty.... IEnumerator iterator = stringList.GetEnumerator(); while (iterator.MoveNext() && charsLeft == 0) { curString = (string)iterator.Current; // offset + header bytes int relativePosition = sst.getOffset() + 4; charsLeft = sst.add(curString); if ((stringIndex % bucketSize) == 0) extsst.addString(outputFile.getPos(), relativePosition); stringIndex++; } outputFile.write(sst); if (charsLeft != 0 || iterator.MoveNext()) { // Add the remainder of the string to the continue record SSTContinueRecord cont = createContinueRecord(curString,charsLeft,outputFile); // Carry on looping through the array until all the strings are done do { curString = (string)iterator.Current; int relativePosition = cont.getOffset() + 4; charsLeft = cont.add(curString); if ((stringIndex % bucketSize) == 0) extsst.addString(outputFile.getPos(), relativePosition); stringIndex++; if (charsLeft != 0) { outputFile.write(cont); cont = createContinueRecord(curString, charsLeft, outputFile); } } while (iterator.MoveNext()); outputFile.write(cont); } outputFile.write(extsst); }
/// <summary> /// Process an HSSF Record. Called when a record occurs in an HSSF file. /// </summary> /// <param name="record"></param> public void ProcessRecord(Record record) { String thisText = null; int thisRow = -1; switch (record.Sid) { case BoundSheetRecord.sid: BoundSheetRecord sr = (BoundSheetRecord)record; sheetNames.Add(sr.Sheetname); break; case BOFRecord.sid: BOFRecord bof = (BOFRecord)record; if (bof.Type == BOFRecordType.Worksheet) { sheetNum++; rowNum = -1; if (includeSheetNames) { if (text.Length > 0) { text.Append("\n"); } text.Append(sheetNames[sheetNum]); } } break; case SSTRecord.sid: sstRecord = (SSTRecord)record; break; case FormulaRecord.sid: FormulaRecord frec = (FormulaRecord)record; thisRow = frec.Row; if (formulasNotResults) { thisText = HSSFFormulaParser.ToFormulaString((HSSFWorkbook)null, frec.ParsedExpression); } else { if (frec.HasCachedResultString) { // Formula result is a string // This is stored in the next record outputNextStringValue = true; nextRow = frec.Row; } else { thisText = FormatNumberDateCell(frec, frec.Value); } } break; case StringRecord.sid: if (outputNextStringValue) { // String for formula StringRecord srec = (StringRecord)record; thisText = srec.String; thisRow = nextRow; outputNextStringValue = false; } break; case LabelRecord.sid: LabelRecord lrec = (LabelRecord)record; thisRow = lrec.Row; thisText = lrec.Value; break; case LabelSSTRecord.sid: LabelSSTRecord lsrec = (LabelSSTRecord)record; thisRow = lsrec.Row; if (sstRecord == null) { throw new Exception("No SST record found"); } thisText = sstRecord.GetString(lsrec.SSTIndex).ToString(); break; case NoteRecord.sid: NoteRecord nrec = (NoteRecord)record; thisRow = nrec.Row; // TODO: Find object to match nrec.GetShapeId() break; case NumberRecord.sid: NumberRecord numrec = (NumberRecord)record; thisRow = numrec.Row; thisText = FormatNumberDateCell(numrec, numrec.Value); break; default: break; } if (thisText != null) { if (thisRow != rowNum) { rowNum = thisRow; if (text.Length > 0) { text.Append("\n"); } } else { text.Append("\t"); } text.Append(thisText); } }
/// <summary> /// Main HSSFListener method, processes events, and outputs the /// strings as the file is processed /// </summary> public void ProcessRecord(Record record) { var thisRow = -1; string thisStr = null; switch (record.Sid) { case BoundSheetRecord.sid: _boundSheetRecords.Add(record); break; case BOFRecord.sid: var br = (BOFRecord)record; if (br.Type == BOFRecord.TYPE_WORKSHEET) { // Create sub workbook if required if (_workbookBuildingListener != null && _stubWorkbook == null) { _stubWorkbook = _workbookBuildingListener.GetStubHSSFWorkbook(); } // Output the worksheet name // Works by ordering the BSRs by the location of // their BOFRecords, and then knowing that we // process BOFRecords in byte offset order if (_orderedBsRs == null) { _orderedBsRs = BoundSheetRecord.OrderByBofPosition(_boundSheetRecords); } } break; case SSTRecord.sid: _sstRecord = (SSTRecord)record; break; case BlankRecord.sid: var brec = (BlankRecord)record; thisRow = brec.Row; thisStr = ""; break; case BoolErrRecord.sid: var berec = (BoolErrRecord)record; thisRow = berec.Row; thisStr = ""; break; case FormulaRecord.sid: var frec = (FormulaRecord)record; thisRow = frec.Row; if (OutputFormulaValues) { if (double.IsNaN(frec.Value)) { // Formula result is a string // This is stored in the next record _outputNextStringRecord = true; _nextRow = frec.Row; } else { thisStr = _formatListener.FormatNumberDateCell(frec); } } else { thisStr = HSSFFormulaParser.ToFormulaString(_stubWorkbook, frec.ParsedExpression); } break; case StringRecord.sid: if (_outputNextStringRecord) { // String for formula var srec = (StringRecord)record; thisStr = srec.String; thisRow = _nextRow; _outputNextStringRecord = false; } break; case LabelRecord.sid: var lrec = (LabelRecord)record; thisRow = lrec.Row; thisStr = lrec.Value; break; case LabelSSTRecord.sid: var lsrec = (LabelSSTRecord)record; thisRow = lsrec.Row; if (_sstRecord == null) { thisStr = "(No SST Record, can't identify string)"; } else { thisStr = _sstRecord.GetString(lsrec.SSTIndex).ToString(); } break; case NoteRecord.sid: var nrec = (NoteRecord)record; thisRow = nrec.Row; thisStr = ""; break; case NumberRecord.sid: var numrec = (NumberRecord)record; thisRow = numrec.Row; // Format thisStr = _formatListener.FormatNumberDateCell(numrec); break; case RKRecord.sid: var rkrec = (RKRecord)record; thisRow = rkrec.Row; thisStr = ""; break; } // Handle new row if (thisRow != -1 && thisRow != _lastRowNumber) { _row = new List <string>(); } // Handle missing column if (record is MissingCellDummyRecord) { var mc = (MissingCellDummyRecord)record; thisRow = mc.Row; thisStr = ""; } // If we got something to print out, do so if (thisStr != null) { _row.Add(thisStr); } // Update column and row count if (thisRow > -1) { _lastRowNumber = thisRow; } // Handle end of row if (record is LastCellOfRowDummyRecord) { // We're onto a new row Output.Add(_row); } }
public void TestHugeStrings() { SSTRecord record = new SSTRecord(); byte[][] bstrings = { new byte[9000], new byte[7433], new byte[9002], new byte[16998] }; UnicodeString[] strings = new UnicodeString[bstrings.Length]; int total_length = 0; for (int k = 0; k < bstrings.Length; k++) { Arrays.Fill(bstrings[k], (byte)(Convert.ToInt32('a') + k)); strings[k] = new UnicodeString(ConvertByteArrayToString(bstrings[k])); record.AddString(strings[k]); total_length += 3 + bstrings[k].Length; } // add overhead of SST record total_length += 8; // add overhead of broken strings total_length += 4; // add overhead of six records total_length += (6 * 4); byte[] content = new byte[record.RecordSize]; record.Serialize(0, content); Assert.AreEqual(total_length, content.Length); //DeSerialize the record. RecordInputStream recStream = new RecordInputStream(new MemoryStream(content)); recStream.NextRecord(); record = new SSTRecord(recStream); Assert.AreEqual(strings.Length, record.NumStrings); Assert.AreEqual(strings.Length, record.NumUniqueStrings); Assert.AreEqual(strings.Length, record.CountStrings); for (int k = 0; k < strings.Length; k++) { Assert.AreEqual(strings[k], record.GetString(k)); } record = new SSTRecord(); bstrings[1] = new byte[bstrings[1].Length - 1]; for (int k = 0; k < bstrings.Length; k++) { if ((bstrings[k].Length % 2) == 1) { Arrays.Fill(bstrings[k], (byte)('a' + k)); strings[k] = new UnicodeString(ConvertByteArrayToString(bstrings[k])); } else { char[] data = new char[bstrings[k].Length / 2]; Arrays.Fill(data, (char)(Convert.ToInt32('\u2122') + k)); strings[k] = new UnicodeString(new String(data)); } record.AddString(strings[k]); } content = new byte[record.RecordSize]; record.Serialize(0, content); total_length--; Assert.AreEqual(total_length, content.Length); recStream = new RecordInputStream(new MemoryStream(content)); recStream.NextRecord(); record = new SSTRecord(recStream); Assert.AreEqual(strings.Length, record.NumStrings); Assert.AreEqual(strings.Length, record.NumUniqueStrings); Assert.AreEqual(strings.Length, record.CountStrings); for (int k = 0; k < strings.Length; k++) { Assert.AreEqual(strings[k], record.GetString(k)); } }