Tag Listeners

For finer control over the content and formatting of the resultant spreadsheet cells, JETT allows the user to create TagListener objects that are notified every time a tag's block has been processed. Tags that are not processed do not notify their TagListener object. This may occur, for example, if an "if" tag has its block removed due to a false condition, or if a looping tag processes an empty collection and its block is removed. Any object that implements the TagListener interface may be supplied in the onProcessed attribute of any Tag that subclasses BaseTag, as all JETT built-in tags do. The TagListener interface contains two methods:

public boolean beforeTagProcessed(TagEvent event);
public void onTagProcessed(TagEvent event);

Specify a TagListener object or a fully-qualified TagListener class name with a Tag. If a fully-qualified class name is supplied, then that class must have a public, no-argument constructor.

<jt:if test="${condition}" then="${trueValue}" onProcessed="${myTagListener}"/>


<jt:if test="${condition}" then="${trueValue}" onProcessed="com.mycompany.myproject.CustomTagListener"/>

Before a Tag is processed, if it has a TagListener, then it creates a TagEvent and calls its TagListener's beforeTagProcessed method. If it returns true, then the tag is processed as normal. If it returns false, then the Tag is not processed.

When a Tag is processed, and it has a TagListener, then it creates a TagEvent and calls its TagListener's onTagProcessed method.

A TagListener can retrieve context information by retrieving properties of the TagEvent.

Sheet sheet = event.getSheet();
Map<String, Object> beans = event.getBeans();
Block block = event.getBlock();
int left = block.getLeftColNum();
int right = block.getRightColNum();
int top = block.getTopRowNum();
int bottom = block.getBottomRowNum();

The Sheet is a reference to the POI Sheet object representing the actual sheet in the spreadsheet. The Map object is a reference to the beans map. It may have extra beans added, if the Tag is a "forEach" tag, or for that matter, any tag that adds values to the beans map. The Block is an object that represents the block of Cells affected by this tag. It has properties for the left and right column numbers (0-based), and the top and bottom row numbers (0-based). The Sheet object can be used to get POI Row objects, and POI Row objects can be used to get POI Cell objects, which can then be manipulated. It can also be used to obtain the POI Workbook object.


A TagListener can be created to affect the formatting of data within a block of cells.

This TagListener will change the font of all its cells to bold. It uses POI objects and functionality to change the font of all cells in the block.

public void onTagProcessed(TagEvent event)
   Block block = event.getBlock();
   Sheet sheet = event.getSheet();
   for (int r = block.getTopRowNum(); r <= block.getBottomRowNum(); r++)
      Row row = sheet.getRow(r);
      if (row != null)
         for (int c = block.getLeftColNum(); c <= block.getRightColNum(); c++)
            Cell cell = row.getCell(c);
            if (cell != null)
               Workbook workbook = sheet.getWorkbook();
               CellStyle style = cell.getCellStyle();
               short fontIdx = style.getFontIndex();
               Font font = workbook.getFontAt(fontIdx);
               if (font.getBoldweight() != Font.BOLDWEIGHT_BOLD)
                  Font boldFont = workbook.findFont(Font.BOLDWEIGHT_BOLD, font.getColor(), font.getFontHeight(),
                     font.getFontName(), font.getItalic(), font.getStrikeout(), font.getTypeOffset(),
                  CellStyle newStyle = workbook.createCellStyle();
                  if (boldFont == null)
                     boldFont = workbook.createFont();

This example uses a forEach tag to process the "employees" collection.

Employee Salary Manager
<jt:forEach items="${employees}" var="employee" onProcessed="${myTagListener}">${employee.lastName}, ${employee.firstName} ${employee.salary} <jt:if test="${employee.getManager() != null}" then="${employee.manager.lastName}, ${employee.manager.firstName}"/></jt:forEach>

...gets transformed into...

Employee Salary Manager
Stack, Robert $1000.00  
Queue, Suzie $900.00 Stack, Robert
Fudd, Elmer $800.00 Stack, Robert
Bunny, Bugs $1500.00