Search in sources :

Example 6 with UnicodeString

use of org.apache.poi.hssf.record.common.UnicodeString in project poi by apache.

the class HSSFOptimiser method optimiseFonts.

/**
	 * Goes through the Workbook, optimising the fonts by
	 *  removing duplicate ones.
	 * For now, only works on fonts used in {@link HSSFCellStyle}
	 *  and {@link HSSFRichTextString}. Any other font uses
	 *  (eg charts, pictures) may well end up broken!
	 * This can be a slow operation, especially if you have
	 *  lots of cells, cell styles or rich text strings
	 * @param workbook The workbook in which to optimise the fonts
	 */
public static void optimiseFonts(HSSFWorkbook workbook) {
    // Where each font has ended up, and if we need to
    //  delete the record for it. Start off with no change
    short[] newPos = new short[workbook.getWorkbook().getNumberOfFontRecords() + 1];
    boolean[] zapRecords = new boolean[newPos.length];
    for (int i = 0; i < newPos.length; i++) {
        newPos[i] = (short) i;
        zapRecords[i] = false;
    }
    // Get each font record, so we can do deletes
    //  without getting confused
    FontRecord[] frecs = new FontRecord[newPos.length];
    for (int i = 0; i < newPos.length; i++) {
        // There is no 4!
        if (i == 4)
            continue;
        frecs[i] = workbook.getWorkbook().getFontRecordAt(i);
    }
    // Note - don't change built in fonts (those before 5)
    for (int i = 5; i < newPos.length; i++) {
        // Check this one for being a duplicate
        //  of an earlier one
        int earlierDuplicate = -1;
        for (int j = 0; j < i && earlierDuplicate == -1; j++) {
            if (j == 4)
                continue;
            FontRecord frCheck = workbook.getWorkbook().getFontRecordAt(j);
            if (frCheck.sameProperties(frecs[i])) {
                earlierDuplicate = j;
            }
        }
        // If we got a duplicate, mark it as such
        if (earlierDuplicate != -1) {
            newPos[i] = (short) earlierDuplicate;
            zapRecords[i] = true;
        }
    }
    // Only need to worry about user fonts
    for (int i = 5; i < newPos.length; i++) {
        // Find the number deleted to that
        //  point, and adjust
        short preDeletePos = newPos[i];
        short newPosition = preDeletePos;
        for (int j = 0; j < preDeletePos; j++) {
            if (zapRecords[j])
                newPosition--;
        }
        // Update the new position
        newPos[i] = newPosition;
    }
    // Zap the un-needed user font records
    for (int i = 5; i < newPos.length; i++) {
        if (zapRecords[i]) {
            workbook.getWorkbook().removeFontRecord(frecs[i]);
        }
    }
    // Tell HSSFWorkbook that it needs to
    //  re-start its HSSFFontCache
    workbook.resetFontCache();
    //  new locations of the fonts
    for (int i = 0; i < workbook.getWorkbook().getNumExFormats(); i++) {
        ExtendedFormatRecord xfr = workbook.getWorkbook().getExFormatAt(i);
        xfr.setFontIndex(newPos[xfr.getFontIndex()]);
    }
    // Update the rich text strings to point at
    //  the new locations of the fonts
    // Remember that one underlying unicode string
    //  may be shared by multiple RichTextStrings!
    HashSet<UnicodeString> doneUnicodeStrings = new HashSet<UnicodeString>();
    for (int sheetNum = 0; sheetNum < workbook.getNumberOfSheets(); sheetNum++) {
        HSSFSheet s = workbook.getSheetAt(sheetNum);
        for (Row row : s) {
            for (Cell cell : row) {
                if (cell.getCellTypeEnum() == CellType.STRING) {
                    HSSFRichTextString rtr = (HSSFRichTextString) cell.getRichStringCellValue();
                    UnicodeString u = rtr.getRawUnicodeString();
                    // Have we done this string already?
                    if (!doneUnicodeStrings.contains(u)) {
                        // Update for each new position
                        for (short i = 5; i < newPos.length; i++) {
                            if (i != newPos[i]) {
                                u.swapFontUse(i, newPos[i]);
                            }
                        }
                        // Mark as done
                        doneUnicodeStrings.add(u);
                    }
                }
            }
        }
    }
}
Also used : FontRecord(org.apache.poi.hssf.record.FontRecord) ExtendedFormatRecord(org.apache.poi.hssf.record.ExtendedFormatRecord) UnicodeString(org.apache.poi.hssf.record.common.UnicodeString) Row(org.apache.poi.ss.usermodel.Row) Cell(org.apache.poi.ss.usermodel.Cell) HashSet(java.util.HashSet)

