Add this expression in a cell:
${java.lang.System.out.println('foo')} bar
and format 'foo' with a color (e.g. red).
Run the transformer and the following exception will be thrown:
java.lang.IllegalArgumentException: Start and end index not in range.
at org.apache.poi.xssf.usermodel.XSSFRichTextString.applyFont(XSSFRichTextString.java:140)
at net.sf.jett.util.RichTextStringUtil.formatString(RichTextStringUtil.java:476)
at net.sf.jett.util.RichTextStringUtil.createFormattedString(RichTextStringUtil.java:445)
at net.sf.jett.util.RichTextStringUtil.replaceValues(RichTextStringUtil.java:215)
at net.sf.jett.expression.Expression.replaceExpressions(Expression.java:543)
at net.sf.jett.expression.Expression.evaluateString(Expression.java:410)
at net.sf.jett.transform.CellTransformer.transform(CellTransformer.java:120)
......
I found that RichTextStringUtil.updateFormattingRuns does not handle the change correctly in some cases.
The attachments are the fixed version of RichTextStringUtil and the output for the test file above.
The logic of RichTextStringUtil.updateFormattingRuns is improved, and the length of replacement target is required as a parameter.
After calling updateFormattingRuns, only one FormattingRun will be applied on each replacement. FormattingRun that applied on the left part or right part of replacement will be either extended or shrunk.
The other changes are for ticket #26 and my debugging purpose.
Edit: the code is pasted on the 4th reply.
Last edit: Merci chao 2014-06-07
The logic also works with HSSF.
Here is the updated version.
Edit: the code is pasted on the 4th reply.
Last edit: Merci chao 2014-06-07
Format your entire expression with red text, not just
'foo'
. JETT will assume that an entire expression is formatted with one formatting run, and the result of the evaluation will have the same formatting run. That's the only way that makes sense. I don't see any logical, consistent way to handle the manipulation of a formatting run when replacing an entire expression with its result, when the formatting run doesn't cover the entire expression. What should happen if the formatting run covers some code in the expression? What should happen if the formatting run covers the end of an expression and some text beyond the expression? I don't know, and JETT doesn't do anything special with these situations.Also, calling
System.out.println
in an expression will print to the system console, not return that value as the result of the expression.Even if you have
${java.lang.System.out.println('foo')} bar
It will result in
bar
with "foo" being printed to the system console's standard out.
Ensure that any formatting run in an expression covers the entire expression.
If you try
${'foo'} bar
then it will result in
foo bar
I know it does not make sense to style part of an expression.
I will never want to do it, but Excel always applies a default font for the unsupported characters.
For example, if there is a cell, uses "Times New Roman" as the font, with the following value:
${null ? "A star ★" : "A triangle ▲"}
You can see that "Times New Roman" won't be applied on the star and triangle symbol, because Times New Roman does not support these characters.
Then IllegalArgumentException will be thrown during transformation.
In my actual case, my users require the reports to use "Times New Roman" as the main font. However, those are Chinese reports, many Chinese strings are used in the expressions. Unfortunately, Times New Roman does not support Chinese characters thus mixed font style appears.
Well, we can hard-code all unsupported characters inside Java code and pass them as variables for workaround. Obviously it is not a good idea for MVC pattern.
Another available workaround is to use some complex solution to scrape the result, but it may make the code become unreadable and hard for maintaining:
${null ? "A star " : "A triangle "}${null ? "★" : "▲"}
(use another font that supports these symbols for the second expression.)
In my own opinion, JETT should handle these situations, and make a more comparatively reasonable result, rather than crashing with an ambiguous IllegalArgumentException.
Like the rewritten version of RichTextStringUtil.updateFormattingRuns I have suggested, applying the first covering formatting to the whole replacement of expression is not a bad idea:
P.S. This problem did make me crazy in finding out the root cause and writing patch for two whole working-days, ha...
Last edit: Merci chao 2014-06-07
The suggested code has been updated in the previous reply.
Hi, was this resolved in version 0.10.0?
You're still wrong! Here is an annex project to simulate the error.
Strange that occurs only when the result of the expression is less than the size of the expression.
I only managed to solve this if, but I do not know if it is the best way
I did it on 0.11.0-SNAPSHOT
Last edit: Hêndi Marcos 2017-10-07