Solved

ColdFusion How can I add a calculated field to my excel export function?

Posted on 2014-03-18
9
775 Views
Last Modified: 2014-03-21
I have two fields in my excel export:
Qty Ordered & Qty Received

How can I automatically create another column "Amount Missing" with the formula:
Qty Ordered minus Qty Received = Amount Missing

Excel Export Code:

<cfif structKeyExists(FORM, "export") AND structKeyExists(VARIABLES, "Results")>

	<cfset sObj = SpreadsheetNew("Ship=#discipline1#")>
     <!--- create query param strings ----> 
    <cfset querySummary = "Ship = #discipline1#, Project = #discipline4#, Contract = #discipline7#, Records Found ("& Results.RecordCount &")">
    <cfset recordsSummary = "("& Results.RecordCount &") Records Found">

    <!--- add query parmas in 1st row and center align --->
    <cfset columnsInQuery = listLen(results.columnList)>
    <cfset SpreadsheetMergeCells(sObj, 1, 1, 1, columnsInQuery)>
    <cfset SpreadSheetSetCellValue(sObj, querySummary, 1, 1)>
    <cfset SpreadsheetFormatRow(sObj, {alignment="center"}, 1)> 

    <!--- add record count in 2nd row and center align --->
   <!--- <cfset SpreadsheetMergeCells(sObj, 2, 2, 1, columnsInQuery)>
    <cfset SpreadSheetSetCellValue(sObj, recordsSummary, 2, 1)>
    <cfset SpreadsheetFormatRow(sObj, {alignment="center"}, 2)> --->
  	<!--- Create header row --->
    <!--- <cfset spreadsheetSetHeader(SObj,"","Material Status Report","")>--->
	<cfset SpreadsheetAddRow(sObj, "Num,ISP,QTY Ordered,QTY REC,I,Part Description,S,Q,Num,,DO,hip,ject")>
      <cfset SpreadsheetFormatRows(sObj, {bold=TRUE,fgcolor="grey_25_percent", alignment="center"},1 )> 
      <cfset SpreadsheetFormatRow(sObj, {bold=TRUE,fgcolor="light_yellow", alignment="center"},2 )> 
   <cfset SpreadsheetFormatColumn(sObj, {alignment="right", dataformat="mm/dd/yyyy"}, 15)>
     <cfset SpreadsheetAddRows(sObj, Results)>
     <cfset SpreadsheetFormatColumns(sObj, {fontsize="14",verticalalignment = "vertical_center",leftborder="thin",rightborder="thin",bottomborder="thin"},"1-13")>
   
   <cfset SpreadsheetFormatColumns(sObj, {alignment="center"}, "1-4")>
   
   <cfset SpreadSheetSetColumnWidth(sObj, 3, 3)> 
<cfset SpreadsheetFormatCell(sObj, {textwrap=true,verticalalignment = "vertical_justify"}, 2, 3)>
<cfset cellValue = "QTY"& chr(10) & "REQ"& chr(10) >
<cfset SpreadsheetSetCellValue(sObj, cellValue, 2, 3)>
   
    <cfset SpreadSheetSetColumnWidth(sObj, 3, 4)> 
<cfset SpreadsheetFormatCell(sObj, {textwrap=true,verticalalignment = "vertical_justify"}, 2, 4)>
<cfset cellValue = "QTY"& chr(10) & "REC"& chr(10) >
<cfset SpreadsheetSetCellValue(sObj, cellValue, 2, 4)>
   
     <cfset SpreadsheetSetRowHeight(sObj,1, (40))>
     
     <cfset SpreadsheetFormatCell(sObj, {textwrap=true}, 2, 3)>
  <cfset SpreadSheetSetColumnWidth(sObj, 3, 3)>
     
     <cfset maxRow = Results.recordCount +  (2)>
     <cfloop from="1" to="#maxRow#" index="rowNum">
         <cfset SpreadsheetSetRowHeight(sObj, rowNum, (40))>
     </cfloop>
     
      <cfset SpreadsheetFormatRow(sObj, {topborder="thin"},3)>
     
   <cfset SpreadsheetFormatColumn(sObj, {alignment="left", dataformat="mm/dd/yyyy"}, 14)>
     <!--- file name MUST be unique --->
     <cfset saveToFile = "C:\Report#createUUID()#.xls">
     
     <!--- get the underlying poi sheet --->
     <cfset poiSheet = sObj.getWorkBook().getSheet("Ship=#discipline1#")>
     <cfset ps = poiSheet.getPrintSetup()>
     <cfset ps.setLandscape(true)>
     <cfset poiSheet.setAutobreaks(true)>
     
     
    <!--- Fit to an 8" wide page...for a small level of auto formatting pre-Excel... this could be made dynamic for different paper sizes--->

   <cfset ps.setFitHeight(javacast("short", 200))>
   <cfset ps.setFitWidth(javacast("short", 1))>
   <cfset poisheet.setMargin(POISheet.TopMargin,.10)>
   <cfset poisheet.setMargin(POISheet.BottomMargin,.10)>
   <cfset poisheet.setMargin(POISheet.LeftMargin, .10)>
   <cfset poisheet.setMargin(POISheet.RightMargin,.10)>

     
     
     
     <cfspreadsheet action="write" name="sObj" filename="#saveToFile#" overwrite="true">

     <cfheader name="Content-Disposition" value="inline; filename=Report.xls">
     <cfcontent type="application/excel" file="#saveToFile#" deletefile="yes">
     <!---- we're finished so exit --->
     <cfabort />