Example 7 with UnicodeString

use of org.apache.poi.hssf.record.common.UnicodeString in project poi by apache.

the class HSSFCell method setCellValue.

/**
     * Set a string value for the cell.
     *
     * @param value  value to set the cell to.  For formulas we'll set the formula
     * string, for String cells we'll set its value.  For other types we will
     * change the cell to a string cell and set its value.
     * If value is <code>null</code> then we will change the cell to a Blank cell.
     */
public void setCellValue(RichTextString value) {
    int row = _record.getRow();
    short col = _record.getColumn();
    short styleIndex = _record.getXFIndex();
    if (value == null) {
        notifyFormulaChanging();
        setCellType(CellType.BLANK, false, row, col, styleIndex);
        return;
    }
    if (value.length() > SpreadsheetVersion.EXCEL97.getMaxTextLength()) {
        throw new IllegalArgumentException("The maximum length of cell contents (text) is 32,767 characters");
    }
    if (_cellType == CellType.FORMULA) {
        // Set the 'pre-evaluated result' for the formula
        // note - formulas do not preserve text formatting.
        FormulaRecordAggregate fr = (FormulaRecordAggregate) _record;
        fr.setCachedStringResult(value.getString());
        // Update our local cache to the un-formatted version
        _stringValue = new HSSFRichTextString(value.getString());
        // All done
        return;
    }
    if (_cellType != CellType.STRING) {
        setCellType(CellType.STRING, false, row, col, styleIndex);
    }
    int index = 0;
    HSSFRichTextString hvalue = (HSSFRichTextString) value;
    UnicodeString str = hvalue.getUnicodeString();
    index = _book.getWorkbook().addSSTString(str);
    ((LabelSSTRecord) _record).setSSTIndex(index);
    _stringValue = hvalue;
    _stringValue.setWorkbookReferences(_book.getWorkbook(), ((LabelSSTRecord) _record));
    _stringValue.setUnicodeString(_book.getWorkbook().getSSTString(index));
}
Also used : UnicodeString(org.apache.poi.hssf.record.common.UnicodeString) FormulaRecordAggregate(org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate) LabelSSTRecord(org.apache.poi.hssf.record.LabelSSTRecord)

Example 8 with UnicodeString

use of org.apache.poi.hssf.record.common.UnicodeString in project poi by apache.

the class HSSFCell method setCellType.

/**
     * sets the cell type. The setValue flag indicates whether to bother about
     *  trying to preserve the current value in the new record if one is created.
     *  <p>
     *  The @see #setCellValue method will call this method with false in setValue
     *  since it will overwrite the cell value later
     *
     */
