CFSpreadsheet in cfscript. The hard way

I needed a quick and dirty way of converting uploaded Excel files to query objects, using values from the first row as column names. CFSpreadsheet is a very pretty tag that allows for various Excel manipulations but it is still unavailable in cfscript and I prefer to keep my components tag-free. After some tinkering with cfscript SpreadsheetRead() method I came with the following solution:

public Query function ExcelToQuery( required String fileNameStr ){
   var xlsObj = SpreadsheetRead( arguments.fileNameStr ); 	
   /* Extract the workbook object from the spreadsheet */
   var workbookObj = xlsObj.getWorkBook();
   var sheetIndex = workbookObj.getActiveSheetIndex();
   /* Extract the sheet */
   var sheetObj = workbookObj.getSheetAt( sheetIndex );
   /* Extract column names (values in the first row in Excel sheet) */
   var rowObj = sheetObj.getRow(0);
   var columnList = "";
   for (headerCellIdx=0; headerCellIdx < rowObj.getLastCellNum(); headerCellIdx++) {
       var headerCellObj = rowObj.getCell(headerCellIdx);
       var headerCellValue = headerCellObj.getRichStringCellValue().getString();
           columnList = ListAppend(columnList,headerCellValue);
    /* Create new query object */
    var outputQry = QueryNew(columnList);
    /* Fetch the DateUtil object (POI), we'll need it later */
    var DateUtilObj = createObject("java","org.apache.poi.hssf.usermodel.HSSFDateUtil");
    /* Loop through the sheet. Mind that the iterator starts with 0 as we are using a Java method
       but we ignore the data from the first row as it contains column labels!  */ 
    for (rowIdx=1; rowIdx < sheetObj.getLastRowNum(); rowIdx++) {
        /* Extract row */	
        var rowObj = sheetObj.getRow(rowIdx);
        /* Add a new row to the query */
        /* Extract cell and pass it to the query */
        for (cellIdx=0; cellIdx < rowObj.getLastCellNum(); cellIdx++) {
            var cellObj = rowObj.getCell(cellIdx);
	    var cellValue = "";	
	    /* Please note that I ignore cellTypes CELL_TYPE_ERROR, CELL_TYPE_FORMULA and CELL_TYPE_BLANK as they are not relevant to me. Add your own handlers if you need them */		
	    if (cellObj.getCellType() eq cellObj.CELL_TYPE_STRING) {
	        cellValue = cellObj.getStringCellValue().toString();
	    } else if (cellObj.getCellType() eq cellObj.CELL_TYPE_BOOLEAN) {
		cellValue = cellObj.getBooleanCellValue();
	    } else if (cellObj.getCellType() eq cellObj.CELL_TYPE_NUMERIC) {
		if (DateUtilObj.isCellDateFormatted(cellObj)) {
		    cellValue = cellObj.getDateCellValue();
		} else {
		    cellValue = cellObj.getNumericCellValue();	
        /* Set query cell to the spreadsheet cell value. Mind the iterators! Coldfusion starts with 1 */
	QuerySetCell(outputQry, ListGetAt(columnList,cellIdx+1), cellValue,rowIdx );
    return outputQry;

Dumping method objects such as cellObj, rowObj, sheetObj etc and exploring underlying methods is quite amusing en zich. Have fun!