2

I need to append to 2 HSSFRichTextStrings in Java with Apache POI. How can I do this?
What I'm exactly doing is I'm getting the rich text string already present in a cell and I'm trying to append an additional rich text string to it and write it back to the cell.
Please tell me how to do this.

rgettman
  • 176,041
  • 30
  • 275
  • 357
Saicharan S M
  • 828
  • 3
  • 11
  • 25
  • Looking at the javadoc it does not seem to be possible. You can alway create a new HSSFRichTextStrings with the concatenated string and re-apply the formatting... – assylias Mar 14 '12 at 09:35
  • But I cant say for sure wat formatting was applied to the rich text string already present in a cell. How can do it then? Is it possible to get the font of a rich text string? – Saicharan S M Mar 14 '12 at 09:41
  • 1
    I don't know how HSSFRichTextStrings work, I just looked at the javadoc. It has methods to read and write formatting character by character - so I would have thought you can use them... (http://poi.apache.org/apidocs/org/apache/poi/hssf/usermodel/HSSFRichTextString.html#applyFont%28int,%20int,%20short%29) and (http://poi.apache.org/apidocs/org/apache/poi/hssf/usermodel/HSSFRichTextString.html#getFontAtIndex%28int%29) – assylias Mar 14 '12 at 09:47

2 Answers2

6

It is possible to append two HSSFRichTextStrings, but you will have to do most of the work yourself. You will need to take advantage of the following methods in HSSFRichTextString:

First, create a little class to store formatting run stats:

public class FormattingRun {
    private int beginIdx;
    private int length;
    private short fontIdx;
    public FormattingRun(int beginIdx, int length, short fontIdx) {
        this.beginIdx = beginIdx;
        this.length = length;
        this.fontIdx = fontIdx;
    }
    public int getBegin() { return beginIdx; }
    public int getLength() { return length; }
    public short getFontIndex { return fontIdx; }
}

Next, gather all of the formatting run statistics for each of the two strings. You'll have to walk the strings yourself to determine how long each formatting run lasts.

List<FormattingRun> formattingRuns = new ArrayList<FormattingRun>();
int numFormattingRuns = richTextString.numFormattingRuns();
for (int fmtIdx = 0; fmtIdx < numFormattingRuns; fmtIdx)
{
    int begin = richTextString.getIndexOfFormattingRun(fmtIdx);
    short fontIndex = richTextString.getFontOfFormattingRun(fmtIdx);

    // Walk the string to determine the length of the formatting run.
    int length = 0;
    for (int j = begin; j < richTextString.length(); j++)
    {
        short currFontIndex = richTextString.getFontAtIndex(j);
        if (currFontIndex == fontIndex)
            length++;
        else
            break;
    }
    formattingRuns.add(new FormattingRun(begin, length, fontIndex));
}

Next, concatenate the two String values yourself and create the result HSSFRichTextString.

HSSFRichTextString result = new HSSFRichTextString(
     richTextString1.getString() + richTextString2.getString());

Last, apply both sets of formatting runs, with the second set of runs being offset by the first string's length.

for (FormattingRun run1 : formattingRuns1)
{
    int begin = run1.getBegin();
    int end = begin + run1.getLength();
    short fontIdx = run1.getFontIndex();
    result.applyFont(begin, end, fontIdx);
}
for (FormattingRun run2 : formattingRuns2)
{
    // offset by string length 1
    int begin = run2.getBegin() + richTextString1.length();
    int end = begin + run2.getLength();
    short fontIdx = run2.getFontIndex();
    result.applyFont(begin, end, fontIdx);
}

That should do it for concatenating HSSFRichTextStrings.

If you ever want to concatenate XSSFRichTextStrings, found in .xlsx files, the process is very similar. One difference is that XSSFRichTextString#getFontOfFormattingRun will return an XSSFFont instead of a short font index. That's okay, because calling applyFont on an XSSFRichTextString takes an XSSFFont anyway. Another difference is that getFontOfFormattingRun may throw a NullPointerException if there is no font applied for the formatting run, which occurs when there is no different font applied than the font that is already there for the CellStyle for the entire Cell.

rgettman
  • 176,041
  • 30
  • 275
  • 357
  • How do you get around the NullPointerException for XSSFRichTextStrings? – user1007895 Oct 01 '13 at 03:19
  • @user1007895 Catch the `NullPointerException` thrown by `getFontOfFormattingRun`; that is the case where there is no formatting run at that index. Don't create a `FormattingRun` for that gap where there is no font applied. Then you won't call `applyFont` for the corresponding gap in the new `XSSFRichTextString`. – rgettman Oct 01 '13 at 17:58
2

If you're using XSSFRichTextStrings, you can't directly concatenate two RichTextString.

However, you can indirectly do so by finding the text value of the second RichTextString and then using the append method to append that string value with an applied font (RichText in essence).

XSSFRichTextString rt1 = new XSSFRichTextString("Apache POI is");
rt1.applyFont(plainArial);
XSSFRichTextString rt2 = new XSSFRichTextString(" great!");
rt2.applyFont(boldArial);
String text = rt2.getString();

cell1.setCellValue(rt1.append(text, boldArial));

Source:

enter link description here

womplefrog
  • 769
  • 1
  • 6
  • 18