private void setCellType(CellType cellType, boolean setValue, int row, short col, short styleIndex) {
    switch(cellType) {
        case FORMULA:
            FormulaRecordAggregate frec;
            if (cellType != _cellType) {
                frec = _sheet.getSheet().getRowsAggregate().createFormula(row, col);
            } else {
                frec = (FormulaRecordAggregate) _record;
                frec.setRow(row);
                frec.setColumn(col);
            }
            if (setValue) {
                frec.getFormulaRecord().setValue(getNumericCellValue());
            }
            frec.setXFIndex(styleIndex);
            _record = frec;
            break;
        case NUMERIC:
            NumberRecord nrec = null;
            if (cellType != _cellType) {
                nrec = new NumberRecord();
            } else {
                nrec = (NumberRecord) _record;
            }
            nrec.setColumn(col);
            if (setValue) {
                nrec.setValue(getNumericCellValue());
            }
            nrec.setXFIndex(styleIndex);
            nrec.setRow(row);
            _record = nrec;
            break;
        case STRING:
            LabelSSTRecord lrec;
            if (cellType == _cellType) {
                lrec = (LabelSSTRecord) _record;
            } else {
                lrec = new LabelSSTRecord();
                lrec.setColumn(col);
                lrec.setRow(row);
                lrec.setXFIndex(styleIndex);
            }
            if (setValue) {
                String str = convertCellValueToString();
                if (str == null) {
                    // bug 55668: don't try to store null-string when formula
                    // results in empty/null value
                    setCellType(CellType.BLANK, false, row, col, styleIndex);
                    return;
                } else {
                    int sstIndex = _book.getWorkbook().addSSTString(new UnicodeString(str));
                    lrec.setSSTIndex(sstIndex);
                    UnicodeString us = _book.getWorkbook().getSSTString(sstIndex);
                    _stringValue = new HSSFRichTextString();
                    _stringValue.setUnicodeString(us);
                }
            }
            _record = lrec;
            break;
        case BLANK:
            BlankRecord brec = null;
            if (cellType != _cellType) {
                brec = new BlankRecord();
            } else {
                brec = (BlankRecord) _record;
            }
            brec.setColumn(col);
            // During construction the cellStyle may be null for a Blank cell.
            brec.setXFIndex(styleIndex);
            brec.setRow(row);
            _record = brec;
            break;
        case BOOLEAN:
            BoolErrRecord boolRec = null;
            if (cellType != _cellType) {
                boolRec = new BoolErrRecord();
            } else {
                boolRec = (BoolErrRecord) _record;
            }
            boolRec.setColumn(col);
            if (setValue) {
                boolRec.setValue(convertCellValueToBoolean());
            }
            boolRec.setXFIndex(styleIndex);
            boolRec.setRow(row);
            _record = boolRec;
            break;
        case ERROR:
            BoolErrRecord errRec = null;
            if (cellType != _cellType) {
                errRec = new BoolErrRecord();
            } else {
                errRec = (BoolErrRecord) _record;
            }
            errRec.setColumn(col);
            if (setValue) {
                errRec.setValue(FormulaError.VALUE.getCode());
            }
            errRec.setXFIndex(styleIndex);
            errRec.setRow(row);
            _record = errRec;
            break;
        default:
            throw new IllegalStateException("Invalid cell type: " + cellType);
    }
    if (cellType != _cellType && // Special Value to indicate an uninitialized Cell
    _cellType != CellType._NONE) {
        _sheet.getSheet().replaceValueRecord(_record);
    }
    _cellType = cellType;
}
Also used : BoolErrRecord(org.apache.poi.hssf.record.BoolErrRecord) BlankRecord(org.apache.poi.hssf.record.BlankRecord) UnicodeString(org.apache.poi.hssf.record.common.UnicodeString) FormulaRecordAggregate(org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate) RichTextString(org.apache.poi.ss.usermodel.RichTextString) UnicodeString(org.apache.poi.hssf.record.common.UnicodeString) NumberRecord(org.apache.poi.hssf.record.NumberRecord) LabelSSTRecord(org.apache.poi.hssf.record.LabelSSTRecord)

Example 9 with UnicodeString

use of org.apache.poi.hssf.record.common.UnicodeString in project poi by apache.

the class TestBugs method bug47847.

/**
     * Round trip a file with an unusual UnicodeString/ExtRst record parts
     */
@Test
public void bug47847() throws Exception {
    HSSFWorkbook wb1 = openSample("47847.xls");
    assertEquals(3, wb1.getNumberOfSheets());
    // Find the SST record
    UnicodeString withExt = wb1.getWorkbook().getSSTString(0);
    UnicodeString withoutExt = wb1.getWorkbook().getSSTString(31);
    assertEquals("O:Alloc:Qty", withExt.getString());
    assertTrue((withExt.getOptionFlags() & 0x0004) == 0x0004);
    assertEquals("RT", withoutExt.getString());
    assertTrue((withoutExt.getOptionFlags() & 0x0004) == 0x0000);
    // Something about continues...
    // Write out and re-read
    HSSFWorkbook wb2 = writeOutAndReadBack(wb1);
    wb1.close();
    assertEquals(3, wb2.getNumberOfSheets());
    // Check it's the same now
    withExt = wb2.getWorkbook().getSSTString(0);
    withoutExt = wb2.getWorkbook().getSSTString(31);
    assertEquals("O:Alloc:Qty", withExt.getString());
    assertTrue((withExt.getOptionFlags() & 0x0004) == 0x0004);
    assertEquals("RT", withoutExt.getString());
    assertTrue((withoutExt.getOptionFlags() & 0x0004) == 0x0000);
    wb2.close();
}
Also used : UnicodeString(org.apache.poi.hssf.record.common.UnicodeString) Test(org.junit.Test)

