JETT 0.11.0 (Beta) Released - 14 May 2018
New in JETT 0.11.0:
- Ticket #68: If a "<" character is inside the body of a tag, JETT had
mistakenly parsed it as the beginning of a tag and thrown a
TagParseException. This is now parsed correctly.
- Ticket #71: Create a tag to set the value of a variable. JETT now has the new
set tag to assign a value to a variable in the
beans map.
- Ticket #74: The "findCellStyleWithFont" method didn't cache a font object if
the font was not found and a new one is created. Now it does cache it.
- Ticket #76: The "rows" and "cols" attributes on the
image tag had no effect and weren't working.
This is now fixed in JETT.
- Ticket #77: Performance issues, calling "copyColumnWidthsRight" when a
rightward looping tag is embedded in a downward looping tag. Now JETT will only
set column widths on the first iteration of the inner, rightward looping tag.
- Ticket #78: Extraneous blank cells created upon processing of nested
jt:forEach tags. The logic has been updated and now this has been
resolved.
- Ticket #79: Implicit Sheet cloning fails if the collection contains exactly
one element. There was an off-by-one error in the logic. This has been
resolved.
- Ticket #81: Add a "page break" tag. JETT now has the new
pageBreak tag
- Ticket #82: In JETT Formulas, a cell reference doesn't get updated unless there
is a space in front of punctuation/operators. The JETT formula parser has been
fixed to recognize the case of a new cell reference following a comma, a right
parenthesis, or a double-quote character.
- Ticket #85: Use a logging library instead of printing to System.err. JETT is
now using Log4J 2, version 2.9.0. Because Log4J 2 requires JDK 1.7, now JETT
requires at least JDK 1.7 as well.
- Ticket #86: Existing hyperlinks in a template spreadsheet are not shifted,
copied, or moved. JETT had ignored existing hyperlinks in a template
spreadsheet; now they are shifted, copied, and moved when appropriate.
- Ticket #87: Add an attribute evaluation method for non-negative doubles. Now
AttributeUtil has a method for validating that an attribute
contains a non-negative double value.
JETT 0.10.0 (Beta) Released - 05 May 2016
New in JETT 0.10.0:
- Ticket #56: Rich text strings using the "automatic" Excel color crashes JETT.
Now, JETT takes into account the "automatic" Excel color to avoid the crash.
- Ticket #57: Two or more levels of nested forEach tags with a JETT Formula that
refers to cells at least 2 levels deeper than the formula result in an
incorrect Excel formula. There was a problem in the algorithm that JETT relied
upon to keep track of cell updates across 2 or more levels of nested looping
tags. The formula nesting level is now kept track in the TagContext
object, and this bug is fixed.
- Ticket #58: A "<" character inside a JETT Formula triggers a
TagParseException when the TagParser attempts to
parse it as a tag. Now JETT skips over JETT Formula text when scanning cell
text looking for tags.
- Ticket #60: Excel 2007+ (.xlsx) templates with Excel comments in them cause
JETT to crash when it is cacheing pre-existing fonts when it first reads the
spreadsheet. An unexpected color index, 81, was outside the normal range of
Excel indexed colors, causing the crash. JETT now takes into account this
index to avoid the crash.
- Ticket #65: Using a lot of span tags, especially in a loop, causes an
IllegalStateException from Apache POI because the maximum number
of cell styles was exceeded. This was caused because JETT didn't cache the new
CellStyle objects, resulting in an excessive number of similar or
identical cell styles. The span tag is now caching any new cell styles it
creates, so it can find that same existing cell style later.
- Ticket #67: Create a tag that can supply a dynamic image to the resultant
spreadsheet. JETT now has the image tag.
- JETT is now tested using Apache POI 3.14. JETT now requires Apache POI 3.14
(or greater).
JETT 0.9.1 (Beta) Released - 28 Aug 2015
New in JETT 0.9.1:
- Ticket #43: Brackets [] messed up the parsing of JETT Formulas.
Now, JETT takes into account JETT formulas that have bracket characters
[], such as $[TEXT(39300.625, "[h]")]. Previously,
the internal ] character would be considered the end of the JETT
Formula incorrectly. Now it is recognized to be part of the formula.
- Ticket #44: Hide columns, rows, and entire sheets. This build introduces the
hideCols tag, the
hideRows tag, and the
hideSheet tag. All 3 tags take one required
attribute, test, with a boolean value, to determine whether to
hide (or show on false) the columns/rows in the tag body, or the
entire sheet.
- Ticket #45: When using the span tag, if a border
color on a .xls template spreadsheet uses the "normal" color, an
ArrayIndexOutOfBoundsException occurred during an internal lookup
on index 32767. When using a .xlsx spreadsheet, this error wasn't
seen. Now JETT considers this case and returns the appropriate color.
- Ticket #46: Using a span tag next to
implicit collections processing results
in the content below being shifted down too much. This was caused by two
independent blocks each determining that they needed to shift the below content
downward to make room for their own content. While implicit collections
processing has the "fixed" metadata key (and all looping tags also have their
"fixed" attribute), the span tag didn't have a "fixed" attribute. The span tag
now has the "fixed" attribute.
- Ticket #48: If a looping tag needs to shift content below the tag downward, but
that content consists solely of styling (no content), then that cell was not
recognized, and it wasn't shifted, resulting in it being overwritten. JETT now
recognizes style-only content and shifts it appropriately.
- Ticket #49: Introduce implicit sheet cloning.
A collection expression, e.g. ${orders.invoiceNbr} in a sheet
normally triggers implicit collections
processing. Now, if such an expression is encountered on the sheet name,
implicit sheet cloning takes place, with one resultant sheet per collection
item. Only a limited set of metadata keys are available, and they are
abbreviated due to the consideration of Excel's 31-character sheet name limit.
- Ticket #50: Include the option for a status variable on looping tags that
provides more information than the simple indexVar attribute. The
varStatus attribute is now supported on all
looping tags and as the varStatus
metadata key in implicit collections
processing. The value is the name of the status variable added to the
beans map. It supplies not just the current iteration index (0-based), but
also the first and last indices. The for tag's
varStatus
also supplies the start, end, and step values.
- Ticket #53: The internal cell style cache was incorrectly caching style
combinations that included a foreground color. This is now corrected.
- Ticket #54: Expose a setter for the "debug" property in the internal
JexlEngine that JETT uses. For some reason, "debug" is by default
true in the JexlEngine, but JEXL exposes this property via a
setter. JETT now allows control via a setter method in
ExcelTransformer.
- Ticket #55: Cache JEXL Expression objects. JETT now caches JEXL expression
objects, keyed by the expression text. This allows JETT to bypass JEXL parsing
when the expression has been encountered before. This is like a "soft parse"
that an Oracle database performs when it has seen query text before. This
should result in a performance boost, especially on transformations with loops
over large collections.
- JETT is now tested using Apache POI 3.12. JETT now requires Apache POI 3.12
(or greater).
JETT 0.9.0 (Beta) Released - 19 Dec 2014
New in JETT 0.9.0:
- Ticket #35: Include more detail on original cell locations on
TagParseExceptions. Now, TagParseException messages
include not just the location of the cell where the tag was encountered, but
also the original template location as well. Also included are the locations
of all tags the error tag was nested inside of, to promote the ease of locating
a tag error on a template spreadsheet.
- Ticket #36: The CommentTag threw a NullPointerException
when a null author was supplied. This tag class now uses
Attributetil to parse and evaluate its attribute values, which
throws the proper exception if a null is passed for the
"author" or the "comment" attributes.
- Ticket #38: NULLs from the database aren't respected when retrieved with JDBC
Execution. Now, JETT checks the database value for null using
wasNull(), so the proper null is stored in
ResultSetRow, JETT's class to store DB results for processing.
- Ticket #40: The ExpressionFactory internal class was a singleton,
but because it represents the interface to Apache Commons JEXL, it becomes a
bottleneck when reports are being generated concurrently. Now, the
ExpressionFactory is no longer a singleton; a new factory is now
owned by each new ExcelTransformer created, eliminating the
bottleneck.
- Ticket #41: A second newline character in a query string to be executed by the
JDBCExecutor causes an error. A previous bug fix had exposed this
bug, which had only replaced the first newline character it encountered. Now,
JETT will replace all newline characters it encounters with spaces.
- Ticket #42: Create an "ana" tag to utilize new jAgg 0.9.0 Analytics
functionality. The new Ana tag now provides
analytic function capability. JETT's dependency on jAgg has been updated to
require jAgg 0.9.0.
JETT 0.8.0 (Beta) Released - 31 Jul 2014
New in JETT 0.8.0:
- Ticket #21: Add more listener hooks to JETT execution. JETT already had
listeners for after cells were processed, after tags were processed, and after
a loop iteration of a looping tag was processed. Now, CellListener,
TagListener, and TagLoopListener each have new
"before" methods that will execute. Additionally, there is the new
SheetListener interface, with both "before" and "after" methods,
that triggers before and after a Sheet is transformed. Each
"before" method returns a boolean that controls whether the
relevant processing should continue.
- Ticket #22: Performance issues were reported after JETT 0.7.0 changed
AttributeUtil into AttributeEvaluator so that it
could carry the state necessary to report on which cell errors were found.
It has been changed back to AttributeUtil, with each static
utility method taking a TagContext as a parameter to supply the
necessary cell information.
- Ticket #23: There was a FormulaParser error when a JETT formula
contained a ranged cell reference such as "A10:A11". The FormulaParser
now recognizes the ":" character, so that each cell reference can be resolved
correctly.
- Ticket #25: JDBC Execution in a "forEach" tag with a "groupBy" attribute
results in an UnsupportedOperationException. JDBC Execution in
JETT relies on a get(String) method existing and being invoked in
an expression context. However, JETT utilizes
jAgg for the processing of the
"groupBy" attribute, which didn't recognize or search for get(String)
methods in a bean if the normal getProperty() method wasn't found.
JETT is now upgraded to use jAgg 0.8.1, which supplies this missing
functionality.
- Ticket #26: Allow expressions to be escaped so that they aren't evaluated.
JETT now allows the "$" character to be escaped, such that \${expression}
won't be evaluated. An unrelated bug was found and fixed when implementing the
changes for this ticket. If rich text formatting was applied to a cell that
contained identical expressions, then the formatting was messed up due to the
fact that all of the expressions were replaced at once, but the formatting was
applied only once. Now, all expressions are replaced individually, resulting
in rich text formatting being applied correctly.
- Ticket #29: JETT has slow performance when transforming sheets with lots of
merged regions. When there are a large number of merged regions in a sheet,
JETT, which relies on Apache POI for its access to the sheet's merged regions,
suffered large performance penalties. This occurred when attempting to process
large numbers of merged regions on .xlsx workbooks. As a workaround, JETT now
caches the merged regions present on the template sheet. It manipulates those
merged regions only in its own cache, and it applies them back to the sheet
after it has been transformed. This results in a big performance boost.
- Ticket #31: Add option to recalculate all formulas. JETT now has the options
to evaluate all formulas once transformation is done, with a new method in
ExcelTransformer: setEvaluateFormulas. It also can
control a flag in the workbook itself to force recalculation of formulas when
Excel opens the workbook, with another new method in
ExcelTransformer: setForceRecalculationOnOpening.
- Bug fix (Ticket #32): Implicit Collections
Processing breaks when a numeric cell is in the block of cells to be
processed. JETT had assumed that the cells in the block all had text, so
Apache POI threw an exception when a numeric cell was found. This occurs when
JETT is searching for collection expressions to be processed in "implicit
collections processing". Now, JETT ignores numeric cells for this purpose.
Also, the calculation of the leftmost and rightmost extent of the block was
wrong when exactly one of the metadata keys "right" and "left" was specified.
This has been fixed also.
- Ticket #33: Update JETT formulas when the sheet name changes, either due to
sheet cloning, sheet repositioning, or evaluating an expression located in the
sheet name. JETT didn't update JETT formula cell references on any of these
events, resulting in possible incorrect cell references or JETT simply not
replacing JETT formulas with an Excel formula at all. Now, JETT updates JETT
formula cell references on all these events.
- Ticket #34: Support the manipulation of existing named ranges. Before now,
JETT completely ignored named ranges. Now, if sheets are cloned, repositioned,
or renamed, any named ranges that were scoped to those sheets are re-scoped.
Also, the new Name tag in the standard library
lets the user supply a JETT formula to an existing named range, so that the
formula referred to by a named range can be changed dynamically during
transformation. This allows a chart that refers to named ranges for its data
ranges to have its data changed dynamically, even if it's indirectly, by
updating the existing named ranges.
JETT 0.7.0 (Beta) Released - 09 May 2014
New in JETT 0.7.0:
- Bug fix (Ticket #9): JETT formulas weren't being copied to the right correctly
when the ForEachTag had "copyRight" set to "true". The ForEachTag is now
properly copying formulas to the right when copyRight is set to "true".
- Bug fix (No ticket): Invalid formula reference replacement when reference is
found as a substring of another formula reference. E.g. A formula reference of
"A2", when being mapped to something like "A22", was being substituted in a formula
reference of "A21" to become "A221". Now JETT formulas will make sure that the
entire formula reference matches, not just a substring.
- Ticket #11: Support expressions in "groupBy" properties. JETT is now upgraded
to use jAgg 0.8.0, which supports nested properties. JETT uses jAgg to provide
aggregate expressions and grouping functionality. It still won't support
full expressions such as groupBy="created.year + ' ' + created.month",
but it will support nested properties such as groupBy="created.year".
- Bug fix (Ticket #12): A JETT formula referencing cells outside a ForEachTag
resulted in a NullPointerException. Previously, the code didn't
even consider this case. JETT now handles this case properly, walking out of
the looping tag looking for references in its translation map.
- Ticket #14: When transforming a template sheet into multiple cloned sheets,
allow template sheets and the cloned sheets to be listed in any order, not just
consecutively. E.g. template sheets can be specified as "A, B, A, B, A, B",
not just as "A, A, A, B, B, B".
- Bug fix (No ticket): When JETT clones a template sheet, the underlying Apache
POI library doesn't preserve all settings. Specifically, some Print Setup
settings are not preseved. JETT now compensates by storing the template sheet's
settings and restoring them on the newly cloned sheet.
- Ticket #15: Make ExcelTransformer's "createContext" method public,
which enables a caller to create and call a SheetTransformer
directly. This has been done.
- Bug fix (Ticket #16): Attribute references to non-existent beans result in an
evaluation of null, causing a NullPointerException in
AttributeUtil. AttributeUtil has been refactored
into AttributeEvaluator, and it now properly handles null
evaluations. It also references the appropriate cell when throwing validation
exceptions. Additional JUnit tests have been added for
AttributeEvaluator.
- Bug fix (Ticket #17): The "<>" Excel operator in a formula is being
interpreted as a tag, causing an error. Now, JETT won't interpret "<" as a
tag if it's followed by whitespace, a ">", another "<", or a "=".
- Ticket #20: Allow expressions to be evaluated in sheet names. JETT now
evaluates expressions in sheet names, and also in the header and footer.
- From Discussion: Allow "\n" characters in attribute values, specifically in
queries contained in JDBC Executor expressions. This is accomplished by
converting all carriage returns, line feeds, and tabs in attribute values to
space characters. To support such special characters, escaping in attribute
values has been expanded to include all Java escape characters:
\\ \' \" \b \f \n \r \t.
- From Discussion: Avoid removing all cell contents when taking a "past end
action" when looping over multiple collections at once, and one when of the
collections has been exhausted. JETT now supports a new "past end action",
replaceExpr, that indicates that any expression that references a
collection that is already exhausted will be replaced. Other content in the
cell will not be affected. The
MultiForEach tag now supports the
replaceExpr "past end action", along with a new attribute,
replaceValue, that specifies with what to replace these
expressions. The replacement value defaults to an empty string.
Correspondingly,
implicit collections processing now
supports the same feature.
JETT 0.6.0 (Beta) Released - 26 Nov 2013
New in JETT 0.6.0:
- JDBC Template Execution is here!
Create a JDBCExecutor, expose it
in the beans, and use it to execute SQL queries specified directly in the
template spreadsheet. Straight "select" statements are supported, and "select"
statements with JDBC "?" values are supported as well.
- Two new
transform
methods are added. These operate on an already created Workbook
object. Also, the existing transform methods that take an input
filename as a parameter no longer create the Workbook with a
FileInputStream; they use a File instead,
to save memory.
- Bug fix (Ticket #6): Unpaired double-quote in a cell value results in an
infinite loop in the TagParser. This has been fixed.
- Bug fix (Ticket #7): BigDecimals are not supported.
BigDecimals and BigIntegers are now supported. Their
values, when entered into a Cell, follow what Excel does when a
user enters large numbers. If the number can be expressed as a normal
double, then the cell will contain a numeric value, else it will
be interpreted as a String value.
JETT 0.5.2 (Beta) Released - 19 Jul 2013
New in JETT 0.5.2:
- Bug fix (Ticket #5): JETT now allows the inclusion of double-quote character in
tag attribute values. Normally a double-quote character delimits the beginning
and ending of an attribute value, but now JETT allows the escaping of the
double-quote character with a backslash: \" means a literal
", e.g. attr="\"Escape it!\", he said.". JETT also
allows the backslash character to escape itself: \\ means a
literal \, e.g. attr="C:\\Program Files\\Java\\".
- Bug fix (No ticket #): If Implicit Collections Processing is operating on a
collection, but a property elsewhere in an expression contained that collection
name as a substring (e.g. ${collection.collectionValue}, then JETT
had a problem with it. JETT now takes into account this case and processes it
correctly.
- Additional test cases have been added for the
comment tag concerning the comment's Excel
visibility.
JETT 0.5.1 (Beta) Released - 04 Mar 2013
New in JETT 0.5.1:
- Bug fix: When using the span tag, sometimes the
background of the Cell was accidentally set to "gray50percent", even if there
was no background color, foreground color, or fill pattern. This bug is now
fixed in 0.5.1.
JETT 0.5.0 (Beta) Released - 21 Feb 2013
New in JETT 0.5.0:
- The style tag has a new attribute: "class" for
assigning styles to a block of cells defined in a ".css" file, which is very
much like a CSS file in web design.
- If the style tag is used extensively, then JETT's
performance suffers. Now, JETT maintains caches for styles and fonts used,
for easy, fast lookup and reuse.
- Additional test cases have been added to the JUnit test case that tests the
hyperlink tag.
- Bug fix: When cell borders were used in the same cell as a
span tag, the borders were not changed to match
the new merged region. Now, the borders are changed to match the new merged
region.
- Bug fix: When an expression contains the method call "size()" on a collection,
JETT didn't properly recognize that the collection expression shouldn't be
processed with implicit collections
processing, i.e. one block for every collection item. Now JETT properly
recognizes the "size()" method on a collection and doesn't perform implicit
collections processing in this case.
JETT 0.4.0 (Beta) Released - 07 Dec 2012
New in JETT 0.4.0:
- New tag: "style" to dynamically change the style
on the Cells in the body of the tag, e.g.
<jt:style style="font-weight: bold;font-height-in-points: 20">${expr}</jt:style>.
- New tag: "formula" to dynamically create Excel
formulas unaffected by JETT formula processing.
- New attributes on the "agg" tag to support rollups,
cubes, and grouping sets.
- New attribute on the "span" tag to make an
adjustment to the size of a merged region, adding a number to the size.
- A new POI bean is exposed: "cell" that represents the Cell that
contains the expression.
- One can now reference static Java methods in JEXL directly, e.g.
${java.lang.String.format("%d / %d", numerator, denominator)}
- New JETT functionality presented as registered functions, e.g.
${jett:cellRef(1, 2)} => "C2", and
${jett:cellRef(1, 2, 2, 2)} => "C2:D3".
- Bug fix: If an expression was repeated more than once, and is present with
other expresssions in a Cell, then the value replacement wasn't working right.
This is now fixed.
- Bug fix: Boolean values were being populated as the strings "true" and "false".
Now they are properly populated as the Excel boolean values TRUE and
FALSE. Boolean expressions within strings will still yield "true"
and "false".
- Lots of JUnit test cases have been added for all the new features.
- There is a new "readme.txt" file.
JETT 0.3.0 (Beta) Released - 26 Sep 2012
New in JETT 0.3.0:
- TagListeners may now be created, which get called when any tag
is finished processing. All Tags that subclass BaseTag
now support the onProcessed attribute for specifying
TagListeners.
- TagLoopListeners may now be created, which get called when every
loop of a looping tag (Tags that subclass BaseLoopTag)
is finished processing. All Tags that subclass
BaseLoopTag now support the onLoopProcessed attribute for
specifying TagLoopListeners.
- There are 2 new attributes for forEach tags:
- groupBy supports separating the collection into separate
groups with identical properties for further processing.
- orderBy supports ordering the collection items before
displaying them.
- For Implicit Collections Processing,
4 additional metadata keys are added:
- indexVar supports a zero-based looping variable name that
works just like the same-named attribute on the
multiForEach tag.
- limit supports a limit to the number of collection items
processed that works like the same-named attribute on the
multiForEach tag.
- onProcessed supports TagListeners just the same
as all BaseTags do.
- onLoopProcessed supports TagLoopListeners just
the same as all looping tags do.
- A bug was fixed in Formulas processing. If a JETT formula is specified in
the middle of a Cell's text, because tag text preceded it, JETT will no longer
throw an uncaught Exception.
- Lots of JUnit test cases have been added for all the new features.
- This is the first JETT release to be submitted to the Sonatype OSS Maven
Repository, which will make JETT available in the Maven Central Repository.
JETT 0.2.0 (Beta) Released - 08 Aug 2012
New in JETT 0.2.0:
- New tags: "comment" to create Excel Comments on
Cells, "group" to define Excel Groups (Outlines), and
"hyperlink" to create Hyperlinks on Cells.
- It is now possible to create Excel Groups (Outlines) on dynamically placed data
using looping tags such as the
forEach tag. It is also possible to specify new
metadata to create Excel Groups using Implicit
Collections Processing.
- JETT has supported Rich Text using Expressions, but now it supports Rich Text
inside certain appropriate tag attributes that are used as actual Cell contents.
- It is now possible to supply custom functions
into a custom JEXL namespace, which can result in such Expressions as
${custom:method(param)}.
- Additional convenience "transform" methods in the ExcelTransformer
class allow the developer to specify input and output filenames, and to let JETT
handle the reading and writing of the Excel files.
- Lots of JUnit test cases have been added for all the new features, and for lots
of old features that needed them.
- Two bugs are fixed relating to JETT Formulas. One bug did not pick up the cell
reference if it was at the end of the JETT Formula, and another bug did not allow
negative default values to be supplied in a formula cell reference. Both bugs are
now fixed.
JETT 0.1.0 (Beta) Released - 20 Jul 2012
This is the initial release of JETT.