You have successfully intrigued my interest!
I was a java major in college and since Clarity in java based I nerd out when somebody does stuff like you are!
Your way will be a great way to create some excel documents quickly.
This is when I began to think of another way somebody could do this. Since we also have on demand clients, I like to try to make things cross compatible for onDemand/onPremise.
Clarity uses Apache POI, which is Java's api for Microsoft Documents. This is how they create all exports to microsoft doc's.
Using only what Clarity gives you on initial install (works for onDemand) I have figured out a way to create excel docs just as Clarity does.
This example will end up looking like this:
This is the EXACT output that the script below sends you.
Things to note: A & B, C & D are merged. Total and Average fields are formulas and will come over as such.
NOTICE: This is just a proof of concept, nothing more. I have not optimized it completely yet. You will notice i do things one way for some things, and another for others. This is because I try different things to see what works best.
This is my first attempt at using this library so sorry if its hard to understand.
<gel:script xmlns:core="jelly:core"
xmlns:util="jelly:util"
xmlns:x="jelly:xml"
xmlns:gel="jelly:com.niku.union.gel.GELTagLibrary"
xmlns:sql="jelly:sql"
xmlns:soap="jelly:com.niku.union.gel.SOAPTagLibrary"
xmlns:xog="http://www.niku.com/xog"
xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:email="jelly:email"
xmlns:file="jelly:com.niku.union.gel.FileTagLibrary">
<!--Create Workbook-->
<core:new className="org.apache.poi.hssf.usermodel.HSSFWorkbook" var="wb"/>
<!--Create Sheet-->
<core:invoke method="createSheet" on="${wb}" var="sheet">
<core:arg type="java.lang.String" value="First Sheet"/>
</core:invoke>
<!--Create 7 Rows-->
<core:set value="0" var="rowNum"/>
<core:while test="${rowNum!=7}">
<core:invoke method="createRow" on="${sheet}" var="row${rowNum+1}">
<core:arg type="java.lang.Integer" value="${rowNum}"/>
</core:invoke>
<core:set value="${rowNum+1}" var="rowNum"/>
</core:while>
<!--Create Bold Style-->
<core:invoke method="createCellStyle" on="${wb}" var="style"/>
<core:invoke method="createFont" on="${wb}" var="font"/>
<core:invoke method="setBoldweight" on="${font}">
<core:arg type="java.lang.Short" value="700"/>
</core:invoke>
<core:invoke method="setFont" on="${style}">
<core:arg type="org.apache.poi.hssf.usermodel.HSSFFont" value="${font}"/>
</core:invoke>
<!--Create Row1 Col1-->
<core:invoke method="createCell" on="${row1}" var="r1c1">
<core:arg type="java.lang.Integer" value="0"/>
</core:invoke>
<core:invoke method="setCellValue" on="${r1c1}">
<core:arg type="java.lang.String" value="Resource Name"/>
</core:invoke>
<!--Bold Row1 Col1-->
<core:invoke method="setCellStyle" on="${r1c1}">
<core:arg type="org.apache.poi.hssf.usermodel.HSSFCellStyle" value="${style}"/>
</core:invoke>
<!--Merge A and B in Row 1-->
<!--rowFrom,rowTo,colFrom,colTo-->
<core:new className="org.apache.poi.hssf.util.CellRangeAddress" var="cellRangeAddress1">
<core:arg type="java.lang.Integer" value="0"/>
<core:arg type="java.lang.Integer" value="0"/>
<core:arg type="java.lang.Integer" value="0"/>
<core:arg type="java.lang.Integer" value="1"/>
</core:new>
<core:invoke method="addMergedRegion" on="${sheet}">
<core:arg type="org.apache.poi.hssf.util.CellRangeAddress" value="${cellRangeAddress1}"/>
</core:invoke>
<!--Create Row1 Col3-->
<core:invoke method="createCell" on="${row1}" var="r1c3">
<core:arg type="java.lang.Integer" value="2"/>
</core:invoke>
<core:invoke method="setCellValue" on="${r1c3}">
<core:arg type="java.lang.String" value="Salary"/>
</core:invoke>
<!--Bold Row1 Col3-->
<core:invoke method="setCellStyle" on="${r1c3}">
<core:arg type="org.apache.poi.hssf.usermodel.HSSFCellStyle" value="${style}"/>
</core:invoke>
<!--Merge C and D in Row 1-->
<!--rowFrom,rowTo,colFrom,colTo-->
<core:new className="org.apache.poi.hssf.util.CellRangeAddress" var="cellRangeAddress2">
<core:arg type="java.lang.Integer" value="0"/>
<core:arg type="java.lang.Integer" value="0"/>
<core:arg type="java.lang.Integer" value="2"/>
<core:arg type="java.lang.Integer" value="3"/>
</core:new>
<core:invoke method="addMergedRegion" on="${sheet}">
<core:arg type="org.apache.poi.hssf.util.CellRangeAddress" value="${cellRangeAddress2}"/>
</core:invoke>
<!--Create Second Row: First, Last, 2013,2014-->
<core:invoke method="createCell" on="${row2}" var="r2c1">
<core:arg type="java.lang.Integer" value="0"/>
</core:invoke>
<core:invoke method="setCellValue" on="${r2c1}">
<core:arg type="java.lang.String" value="First"/>
</core:invoke>
<core:invoke method="setCellStyle" on="${r2c1}">
<core:arg type="org.apache.poi.hssf.usermodel.HSSFCellStyle" value="${style}"/>
</core:invoke>
<core:invoke method="createCell" on="${row2}" var="r2c2">
<core:arg type="java.lang.Integer" value="1"/>
</core:invoke>
<core:invoke method="setCellValue" on="${r2c2}">
<core:arg type="java.lang.String" value="Last"/>
</core:invoke>
<core:invoke method="setCellStyle" on="${r2c2}">
<core:arg type="org.apache.poi.hssf.usermodel.HSSFCellStyle" value="${style}"/>
</core:invoke>
<core:invoke method="createCell" on="${row2}" var="r2c3">
<core:arg type="java.lang.Integer" value="2"/>
</core:invoke>
<core:invoke method="setCellValue" on="${r2c3}">
<core:arg type="java.lang.String" value="2013"/>
</core:invoke>
<core:invoke method="setCellStyle" on="${r2c3}">
<core:arg type="org.apache.poi.hssf.usermodel.HSSFCellStyle" value="${style}"/>
</core:invoke>
<core:invoke method="createCell" on="${row2}" var="r2c4">
<core:arg type="java.lang.Integer" value="3"/>
</core:invoke>
<core:invoke method="setCellValue" on="${r2c4}">
<core:arg type="java.lang.String" value="2014"/>
</core:invoke>
<core:invoke method="setCellStyle" on="${r2c4}">
<core:arg type="org.apache.poi.hssf.usermodel.HSSFCellStyle" value="${style}"/>
</core:invoke>
<!--Peter Griffin Row-->
<core:invoke method="split" on="Peter,Griffin,87000,90000" var="peter">
<core:arg type="java.lang.String" value=","/>
</core:invoke>
<core:set value="0" var="peterRow"/>
<core:forEach items="${peter}" var="peterPart">
<core:invoke method="createCell" on="${row3}" var="r">
<core:arg type="java.lang.Integer" value="${peterRow}"/>
</core:invoke>
<core:if test="${peterPart.matches("^[0-9]+$") == true}">
<core:invokeStatic className="java.lang.Integer" method="parseInt" var="cellNumeric">
<core:arg type="java.lang.String" value="${peterPart}"/>
</core:invokeStatic>
<core:set value="${r.setCellValue(cellNumeric)}" var="setCell"/>
</core:if>
<core:if test="${peterPart.matches("^[0-9]+$") != true}">
<core:set value="${r.setCellValue(peterPart)}" var="setCell"/>
</core:if>
<core:set value="${peterRow+1}" var="peterRow"/>
</core:forEach>
<!--Lois Griffin Row-->
<core:invoke method="split" on="Lois,Griffin,60000,65000" var="lois">
<core:arg type="java.lang.String" value=","/>
</core:invoke>
<core:set value="0" var="loisRow"/>
<core:forEach items="${lois}" var="loisPart">
<core:invoke method="createCell" on="${row4}" var="r">
<core:arg type="java.lang.Integer" value="${loisRow}"/>
</core:invoke>
<core:if test="${loisPart.matches("^[0-9]+$") == true}">
<core:invokeStatic className="java.lang.Integer" method="parseInt" var="cellNumeric">
<core:arg type="java.lang.String" value="${loisPart}"/>
</core:invokeStatic>
<core:set value="${r.setCellValue(cellNumeric)}" var="setCell"/>
</core:if>
<core:if test="${loisPart.matches("^[0-9]+$") != true}">
<core:set value="${r.setCellValue(loisPart)}" var="setCell"/>
</core:if>
<core:set value="${loisRow+1}" var="loisRow"/>
</core:forEach>
<!--Chris Griffin Row-->
<core:invoke method="split" on="Chris,Griffin,5000,5250" var="chris">
<core:arg type="java.lang.String" value=","/>
</core:invoke>
<core:set value="0" var="chrisRow"/>
<core:forEach items="${chris}" var="chrisPart">
<core:invoke method="createCell" on="${row5}" var="r">
<core:arg type="java.lang.Integer" value="${chrisRow}"/>
</core:invoke>
<core:if test="${chrisPart.matches("^[0-9]+$") == true}">
<core:invokeStatic className="java.lang.Integer" method="parseInt" var="cellNumeric">
<core:arg type="java.lang.String" value="${chrisPart}"/>
</core:invokeStatic>
<core:set value="${r.setCellValue(cellNumeric)}" var="setCell"/>
</core:if>
<core:if test="${chrisPart.matches("^[0-9]+$") != true}">
<core:set value="${r.setCellValue(chrisPart)}" var="setCell"/>
</core:if>
<core:set value="${chrisRow+1}" var="chrisRow"/>
</core:forEach>
<!--Create Total Label-->
<core:invoke method="createCell" on="${row6}" var="r1c1">
<core:arg type="java.lang.Integer" value="1"/>
</core:invoke>
<core:invoke method="setCellValue" on="${r1c1}">
<core:arg type="java.lang.String" value="Total"/>
</core:invoke>
<!--Bold Total Label-->
<core:invoke method="setCellStyle" on="${r1c1}">
<core:arg type="org.apache.poi.hssf.usermodel.HSSFCellStyle" value="${style}"/>
</core:invoke>
<!-- Create Total Formula Cell 2013-->
<core:invoke method="createCell" on="${row6}" var="r6c2">
<core:arg type="java.lang.Integer" value="2"/>
</core:invoke>
<core:invoke method="setCellType" on="${r6c2}">
<core:arg type="java.lang.Integer" value="2"/>
</core:invoke>
<core:invoke method="setCellFormula" on="${r6c2}">
<core:arg type="java.lang.String" value="SUM(C3:C5)"/>
</core:invoke>
<!-- Create Total Formula Cell 2014-->
<core:invoke method="createCell" on="${row6}" var="r6c3">
<core:arg type="java.lang.Integer" value="3"/>
</core:invoke>
<core:invoke method="setCellType" on="${r6c3}">
<core:arg type="java.lang.Integer" value="2"/>
</core:invoke>
<core:invoke method="setCellFormula" on="${r6c3}">
<core:arg type="java.lang.String" value="SUM(D3:D5)"/>
</core:invoke>
<!--Create Average Label-->
<core:invoke method="createCell" on="${row7}" var="r1c1">
<core:arg type="java.lang.Integer" value="1"/>
</core:invoke>
<core:invoke method="setCellValue" on="${r1c1}">
<core:arg type="java.lang.String" value="Average"/>
</core:invoke>
<!--Bold Total Label-->
<core:invoke method="setCellStyle" on="${r1c1}">
<core:arg type="org.apache.poi.hssf.usermodel.HSSFCellStyle" value="${style}"/>
</core:invoke>
<!-- Create Average Formula Cell 2013-->
<core:invoke method="createCell" on="${row7}" var="r7c2">
<core:arg type="java.lang.Integer" value="2"/>
</core:invoke>
<core:invoke method="setCellType" on="${r7c2}">
<core:arg type="java.lang.Integer" value="2"/>
</core:invoke>
<core:invoke method="setCellFormula" on="${r7c2}">
<core:arg type="java.lang.String" value="AVERAGE(C3:C5)"/>
</core:invoke>
<!-- Create Average Formula Cell 2014-->
<core:invoke method="createCell" on="${row7}" var="r7c3">
<core:arg type="java.lang.Integer" value="3"/>
</core:invoke>
<core:invoke method="setCellType" on="${r7c3}">
<core:arg type="java.lang.Integer" value="2"/>
</core:invoke>
<core:invoke method="setCellFormula" on="${r7c3}">
<core:arg type="java.lang.String" value="AVERAGE(D3:D5)"/>
</core:invoke>
<!--Find Niku Home Location-->
<core:invokeStatic className="java.lang.System" method="getenv" var="NIKU_HOME">
<core:arg value="NIKU_HOME"/>
</core:invokeStatic>
<!--Create Output Stream To File-->
<core:new className="java.io.FileOutputStream" var="fileOut">
<core:arg type="java.lang.String" value="${NIKU_HOME}/Files/createExcel.xls"/>
</core:new>
<!--Write Workbook To File Using Output Stream-->
<core:invoke method="write" on="${wb}">
<core:arg type="java.io.FileOutputStream" value="${fileOut}"/>
</core:invoke>
<!--Close File Output Stream-->
<core:invoke method="close" on="${fileOut}"/>
<!--Change Save Folder to one on your server that your allowed to use...-->
<email:email to="email@email.com" from="clarity@emil.com" subject="Excel File Attached." server="PUT_SMTP_SERVER_HERE" attach="${NIKU_HOME}/Files/createExcel.xls">
Excel Document Attached.
</email:email>
</gel:script>
Hope you find this as fun/interesting as I do!
~Chris