</cfif>

Open in new window

0
Comment
Question by:DJPr0
  • 5
  • 4
9 Comments
 
LVL 4

Expert Comment

by:Rodrigo Munera
ID: 39940221
To create the new column, you have to create it into your original query, or in the header row if the column will be at the end of the data.

Once you have the column, and you have populated your entire spreadsheet with your data, You have to put the formula in each cell.

In my code below I'm adding 2 formulas to 2 separate rows, I start from the second row, so my code will skip the header row and start inserting the formula in the second row of the spreadsheet, and I'm setting the "to" field to record count of my query +1 (to account for the header row being skipped)

In the code below "qReturn" is my query object with the data that was passed to the spreadsheet, "sprObj" is the spreadsheet object, my formulas are "IF(H[row]=0,0,I[row]/H[row])" and "IF(H[row]=0,0,J[row]/H[row])".

The syntax for entering a function into a spreadsheet is https://wikidocs.adobe.com/wiki/display/coldfusionen/SpreadsheetSetCellFormula

<cfloop from="2" to="#qReturn.recordcount+1#" index="i">
	<cfset SpreadSheetSetCellFormula(sprObj,"IF(H#i#=0,0,I#i#/H#i#)",i,12)>
	<cfset SpreadSheetSetCellFormula(sprObj,"IF(H#i#=0,0,J#i#/H#i#)",i,13)>
</cfloop>

Open in new window

0
 
LVL 4

Expert Comment

by:Rodrigo Munera
ID: 39940224
I use that loop after I've populated my spreadsheet object with
SpreadsheetAddRows(sprObj,qReturn);

Open in new window

0
 

Author Comment

by:DJPr0
ID: 39940838
Thanks for the reply Rodrigo.

I need some help with the formula:

If column 3 and 4 has a number, perform a minus calculation and output on column 5

Qty Ordered - Qty Received = Qty Missing  (Calculation is performed on each row)
       10                      5                     5
0
 
LVL 4

Assisted Solution

by:Rodrigo Munera
Rodrigo Munera earned 500 total points
ID: 39940912
Excel formulas are based on the rows and columns where your data resides.

For this example, I'm going to assume:
Qty Ordered is on Column A
Qty Received is on Column B
Qty Missing is on Column C (the position of this column is 3)

Your formula in excel "=IF(AND(ISNUMBER(A1),ISNUMBER(B1)),A1-B1,0)"
In Coldfusion you don't use the "=" at the beginning of the formula, so you would put your formula as: "IF(AND(ISNUMBER(A1),ISNUMBER(B1)),A1-B1,0)"
Also, you want to replace the hard-coded rows with variables


<cfloop from="2" to="#qReturn.recordcount+1#" index="i">
	<cfset SpreadSheetSetCellFormula(sprObj,"IF(AND(ISNUMBER(A#i#),ISNUMBER(B#i#)),A#i#-B#i#,0)",i,3)>
</cfloop>

Open in new window

0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 4

Expert Comment

by:Rodrigo Munera
ID: 39940920
Just to clarify, the formulas are not being calculated by coldFusion, cold fusion is only putting the formula in your spreadsheet (I'm assuming your user will have excel), and the actual calculation is made by the spreadsheet once it is opened by the user.
0
 

Author Comment

by:DJPr0
ID: 39941221
The formula seems to be downloading to the excel sheet ; )

Formula in excel sheet:
=IF(AND(ISNUMBER(C3),ISNUMBER(D3)),C3-D3,)

Problem:
All fields have 0

If I put the cursor in the formula and press enter the formula/calculation works.

I tried saving then opening without success - does something need to trigger the formula when the excel sheet opens?
0
 
LVL 4

Accepted Solution

by:
Rodrigo Munera earned 500 total points
ID: 39941238
Hmm, that seems to be an excel question. In my spreadsheets the formula loads when I open it, but I'm also not using that number of functions. You could try stripping the formula down to just "C[row]-D[row]" and see if that does the trick.
0
 

Author Comment

by:DJPr0
ID: 39941320
Yes, If I strip it down it calculates the one with numbers in both cells and gives me an error with no value:

<cfset SpreadSheetSetCellFormula(sObj,"IF(ISNUMBER(C#i#),C#i#-D#i#, )",i,5)>

Strip down version works fine since one column always has a number.
0
 

Author Closing Comment

by:DJPr0
ID: 39944999
Thanks for your assistance Rodrigo Munera!
0

Featured Post

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

In a multiple monitor setup, if you don't want to use AutoCenter to position your popup forms, you have a problem: where will they appear?  Sometimes you may have an additional problem: where the devil did they go?  If you last had a popup form open…
Overview: This article:       (a) explains one principle method to cross-reference invoice items in Quickbooks®       (b) explores the reasons one might need to cross-reference invoice items       (c) provides a sample process for creating a M…
Familiarize people with the process of utilizing SQL Server views from within Microsoft Access. Microsoft Access is a very powerful client/server development tool. One of the SQL Server objects that you can interact with from within Microsoft Access…
With Microsoft Access, learn how to start a database in different ways and produce different start-up actions allowing you to use a single database to perform multiple tasks. Specify a start-up form through options: Specify an Autoexec macro: Us…

759 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now