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.