Example 10 with UnicodeString

use of org.apache.poi.hssf.record.common.UnicodeString in project poi by apache.

the class TestSSTRecord method testHugeStrings.

/**
     * Test capability of handling mondo big strings
     *
     * @exception IOException
     */
@Test
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) ('a' + k));
        strings[k] = new UnicodeString(new String(bstrings[k], LocaleUtil.CHARSET_1252));
        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.getRecordSize()];
    record.serialize(0, content);
    assertEquals(total_length, content.length);
    //Deserialize the record.
    RecordInputStream recStream = new RecordInputStream(new ByteArrayInputStream(content));
    recStream.nextRecord();
    record = new SSTRecord(recStream);
    assertEquals(strings.length, record.getNumStrings());
    assertEquals(strings.length, record.getNumUniqueStrings());
    assertEquals(strings.length, record.countStrings());
    for (int k = 0; k < strings.length; k++) {
        assertEquals(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(new String(bstrings[k], LocaleUtil.CHARSET_1252));
        } else {
            char[] data = new char[bstrings[k].length / 2];
            Arrays.fill(data, (char) ('™' + k));
            strings[k] = new UnicodeString(new String(data));
        }
        record.addString(strings[k]);
    }
    content = new byte[record.getRecordSize()];
    record.serialize(0, content);
    total_length--;
    assertEquals(total_length, content.length);
    recStream = new RecordInputStream(new ByteArrayInputStream(content));
    recStream.nextRecord();
    record = new SSTRecord(recStream);
    assertEquals(strings.length, record.getNumStrings());
    assertEquals(strings.length, record.getNumUniqueStrings());
    assertEquals(strings.length, record.countStrings());
    for (int k = 0; k < strings.length; k++) {
        assertEquals(strings[k], record.getString(k));
    }
}
Also used : UnicodeString(org.apache.poi.hssf.record.common.UnicodeString) ByteArrayInputStream(java.io.ByteArrayInputStream) UnicodeString(org.apache.poi.hssf.record.common.UnicodeString) Test(org.junit.Test)

Aggregations

UnicodeString (org.apache.poi.hssf.record.common.UnicodeString)16 Test (org.junit.Test)5 LabelSSTRecord (org.apache.poi.hssf.record.LabelSSTRecord)3 ExtendedFormatRecord (org.apache.poi.hssf.record.ExtendedFormatRecord)2 FontRecord (org.apache.poi.hssf.record.FontRecord)2 FormulaRecordAggregate (org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate)2 ByteArrayInputStream (java.io.ByteArrayInputStream)1 HashSet (java.util.HashSet)1 EscherBSERecord (org.apache.poi.ddf.EscherBSERecord)1 EscherBlipRecord (org.apache.poi.ddf.EscherBlipRecord)1 EscherRecord (org.apache.poi.ddf.EscherRecord)1 AbstractEscherHolderRecord (org.apache.poi.hssf.record.AbstractEscherHolderRecord)1 BackupRecord (org.apache.poi.hssf.record.BackupRecord)1 BlankRecord (org.apache.poi.hssf.record.BlankRecord)1 BoolErrRecord (org.apache.poi.hssf.record.BoolErrRecord)1 BoundSheetRecord (org.apache.poi.hssf.record.BoundSheetRecord)1 DrawingGroupRecord (org.apache.poi.hssf.record.DrawingGroupRecord)1 FilePassRecord (org.apache.poi.hssf.record.FilePassRecord)1 LabelRecord (org.apache.poi.hssf.record.LabelRecord)1 NameRecord (org.apache.poi.hssf.record.NameRecord)1