- CFML Reference User Guide
- ColdFusion functions
- ColdFusion functions by category
- Functions a-b
- Abs
- ACos
- AddSOAPRequestHeader
- AddSOAPResponseHeader
- AjaxLink
- AjaxOnLoad
- ApplicationStop
- ArrayAppend
- ArrayAvg
- ArrayClear
- ArrayContains
- ArrayContainsNoCase
- ArrayDelete
- ArrayDeleteAt
- ArrayDeleteNoCase
- ArrayEach
- ArrayFilter
- ArrayFind
- ArrayFindAll
- ArrayFindAllNoCase
- ArrayFindNoCase
- ArrayInsertAt
- ArrayIsDefined
- ArrayIsEmpty
- ArrayLen
- ArrayMap
- ArrayMax
- ArrayMin
- ArrayNew
- ArrayPrepend
- ArrayReduce
- ArrayResize
- ArraySet
- ArraySetMetadata
- ArraySlice
- ArraySort
- ArraySum
- ArraySwap
- ArrayToList
- Asc
- ASin
- Atn
- AuthenticatedContext
- AuthenticatedUser
- BinaryDecode
- BinaryEncode
- BitAnd
- BitMaskClear
- BitMaskRead
- BitMaskSet
- BitNot
- BitOr
- BitSHLN
- BitSHRN
- BitXor
- BooleanFormat
- Abs
- Functions-c-d
- CacheGet
- CacheGetAllIds
- CacheGetMetadata
- CacheGetProperties
- CacheGetSession
- CacheIdExists
- CachePut
- CacheRegionExists
- CacheRegionNew
- CacheRegionRemove
- CacheRemove
- CacheRemoveAll
- CacheSetProperties
- CallStackDump
- CallStackGet
- CanDeSerialize
- Canonicalize
- CanSerialize
- Ceiling
- CharsetDecode
- CharsetEncode
- Chr
- CJustify
- Compare
- CompareNoCase
- Cos
- CreateDate
- CreateDateTime
- CreateObject
- CreateObject: .NET object
- CreateObject: COM object
- CreateObject: component object
- CreateObject: CORBA object
- CreateObject: Java or EJB object
- CreateObject: web service object
- CreateODBCDate
- CreateODBCDateTime
- CreateODBCTime
- CreateSignedJWT
- CreateEncryptedJWT
- CreateTime
- CreateTimeSpan
- CreateUUID
- CSRFGenerateToken
- CSRFVerifyToken
- CSVRead
- CSVWrite
- CSVProcess
- DateAdd
- DateCompare
- DateConvert
- DateDiff
- DateFormat
- DatePart
- DateTimeFormat
- Day
- DayOfWeek
- DayOfWeekAsString
- DayOfYear
- DaysInMonth
- DaysInYear
- DE
- DecimalFormat
- DecodeForHTML
- DecodeFromURL
- DecrementValue
- Decrypt
- DecryptBinary
- DeleteClientVariable
- Deserialize
- DeserializeJSON
- DeserializeXML
- DirectoryCopy
- DirectoryCreate
- DirectoryDelete
- DirectoryExists
- DirectoryList
- DirectoryRename
- DollarFormat
- DotNetToCFType
- Duplicate
- Functions-e-g
- EncodeForCSS
- EncodeForDN
- EncodeForHTML
- EncodeForHTMLAttribute
- EncodeForJavaScript
- EncodeForLDAP
- EncodeForURL
- EncodeForXML
- EncodeForXMLAttribute
- EncodeForXpath
- Encrypt
- EncryptBinary
- EntityDelete
- EntityLoad
- EntityLoadByExample
- EntityLoadByPK
- EntityMerge
- EntityNew
- EntityReload
- EntitySave
- EntityToQuery
- Evaluate
- Exp
- ExpandPath
- FileClose
- FileCopy
- FileDelete
- FileExists
- FileGetMimeType
- FileIsEOF
- FileMove
- FileOpen
- FileRead
- FileReadBinary
- FileReadLine
- FileSeek
- FileSetAccessMode
- FileSetAttribute
- FileSetLastModified
- FileSkipBytes
- FileUpload
- FileUploadAll
- FileWrite
- FileWriteLine
- Find
- FindNoCase
- FindOneOf
- FirstDayOfMonth
- Fix
- Floor
- FormatBaseN
- GeneratePBKDFKey
- GenerateSecretKey
- GetApplicationMetadata
- GetAuthUser
- GetBaseTagData
- GetBaseTagList
- GetBaseTemplatePath
- GetClientVariablesList
- GetComponentMetaData
- GetContextRoot
- GetCPUUsage
- GetCurrentTemplatePath
- GetCSPNonce
- GetDirectoryFromPath
- GetEncoding
- GetException
- GetFileFromPath
- GetFileInfo
- GetFreeSpace
- GetFunctionCalledName
- GetFunctionList
- GetGatewayHelper
- GetHttpRequestData
- GetHttpTimeString
- GetK2ServerDocCount
- GetK2ServerDocCountLimit
- GetLocale
- GetLocaleDisplayName
- GetLocalHostIP
- GetMetaData
- GetMetricData
- GetPageContext
- GetPropertyString
- GetPropertyFile
- GetPrinterInfo
- GetPrinterList
- GetProfileSections
- GetProfileString
- GetReadableImageFormats
- GetSafeHTML
- GetSAMLAuthRequest
- GetSAMLLogoutRequest
- Generate3DesKey
- GenerateSAMLSPMetadata
- GetSOAPRequest
- GetSOAPRequestHeader
- GetSOAPResponse
- GetSOAPResponseHeader
- GetSystemFreeMemory
- GetSystemTotalMemory
- GetTempDirectory
- GetTempFile
- GetTemplatePath
- GetTickCount
- GetTimeZoneInfo
- GetToken
- GetTotalSpace
- GetUserRoles
- GetVFSMetaData
- GetWriteableImageFormats
- Functions-h-im
- Hash
- HMac
- Hour
- HQLMethods
- HTMLCodeFormat
- HTMLEditFormat
- IIf
- ImageAddBorder
- ImageBlur
- ImageClearRect
- ImageCopy
- ImageCreateCaptcha
- ImageCrop
- ImageDrawArc
- ImageDrawBeveledRect
- ImageDrawCubicCurve
- ImageDrawLine
- ImageDrawLines
- ImageDrawOval
- ImageDrawPoint
- ImageDrawQuadraticCurve
- ImageDrawRect
- ImageDrawRoundRect
- ImageDrawText
- ImageFlip
- ImageGetBlob
- ImageGetBufferedImage
- ImageGetEXIFMetadata
- ImageGetEXIFTag
- ImageGetHeight
- ImageGetIPTCMetadata
- ImageGetIPTCTag
- ImageGetMetadata
- ImageGetWidth
- ImageGrayscale
- ImageInfo
- ImageMakeColorTransparent
- ImageMakeTranslucent
- ImageNegative
- ImageNew
- ImageOverlay
- ImagePaste
- ImageRead
- ImageReadBase64
- ImageResize
- ImageRotate
- ImageRotateDrawingAxis
- ImageScaleToFit
- ImageSetAntialiasing
- ImageSetBackgroundColor
- ImageSetDrawingColor
- ImageSetDrawingStroke
- ImageSetDrawingTransparency
- ImageSharpen
- ImageShear
- ImageShearDrawingAxis
- ImageTranslate
- ImageTranslateDrawingAxis
- ImageWrite
- ImageWriteBase64
- ImageXORDrawingMode
- Functions-in-k
- IncrementValue
- InputBaseN
- Insert
- Int
- InterruptThread
- InvalidateOauthAccesstoken
- Invoke
- InitSAMLAuthRequest
- InitSAMLLogoutRequest
- InvokeCFClientFunction
- IsArray
- IsAuthenticated
- IsAuthorized
- IsBinary
- IsBoolean
- IsClosure
- IsCustomFunction
- IsDate
- IsDateObject
- IsDDX
- IsDebugMode
- IsDefined
- IsImage
- IsImageFile
- IsInstanceOf
- IsIPv6
- IsJSON
- IsK2ServerABroker
- IsK2ServerDocCountExceeded
- IsK2ServerOnline
- IsLeapYear
- IsLocalHost
- IsNull
- IsNumeric
- IsNumericDate
- IsObject
- isOnline
- IsPDFArchive
- IsPDFFile
- IsPDFObject
- IsProtected
- IsQuery
- isSamlLogoutResponse
- isSafeHTML
- IsSimpleValue
- IsSOAPRequest
- IsSpreadsheetFile
- IsSpreadsheetObject
- IsStruct
- isThreadInterrupted
- IsUserInAnyRole
- IsUserInRole
- IsUserLoggedIn
- IsValid
- IsValidOauthAccesstoken
- IsWDDX
- IsXML
- IsXmlAttribute
- IsXmlDoc
- IsXmlElem
- IsXmlNode
- IsXmlRoot
- JavaCast
- JSStringFormat
- Functions-l
- LCase
- Left
- Len
- ListAppend
- ListChangeDelims
- ListContains
- ListContainsNoCase
- ListDeleteAt
- ListEach
- ListFilter
- ListFind
- ListFindNoCase
- ListFirst
- ListGetAt
- ListGetDuplicates
- ListInsertAt
- ListLast
- ListLen
- ListMap
- ListPrepend
- ListQualify
- ListReduce
- ListRemoveDuplicates
- ListRest
- ListSetAt
- ListSort
- ListToArray
- ListValueCount
- ListValueCountNoCase
- LJustify
- Location
- Log
- Log10
- LSCurrencyFormat
- LSDateFormat
- LSDateTimeFormat
- LSEuroCurrencyFormat
- LSIsCurrency
- LSIsDate
- LSIsNumeric
- LSNumberFormat
- LSParseCurrency
- LSParseDateTime
- LSParseEuroCurrency
- LSParseNumber
- LSTimeFormat
- LTrim
- Functions-m-r
- Max
- Mid
- Min
- Minute
- Month
- MonthAsString
- Now
- NumberFormat
- ObjectEquals
- ObjectLoad
- ObjectSave
- OnWSAuthenticate
- ORMClearSession
- ORMCloseAllSessions
- ORMCloseSession
- ORMEvictCollection
- ORMEvictEntity
- ORMEvictQueries
- ORMExecuteQuery
- ORMFlush
- ORMFlushall
- ORMGetSession
- ORMGetSessionFactory
- ORMIndex
- ORMIndexPurge
- ORMReload
- ORMSearch
- ORMSearchOffline
- ParagraphFormat
- ParameterExists
- ParseDateTime
- Pi
- PrecisionEvaluate
- ProcessSAMLResponse
- ProcessSAMLLogoutRequest
- Quarter
- PreserveSingleQuotes
- QueryAddColumn
- QueryAddRow
- QueryConvertForGrid
- QueryExecute
- QueryFilter
- QueryGetResult
- QueryGetRow
- QueryKeyExists
- QueryMap
- QueryNew
- QueryReduce
- QuerySetCell
- QuotedValueList
- QueryEach
- Rand
- Randomize
- RandRange
- ReEscape
- REFind
- REFindNoCase
- ReleaseComObject
- REMatch
- REMatchNoCase
- RemoveCachedQuery
- RemoveChars
- RepeatString
- Replace
- ReplaceList
- ReplaceNoCase
- REReplace
- REReplaceNoCase
- RestDeleteApplication
- RestSetResponse
- RestInitApplication
- Reverse
- Right
- RJustify
- Round
- RTrim
- Functions-s
- Second
- SendGatewayMessage
- SendSAMLLogoutResponse
- Serialize
- SerializeJSON
- SerializeXML
- SessionInvalidate
- SessionRotate
- SessionGetMetaData
- SessionInvalidate
- SessionRotate
- SetDay
- SetEncoding
- SetHour
- SetLocale
- SetMonth
- SetProfileString
- SetPropertyString
- SetVariable
- SetYear
- Sgn
- Sin
- Sleep
- SpanExcluding
- SpanIncluding
- SpreadsheetAddAutoFilter
- SpreadsheetAddColumn
- SpreadsheetAddFreezePane
- SpreadsheetAddImage
- SpreadsheetAddInfo
- SpreadsheetAddPageBreaks
- SpreadsheetAddRow
- SpreadsheetAddRows
- SpreadsheetAddSplitPane
- SpreadsheetCreateSheet
- SpreadsheetDeleteColumn
- SpreadsheetDeleteColumns
- SpreadsheetDeleteRow
- SpreadsheetDeleteRows
- SpreadsheetFormatCell
- SpreadsheetFormatColumn
- SpreadsheetFormatCellRange
- SpreadsheetFormatColumn
- SpreadsheetFormatColumns
- SpreadsheetFormatRow
- SpreadsheetFormatRows
- SpreadsheetGetCellComment
- SpreadsheetGetCellFormula
- SpreadsheetGetCellValue
- SpreadsheetGetColumnCount
- SpreadsheetInfo
- SpreadsheetMergeCells
- SpreadsheetNew
- SpreadsheetRead
- SpreadsheetReadBinary
- SpreadsheetRemoveSheet
- SpreadsheetSetActiveSheet
- SpreadsheetSetActiveSheetNumber
- SpreadsheetSetCellComment
- SpreadsheetSetCellFormula
- SpreadsheetSetCellValue
- SpreadsheetSetColumnWidth
- SpreadsheetSetFooter
- SpreadsheetSetHeader
- SpreadsheetSetRowHeight
- SpreadsheetShiftColumns
- SpreadsheetShiftRows
- SpreadsheetWrite
- StreamingSpreadsheetNew
- StreamingSpreadsheetCleanup
- StreamingSpreadsheetRead
- StreamingSpreadsheetProcess
- SpreadsheetSetFooterImage
- SpreadsheetSetHeaderImage
- SpreadsheetSetFittoPage
- SpreadsheetUngroupColumns
- SpreadsheetGroupColumns
- SpreadsheetUngroupRows
- SpreadsheetGroupRows
- SpreadsheetRemoveColumnBreak
- SpreadsheetSetColumnBreak
- SpreadsheetRemoveRowBreak
- SpreadsheetSetRowBreak
- SpreadsheetRemovePrintGridlines
- SpreadsheetAddPrintGridlines
- SpreadsheetGetColumnWidth
- SpreadsheetSetColumnHidden
- SpreadsheetSetRowHidden
- SpreadsheetisColumnHidden
- SpreadsheetisRowHidden
- SpreadsheetisStreamingXmlFormat
- SpreadsheetisXmlFormat
- SpreadsheetisBinaryFormat
- SpreadsheetRenameSheet
- SpreadsheetRemoveSheetNumber
- SpreadsheetGetLastRowNumber
- SpreadsheetGetPrintOrientation
- Sqr
- StripCR
- StructAppend
- StructClear
- StructCopy
- StructCount
- StructDelete
- StructEach
- StructFilter
- StructFind
- StructFindKey
- StructFindValue
- StructGet
- StructGetMetadata
- StructInsert
- StructIsEmpty
- StructKeyArray
- StructKeyExists
- StructKeyList
- StructMap
- StructNew
- StructReduce
- StructSetMetadata
- StructSort
- StructToSorted
- StructUpdate
- StructValueArray
- StoreSetMetadata
- StoreGetACL
- StoreGetMetadata
- StoreAddACL
- StoreSetACL
- Functions-t-z
- Tan
- ThreadJoin
- ThreadTerminate
- Throw
- TimeFormat
- ToBase64
- ToBinary
- ToScript
- ToString
- Trace
- Transactionandconcurrency
- TransactionCommit
- TransactionRollback
- TransactionSetSavePoint
- Trim
- UCase
- URLDecode
- URLEncodedFormat
- URLSessionFormat
- Val
- ValueList
- VerifyClient
- Week
- Wrap
- WriteDump
- WriteLog
- WriteOutput
- WSGetAllChannels
- WSGetSubscribers
- WSPublish
- WSSendMessage
- XmlChildPos
- XmlElemNew
- XmlFormat
- XmlGetNodeType
- XmlNew
- XmlParse
- XmlSearch
- XmlTransform
- XmlValidate
- Year
- YesNoFormat
- ColdFusion tags
- ColdFusion tag summary
- ColdFusion tags by category
- Application framework tags
- Communications tags
- Database manipulation tags
- Data output tags
- Debugging tags
- Exception handling tags
- Extensibility tags
- File management tags
- Flow-control tags
- Forms tags
- Internet Protocol tags
- Page processing tags
- Security tags
- Variable manipulation tags
- Other tags
- Tags a-b
- Tags c
- cfcache
- cfcalendar
- cfcase
- cfcatch
- cfchart
- cfchart tag in ColdFusion
- Get started with cfchart
- Customize a chart using cfchart
- Advanced cfchart customization options
- Create an area chart in ColdFusion
- Create line charts in ColdFusion
- Create bar charts in ColdFusion
- Create floating bar charts in ColdFusion
- Create histograms in ColdFusion
- Create pie charts in ColdFusion
- Create funnel charts in ColdFusion
- Create pyramid charts in ColdFusion
- Create curve charts in ColdFusion
- Create boxplots in ColdFusion
- Create donut charts in ColdFusion
- Create bubble charts in ColdFusion
- Create scatterplots in ColdFusion
- Create radar charts in ColdFusion
- Other chart types in ColdFusion (Cone, Cylinder, Piano, and Bullet)
- Advanced customization options in cfchart
- cfchartdata
- cfchartseries
- cfchartset
- cfclient
- cfclientsettings
- cfcol
- cfcollection
- cfcomponent
- cfcontent
- cfcontinue
- cfcookie
- Tags f
- cffeed
- cffile
- cffile action = "append"
- cffile action = "copy"
- cffile action = "delete"
- cffile action = "move"
- cffile action = "read"
- cffile action = "readBinary"
- cffile action = "rename"
- cffile action = "upload"
- cffile action = "uploadAll"
- cffile action = "write"
- cffileupload
- cffinally
- cfflush
- cfform
- cfformgroup
- cfformitem
- cfftp
- cfftp: Connection: file and directory operations
- cfftp: Opening and closing FTP server connections
- cfftp : Opening and closing secure FTP server connections
- cfftp action = "listDir"
- cffunction
- Tags g-h
- Tags i
- Tags j-l
- cfjava
- cflayout
- cflayoutarea
- cfldap
- cflocation
- cflock
- cflog
- cflogin
- cfloginuser
- cflogout
- cfloop
- cfloop : conditional loop
- cfloop : index loop
- cfloop : looping over a COM collection or structure
- cfloop : looping over a date or time range
- cfloop : looping over a list, a file, or an array
- cfloop : looping over a query
- Tags m-o
- cfmail
- cfmailparam
- cfmailpart
- cfmap
- cfmapitem
- cfmediaplayer
- cfmenu
- cfmenuitem
- cfmessagebox
- cfmodule
- cfNTauthenticate
- cfoauth
- cfobject
- cfobject: .NET object
- cfobject: COM object
- cfobject: component object
- cfobject: CORBA object
- cfobject: Java or EJB object
- cfobject: web service object
- cfobjectcache
- cfoutput
- Tags p-q
- Tags r-s
- Tags t
- Tags u-z
- CFML Reference
- Reserved words and variables
- Ajax JavaScript functions
- Ajax JavaScript functions
- Function summary Ajax
- ColdFusion.Ajax.submitForm
- ColdFusion.Autosuggest.getAutosuggestObject
- ColdFusion.Layout.enableSourceBind
- ColdFusion.MessageBox.getMessageBoxObject
- ColdFusion.ProgressBar.getProgressBarObject
- ColdFusion.MessageBox.isMessageBoxDefined
- JavaScriptFunctionsinColdFusion9Update1
- ColdFusion ActionScript functions
- ColdFusion mobile functions
- Application.cfc reference
- Script functions implemented as CFCs
- ColdFusion Flash Form style reference
- Styles valid for all controls
- Styles for cfform
- Styles for cfformgroup with horizontal or vertical type attributes
- Styles for box-style cfformgroup elements
- Styles for cfformgroup with accordion type attribute
- Styles for cfformgroup with tabnavigator type attribute
- Styles for cfformitem with hrule or vrule type attributes
- Styles for cfinput with radio, checkbox, button, image, or submit type attributes
- Styles for cftextarea tag and cfinput with text, password, or hidden type attributes
- Styles for cfselect with size attribute value of 1
- Styles for cfselect with size attribute value greater than 1
- Styles for cfcalendar tag and cfinput with dateField type attribute
- Styles for the cfgrid tag
- Styles for the cftree tag
- ColdFusion Flash Form Style Reference
- ColdFusion event gateway reference
- ColdFusion Event Gateway reference
- addEvent
- CFEvent
- CFEventclass
- Constructor
- Gateway development interfaces and classes
- getStatus
- setCFCPath
- setCFCMethod
- getOriginatorID
- getLogger
- getBuddyList
- getBuddyInfo
- IM gateway message sending commands
- IM Gateway GatewayHelper class methods
- onIncomingMessage
- onIMServerMessage
- onBuddyStatus
- onAddBuddyResponse
- onAddBuddyRequest
- IM Gateway CFC incoming message methods
- IM gateway methods and commands
- CFML CFEvent structure
- warn
- info
- setOriginatorID
- data command
- submit Multi command
- submit command
- setGatewayType
- setGatewayID
- setData
- setCFCListeners
- outgoingMessage
- getStatusTimeStamp
- numberOfMessagesReceived
- numberOfMessagesSent
- removeBuddy
- removeDeny
- removePermit
- setNickName
- setPermitMode
- setStatus
- SMS Gateway CFEvent structure and commands
- SMS Gateway incoming message CFEvent structure
- getStatusAsString
- getProtocolName
- getPermitMode
- getPermitList
- getNickName
- getName
- getDenyList
- getCustomAwayMessage
- getQueueSize
- getMaxQueueSize
- getHelper
- getGatewayType
- getGatewayServices
- getGatewayID_1
- getGatewayID
- getData
- getCFCTimeout
- setCFCTimeout
- getCFCPath
- getCFCMethod
- GatewayServices class
- Gateway interface
- GatewayHelper interface
- addPermit
- addDeny
- addBuddy
- error
- debug
- Logger class
- stop
- start
- CFML event gateway SendGatewayMessage data parameter
- restart
- fatal
- SMS gateway message sending commands
- ColdFusion C++ CFX Reference
- ColdFusion Java CFX reference
- WDDX JavaScript Objects
- Cloud services
- ColdFusion and GCP Storage
- ColdFusion and GCP Firestore
- ColdFusion and GCP PubSub
- ColdFusion and Amazon S3
- ColdFusion and DynamoDB
- ColdFusion and Amazon SQS
- ColdFusion and Amazon SNS
- ColdFusion and MongoDB
- ColdFusion and Azure Blob
- ColdFusion and Azure Service Bus
- Multi-cloud storage services
- Multi-cloud RDS databases
- ColdFusion and Azure Cosmos DB
Description
Manages Excel spreadsheet files:
- Reads a sheet from a spreadsheet file and stores it in a ColdFusion spreadsheet object, query, CSV string, or HTML string.
- Writes single sheet to a new XLS file from a query, ColdFusion spreadsheet object, or CSV string variable.
- Add a sheet an existing XLS file.
Category
Syntax
The tag syntax depends on the action attribute value:
Read
<cfspreadsheet
action="read"
src = "filepath"
columns = "range"
columnnames = "comma-delimited list"
excludeHeaderRow = "true | false"
format = "CSV|HTML"
headerrow = "row number"
name = "text"
query = "query name"
rows = "range"
sheet = "number"
sheetname = "text">
Update
<cfspreadsheet
action="update"
filename = "filepath"
format = "csv"
name = "text"
password = "password"
query = "query name"
sheetname = "text" >
Write
<cfspreadsheet
action="write"
autosize="true|false"
filename = "filepath"
format = "csv"
name = "text"
overwrite = "true | false"
password = "password"
query = "queryname"
sheetname = "text"
autosize = "true | false" >
See also
Sreadsheet functions.
History
ColdFusion (2025 release): You can no longer read password-protected Excel files without specifying the password. If you skip the password attribute in the read action, you will get an exception. As a result, you’ll also be unable to update the file as the read action will produce the exception. View the examples for more information.
ColdFusion 11: Added the attribute autosize.
ColdFusion 9.0.1: Added the attribute {{excludeHeaderRow}}
ColdFusion 9: Added this tag.
Attributes
Attribute |
Action |
Req/Opt |
Default |
Description |
|---|---|---|---|---|
action |
All |
Required |
|
One of the following:
|
| autosize | write | Optional | true | By default the value of this attribute is true. The columns in a sheet resize to accommodate the contents. To avoid resizing the columns, set it to false. Note: Auto sizing can be relatively slow on large sheets. |
filename |
{{update, write}}r |
Required |
|
The pathname of the file that is written. |
excludeHeaderRow |
read |
Optional |
false |
If set to true, excludes the headerrow from being included in the query results. |
name |
All |
name or query is required. |
|
|
query |
All |
name or query is required. |
|
|
src |
read |
Required |
|
The pathname of the file to read. |
columns |
read |
Optional |
|
Column number or range of columns. Specify a single number, a hypen-separated column range, a comma-separated list, or any combination of these; for example: 1,3-6,9. Note: Setting a range higher than the actual number of columns in sheet results in an exception when accessing columns which are yet to be added. |
columnnames |
read |
Optional |
|
Comma-separated column names. |
format |
All |
Optional |
For read, save as a spreadsheet object. |
Format of the data represented by the name variable.
|
headerrow |
read |
Optional |
|
Row number that contains column names. |
overwrite |
write |
Optional |
false |
A Boolean value specifying whether to overwrite an existing file. |
password |
updatewrite |
Optional |
|
Set a password for modifying the sheet. |
rows |
read |
Optional |
|
The range of rows to read. Specify a single number, a hypen-separated row range, a comma-separated list, or any combination of these; for example: 1,3-6,9. |
sheet |
read |
Optional |
|
Number of the sheet. For the read action, you can specify sheet or sheetname. |
sheetname |
All |
Optional |
|
Name of the sheet For the read action, you can specify sheet or sheetname. For write and update actions, the specified sheet is renamed according to the value you specify for sheetname. |
Usage
Each ColdFusion spreadsheet object represents Excel sheet:
- To read an Excel file with multiple sheets, use multiple cfspreadsheet tags with the read option and specify different name and sheet or sheetname attributes for each sheet.
- To write multiple sheets to a single file, use the write action to create the file and save the first sheet and use the update action to add each additional sheet.
- To update an existing file, read all sheets in the file, modify one or more sheets, and use the contents, and use the write action and Update actions (for multiple sheet files) to rewrite the entire file.
The cfspreadsheet tag writes only XLS format files. To write a CSV file, put your data in a CSV formatted string variable and use the cffile tag to write the variable contents in a file.Use the ColdFusion Spreadsheet* functions, such as SpreadsheetNew and SpreadsheetAddColumn to create a new ColdFusion Spreadsheet object and modify the spreadsheet contents.
Example
The following example uses the cfspreadsheet tag to read and write Excel spreadsheets using various formats. It also shows a simple use of ColdFusion Spreadsheet functions to modify a sheet.
<!--- Read data from two datasource tables. --->
<cfquery
name="courses" datasource="cfdocexamples"
cachedwithin="#CreateTimeSpan(0, 6, 0, 0)#">
SELECT CORNUMBER,DEPT_ID,COURSE_ID,CORNAME
FROM COURSELIST
</cfquery>
<cfquery
name="centers" datasource="cfdocexamples"
cachedwithin="#CreateTimeSpan(0, 6, 0, 0)#">
SELECT *
FROM CENTERS
</cfquery>
<cfscript>
//Use an absolute path for the files. --->
theDir=GetDirectoryFromPath(GetCurrentTemplatePath());
theFile=theDir & "courses.xls";
//Create two empty ColdFusion spreadsheet objects. --->
theSheet = SpreadsheetNew("CourseData");
theSecondSheet = SpreadsheetNew("CentersData");
//Populate each object with a query. --->
SpreadsheetAddRows(theSheet,courses);
SpreadsheetAddRows(theSecondSheet,centers);
</cfscript>
<!--- Write the two sheets to a single file --->
<cfspreadsheet action="write" filename="#theFile#" name="theSheet"
sheetname="courses" overwrite=true>
<cfspreadsheet action="update" filename="#theFile#" name="theSecondSheet"
sheetname="centers">
<!--- Read all or part of the file into a spreadsheet object, CSV string,
HTML string, and query. --->
<cfspreadsheet action="read" src="#theFile#" sheetname="courses" name="spreadsheetData">
<cfspreadsheet action="read" src="#theFile#" sheet=1 rows="3,4" format="csv" name="csvData">
<cfspreadsheet action="read" src="#theFile#" format="html" rows="5-10" name="htmlData">
<cfspreadsheet action="read" src="#theFile#" sheetname="centers" query="queryData">
<h3>First sheet row 3 read as a CSV variable</h3>
<cfdump var="#csvData#">
<h3>Second sheet rows 5-10 read as an HTML variable</h3>
<cfdump var="#htmlData#">
<h3>Second sheet read as a query variable</h3>
<cfdump var="#queryData#">
<!--- Modify the courses sheet. --->
<cfscript>
SpreadsheetAddRow(spreadsheetData,"03,ENGL,230,Poetry 1",8,1);
SpreadsheetAddColumn(spreadsheetData,
"Basic,Intermediate,Advanced,Basic,Intermediate,Advanced,Basic,Intermediate,Advanced",
3,2,true);
</cfscript>
<!--- Write the updated Courses sheet to a new XLS file --->
<cfspreadsheet action="write" filename="#theDir#updatedFile.xls" name="spreadsheetData"
sheetname="courses" overwrite=true>
<!--- Write an XLS file containing the data in the CSV variable. --->
<cfspreadsheet action="write" filename="#theDir#dataFromCSV.xls" name="CSVData"
format="csv" sheetname="courses" overwrite=true>
Let's take chunks of the above code and see each chunk in action. For example, consider a csv file is uploaded on the web, which you want to retrieve and perform some actions.
You can also jump to ths fiddle and try out the code chunks. Sign in with your Google or Facebook credentials and launch the file cfspreadsheet.cfm.
Step 1
Read the csv file and store the response in a variable.
<cfscript> cfhttp( name="mydata", url="https://raw.githubusercontent.com/sauravg94/test-repo/master/MOCK_DATA.csv", firstrowasheaders="true" ,method="GET"); writedump(mydata); </cfscript>
Step 2
- Set the destination for the xlsx or xls file.
- Create an empty spreadsheet object.
- Populate the object with data fetched with cfhttp.
Note:
SpreadsheetNew(true|false)
- True or Yes: Creates an .xlsx file that is supported by Microsoft Office Excel 2007.
- False or No: Creates an .xls file.
<cfscript>
//Use an absolute path for the files.
theDir=GetDirectoryFromPath(GetCurrentTemplatePath());
theFile=theDir & "mock_data.xlsx";
//Create an empty ColdFusion spreadsheet objects.
theSheet = SpreadsheetNew(true);
//Populate the object with data fetched with cfhttp
SpreadsheetAddRows(theSheet,mydata,1);
</cfscript>
Step 3
Write the sheet into a file.
<cfspreadsheet action="write" filename="#theFile#" name="theSheet" sheetname="mock_data" overwrite=true>
Step 4
Read all or part of the file into a spreadsheet object, CSV string, HTML string, and query.
<cfspreadsheet action="read" src="#theFile#" sheetname="mock_data" name="spreadsheetData"> <cfspreadsheet action="read" src="#theFile#" sheet=1 rows="100-200" format="csv" name="csvData"> <cfspreadsheet action="read" src="#theFile#" format="html" rows="5-10" name="htmlData"> <cfspreadsheet action="read" src="#theFile#" sheetname="mock_data" query="queryData">
Step 5
<cfdump var="#spreadsheetData#" > <cfoutput > #csvData# </cfoutput> <cfdump var="#htmlData#" > <cfdump var="#queryData#" >
<cfspreadsheet action="read" src="#expandPath('employee.xlsx')#" name="employee" password="abc123">
<cfdump var="#employee#" label="Result of cfspreadsheet read action (with password attribute)">
Example 2
Read the file without specifying the password attribute. The script will produce an exception.
cfspreadsheet action="read" src="#expandPath('employee.xlsx')#" name="employee">
<cfdump var="#employee#" label="Result of cfspreadsheet read action (without password attribute)">
Example 3
Read the file with an incorrect password, which will produce an exception.
<cfspreadsheet action="read" src="#expandPath('employee.xls')#" name="employee" password="1234">
<cfdump var="#employee#" label="Result of cfspreadsheet read action (with incorrect password attribute)">
Example 4
Now, attempt updating the file without specifying the password attribute. The read action will produce an exception.
<cfspreadsheet action="read" src="#expandPath('employee.xlsx')#" name="employee" >
<cfspreadsheet
action="update"
filename = "#expandPath('employee.xlsx')#"
name="employee"
sheetname = "sheet1"
password="abc123" >
<cfdump var="#var#" >
Real-world uses of the cfspreadsheet tag
Database report export to Excel
Your sales department needs weekly reports showing all customer orders for management review. The reports must be in Excel format so managers can sort, filter, and analyze the data. The reports should include proper formatting, headers, and be easy to distribute via email.
Problem statement
- Management requires reports in Excel format, not HTML or PDF
- Database queries return data that needs to be exported
- Reports must be well-formatted and professional
- Need to automate weekly report generation
- Multiple departments need different subsets of data
- Manual export from database tools is time-consuming
Solution
Use cfspreadsheet to convert database query results directly into formatted Excel files.
<cfscript>
// Create sample order data (in production, this would be a database query)
ordersQuery = queryNew(
"OrderID,OrderDate,CustomerName,ProductName,Quantity,UnitPrice,Total,Status",
"integer,date,varchar,varchar,integer,decimal,decimal,varchar"
);
queryAddRow(ordersQuery, [
{
OrderID: 1001,
OrderDate: dateAdd("d", -7, now()),
CustomerName: "Acme Corporation",
ProductName: "Laptop Computer",
Quantity: 5,
UnitPrice: 1299.99,
Total: 6499.95,
Status: "Shipped"
},
{
OrderID: 1002,
OrderDate: dateAdd("d", -6, now()),
CustomerName: "Tech Solutions Inc",
ProductName: "Wireless Mouse",
Quantity: 25,
UnitPrice: 29.99,
Total: 749.75,
Status: "Delivered"
},
{
OrderID: 1003,
OrderDate: dateAdd("d", -5, now()),
CustomerName: "Digital Dynamics",
ProductName: "USB-C Hub",
Quantity: 10,
UnitPrice: 49.99,
Total: 499.90,
Status: "Processing"
},
{
OrderID: 1004,
OrderDate: dateAdd("d", -4, now()),
CustomerName: "Global Enterprises",
ProductName: "Wireless Keyboard",
Quantity: 15,
UnitPrice: 79.99,
Total: 1199.85,
Status: "Shipped"
},
{
OrderID: 1005,
OrderDate: dateAdd("d", -3, now()),
CustomerName: "Innovative Systems",
ProductName: "Monitor 27-inch",
Quantity: 8,
UnitPrice: 349.99,
Total: 2799.92,
Status: "Delivered"
}
]);
// Set file location (use expandPath to get web-accessible directory)
// In production, configure a specific reports directory with proper permissions
reportDir = expandPath("./reports/");
// Create directory if it doesn't exist (with error handling)
try {
if (!directoryExists(reportDir)) {
directoryCreate(reportDir);
}
canWriteFiles = true;
} catch (any e) {
// If we can't create directory, use memory-only mode
canWriteFiles = false;
reportDir = "Unable to create directory - using memory mode";
}
reportFileName = "Weekly_Sales_Report_" & dateFormat(now(), "yyyy-mm-dd") & ".xlsx";
fullReportPath = canWriteFiles ? reportDir & reportFileName : "";
</cfscript>
<h2>Database Report Export to Excel</h2>
<!--- Check if we can write files --->
<cfif NOT canWriteFiles>
<div style="background: ##fff3e0; border: 2px solid ##ff9800; padding: 15px; margin: 15px 0; border-radius: 5px;">
<h4 style="color: orange; margin: 0;">⚠ File System Access Limited</h4>
<p>Unable to write files to disk. This demo will show in-memory spreadsheet operations instead.</p>
<p><strong>For production:</strong> Configure a directory with proper write permissions in your application.</p>
</div>
</cfif>
<!--- Display the query data --->
<h3>Order Data (Query Results)</h3>
<cfdump
var="#ordersQuery#"
label="Orders to Export"
expand="yes">
<hr>
<!--- Method 1: Simple export - Query directly to Excel --->
<h3>Method 1: Simple Query Export</h3>
<cfif canWriteFiles>
<cftry>
<cfspreadsheet
action="write"
query="#ordersQuery#"
filename="#fullReportPath#"
sheetname="Weekly Orders"
overwrite="true">
<div style="background: ##e8f5e9; border: 2px solid ##4caf50; padding: 15px; margin: 15px 0; border-radius: 5px;">
<h4 style="color: green; margin: 0;">✓ Excel File Created Successfully</h4>
<p><strong>Location:</strong> #fullReportPath#</p>
<p><strong>Records Exported:</strong> #ordersQuery.recordCount#</p>
</div>
<cfcatch type="any">
<div style="background: ##ffebee; border: 2px solid ##f44336; padding: 15px; margin: 15px 0; border-radius: 5px;">
<h4 style="color: red; margin: 0;">✗ Error Writing File</h4>
<p><strong>Error:</strong> #cfcatch.message#</p>
<p>The application may not have permission to write to this directory.</p>
</div>
<cfset canWriteFiles = false>
</cfcatch>
</cftry>
<cfelse>
<div style="background: ##e3f2fd; border: 2px solid ##2196f3; padding: 15px; margin: 15px 0; border-radius: 5px;">
<h4>📝 Code Example (File Write Disabled)</h4>
<pre style="background: ##f5f5f5; padding: 10px; border-radius: 5px;">
<cfspreadsheet
action="write"
query="##ordersQuery##"
filename="##fullReportPath##"
sheetname="Weekly Orders"
overwrite="true"></pre>
<p>This would create an Excel file with all query data when file permissions are available.</p>
</div>
</cfif>
<!--- Method 2: Advanced export with formatting --->
<h3>Method 2: Formatted Excel Export (In-Memory)</h3>
<cfscript>
// Create a new spreadsheet object (true = .xlsx format)
// This works in memory even without file system access
spreadsheetObj = SpreadsheetNew("Weekly Sales Report", true);
// Add the query data starting at row 2 (leaving room for title)
SpreadsheetAddRow(spreadsheetObj, "WEEKLY SALES REPORT - " & dateFormat(now(), "mmmm dd, yyyy"));
SpreadsheetAddRow(spreadsheetObj, ""); // Blank row
// Add query data
SpreadsheetAddRows(spreadsheetObj, ordersQuery);
// Format the title row
SpreadsheetFormatRow(spreadsheetObj,
{
bold: true,
fontsize: 14,
alignment: "center"
},
1
);
// Format the header row (row 3, after title and blank row)
SpreadsheetFormatRow(spreadsheetObj,
{
bold: true,
fgcolor: "light_blue",
alignment: "center"
},
3
);
// Set column widths for better readability
SpreadsheetSetColumnWidth(spreadsheetObj, 1, 12); // OrderID
SpreadsheetSetColumnWidth(spreadsheetObj, 2, 15); // OrderDate
SpreadsheetSetColumnWidth(spreadsheetObj, 3, 25); // CustomerName
SpreadsheetSetColumnWidth(spreadsheetObj, 4, 25); // ProductName
SpreadsheetSetColumnWidth(spreadsheetObj, 5, 12); // Quantity
SpreadsheetSetColumnWidth(spreadsheetObj, 6, 12); // UnitPrice
SpreadsheetSetColumnWidth(spreadsheetObj, 7, 12); // Total
SpreadsheetSetColumnWidth(spreadsheetObj, 8, 15); // Status
// Try to save formatted spreadsheet
formattedFileName = "Weekly_Sales_Report_Formatted_" & dateFormat(now(), "yyyy-mm-dd") & ".xlsx";
formattedPath = canWriteFiles ? reportDir & formattedFileName : "";
if (canWriteFiles) {
try {
SpreadsheetWrite(spreadsheetObj, formattedPath, true);
formattedSaved = true;
} catch (any e) {
formattedSaved = false;
}
} else {
formattedSaved = false;
}
</cfscript>
<cfif formattedSaved>
<div style="background: ##e8f5e9; border: 2px solid ##4caf50; padding: 15px; margin: 15px 0; border-radius: 5px;">
<h4 style="color: green; margin: 0;">✓ Formatted Excel File Created</h4>
<p><strong>Location:</strong> #formattedPath#</p>
<p><strong>Features:</strong> Title row, formatted headers, adjusted column widths</p>
</div>
<cfelse>
<div style="background: ##e8f5e9; border: 2px solid ##4caf50; padding: 15px; margin: 15px 0; border-radius: 5px;">
<h4 style="color: green; margin: 0;">✓ Spreadsheet Object Created in Memory</h4>
<p><strong>Features Applied:</strong> Title row, formatted headers, adjusted column widths</p>
<p><em>In production with file permissions, this would be saved to disk.</em></p>
<p><strong>Alternative:</strong> Use <code>cfheader/cfcontent</code> to stream directly to browser for download.</p>
</div>
</cfif>
<!--- Method 3: Multiple sheets in one workbook --->
<h3>Method 3: Multi-Sheet Workbook (In-Memory)</h3>
<cfscript>
// Create summary data
summaryQuery = queryNew(
"Status,OrderCount,TotalAmount",
"varchar,integer,decimal"
);
queryAddRow(summaryQuery, [
{Status: "Shipped", OrderCount: 2, TotalAmount: 7699.80},
{Status: "Delivered", OrderCount: 2, TotalAmount: 3549.67},
{Status: "Processing", OrderCount: 1, TotalAmount: 499.90}
]);
// Create main workbook
workbook = SpreadsheetNew("Orders", true);
SpreadsheetAddRows(workbook, ordersQuery);
// Format headers
SpreadsheetFormatRow(workbook, {bold: true, fgcolor: "light_blue"}, 1);
// Add summary sheet
SpreadsheetCreateSheet(workbook, "Summary");
SpreadsheetSetActiveSheet(workbook, "Summary");
SpreadsheetAddRows(workbook, summaryQuery);
SpreadsheetFormatRow(workbook, {bold: true, fgcolor: "light_green"}, 1);
// Try to save multi-sheet workbook
multiSheetFileName = "Weekly_Sales_Report_MultiSheet_" & dateFormat(now(), "yyyy-mm-dd") & ".xlsx";
multiSheetPath = canWriteFiles ? reportDir & multiSheetFileName : "";
if (canWriteFiles) {
try {
SpreadsheetWrite(workbook, multiSheetPath, true);
multiSheetSaved = true;
} catch (any e) {
multiSheetSaved = false;
}
} else {
multiSheetSaved = false;
}
</cfscript>
<cfif multiSheetSaved>
<div style="background: ##e8f5e9; border: 2px solid ##4caf50; padding: 15px; margin: 15px 0; border-radius: 5px;">
<h4 style="color: green; margin: 0;">✓ Multi-Sheet Workbook Created</h4>
<p><strong>Location:</strong> #multiSheetPath#</p>
<p><strong>Sheets:</strong> Orders (detailed data) + Summary (aggregated data)</p>
</div>
<cfelse>
<div style="background: ##e8f5e9; border: 2px solid ##4caf50; padding: 15px; margin: 15px 0; border-radius: 5px;">
<h4 style="color: green; margin: 0;">✓ Multi-Sheet Workbook Created in Memory</h4>
<p><strong>Sheets:</strong> Orders (detailed data) + Summary (aggregated data)</p>
<p><em>In production with file permissions, this would be saved to: #multiSheetFileName#</em></p>
</div>
</cfif>
<!--- Display summary data --->
<h3>Summary Data</h3>
<cfdump
var="#summaryQuery#"
label="Order Summary by Status"
expand="yes">
<!--- Calculate totals --->
<cfscript>
reportStats = {
"totalOrders": ordersQuery.recordCount,
"totalRevenue": dollarFormat(arraySum(ordersQuery["Total"])),
"reportDate": dateTimeFormat(now(), "yyyy-mm-dd HH:nn:ss"),
"filesGenerated": 3,
"reportDirectory": reportDir
};
</cfscript>
<h3>Report Generation Summary</h3>
<cfdump
var="#reportStats#"
label="Export Statistics"
expand="yes">
<!--- Example: Download link --->
<div style="background: ##e3f2fd; border-left: 4px solid ##2196f3; padding: 15px; margin: 20px 0;">
<h4>📥 Generated Reports:</h4>
<ul>
<li><strong>Simple Export:</strong> #reportFileName#</li>
<li><strong>Formatted Export:</strong> #formattedFileName#</li>
<li><strong>Multi-Sheet Export:</strong> #multiSheetFileName#</li>
</ul>
<cfif canWriteFiles>
<p><strong>Location:</strong> #reportDir#</p>
<cfelse>
<p><strong>Status:</strong> Created in memory (file system access not available)</p>
<p><strong>Alternative:</strong> Stream directly to browser using cfheader/cfcontent</p>
</cfif>
</div>
<!--- Show download example --->
<div style="background: ##f5f5f5; border: 1px solid ##ccc; padding: 15px; margin: 20px 0; border-radius: 5px;">
<h4>💡 Alternative: Stream Excel to Browser (No File System Required)</h4>
<p>When file system access is limited, stream the spreadsheet directly to the browser:</p>
<pre style="background: ##fff; padding: 10px; border: 1px solid ##ddd; border-radius: 3px; overflow-x: auto;">
<cfscript>
// Create spreadsheet in memory
sheet = SpreadsheetNew("Report", true);
SpreadsheetAddRows(sheet, myQuery);
// Get binary data
binaryData = SpreadsheetReadBinary(sheet);
</cfscript>
<cfheader name="Content-Disposition" value="attachment; filename=report.xlsx">
<cfcontent type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
variable="##binaryData##" reset="true"></pre>
</div>
Employee data import from Excel
Your HR department maintains employee records in Excel spreadsheets. When onboarding new employees or updating existing records, HR staff upload Excel files that need to be imported into your employee management system. The system must validate the data and insert it into the database.
Problem statement
- HR staff work with Excel for employee data entry
- Need to import Excel data into ColdFusion application
- Must validate data before database insertion
- Handle errors gracefully (missing fields, invalid formats)
- Support both .xls and .xlsx formats
- Prevent duplicate employee records
- Provide clear feedback on import success/failure
Solution
Use cfspreadsheet to read Excel files and convert them to query objects for processing.
<cfscript>
// Set upload directory (use expandPath for web-accessible directory)
uploadDir = expandPath("./employee-uploads/");
// Create directory if it doesn't exist (with error handling)
try {
if (!directoryExists(uploadDir)) {
directoryCreate(uploadDir);
}
canUploadFiles = true;
} catch (any e) {
// If we can't create directory, disable file upload
canUploadFiles = false;
uploadDir = "File system access not available";
}
</cfscript>
<h2>Employee Data Import from Excel</h2>
<!--- Check if file upload is available --->
<cfif NOT canUploadFiles>
<div style="background: ##fff3e0; border: 2px solid ##ff9800; padding: 20px; margin: 20px 0; border-radius: 5px;">
<h3 style="color: orange; margin: 0;">⚠ File Upload Not Available</h3>
<p>The application doesn't have permission to create upload directories.</p>
<p><strong>For production:</strong> Configure a directory with proper write permissions.</p>
<p><strong>Alternative:</strong> This demo will show how the import process works with sample data instead.</p>
</div>
<!--- Set flag to use sample data --->
<cfset useSampleData = true>
<cfelse>
<cfset useSampleData = false>
</cfif>
<!--- File upload form --->
<cfif NOT isDefined("form.employeeFile") AND canUploadFiles>
<div style="background: ##e3f2fd; border: 2px solid ##2196f3; padding: 20px; margin: 20px 0; border-radius: 5px;">
<h3>Upload Employee Data</h3>
<p>Please upload an Excel file (.xlsx or .xls) containing employee information.</p>
<p><strong>Required columns:</strong> EmployeeID, FirstName, LastName, Email, Department, Position, HireDate, Salary</p>
</div>
<form method="post" enctype="multipart/form-data">
<div style="margin: 20px 0;">
<label for="employeeFile"><strong>Select Excel File:</strong></label><br>
<input type="file" name="employeeFile" id="employeeFile" accept=".xlsx,.xls" required>
</div>
<div>
<button type="submit" style="padding: 10px 20px; background: ##2196f3; color: white; border: none; border-radius: 5px; cursor: pointer;">
Upload and Import
</button>
</div>
</form>
<!--- Show sample data format --->
<h3>Sample Data Format</h3>
<cfscript>
sampleData = queryNew(
"EmployeeID,FirstName,LastName,Email,Department,Position,HireDate,Salary",
"varchar,varchar,varchar,varchar,varchar,varchar,date,decimal"
);
queryAddRow(sampleData, [
{
EmployeeID: "EMP001",
FirstName: "John",
LastName: "Smith",
Email: "john.smith@company.com",
Department: "Engineering",
Position: "Software Developer",
HireDate: now(),
Salary: 85000
},
{
EmployeeID: "EMP002",
FirstName: "Jane",
LastName: "Doe",
Email: "jane.doe@company.com",
Department: "Marketing",
Position: "Marketing Manager",
HireDate: now(),
Salary: 75000
}
]);
</cfscript>
<cfdump
var="#sampleData#"
label="Expected Excel Format"
expand="yes">
<cfelseif useSampleData>
<!--- Process with sample data when file upload is not available --->
<h3>Processing Sample Data (File Upload Not Available)...</h3>
<cfscript>
// Use the sample data we created earlier
employeeData = sampleData;
</cfscript>
<div style="background: ##e3f2fd; border: 2px solid ##2196f3; padding: 15px; margin: 15px 0; border-radius: 5px;">
<h4 style="color: blue; margin: 0;">📝 Using Sample Data</h4>
<p>Since file upload is not available, demonstrating with sample employee data.</p>
<p><strong>Records:</strong> #employeeData.recordCount#</p>
</div>
<!--- Display imported data --->
<h3>Sample Employee Data</h3>
<cfdump
var="#employeeData#"
label="Data for Processing (#employeeData.recordCount# records)"
expand="yes"
top="10">
<!--- Continue with validation process (skip to line after file read) --->
<cfset continueWithValidation = true>
<cfelse>
<!--- Process file upload --->
<h3>Processing Upload...</h3>
<cftry>
<!--- Upload the file --->
<cffile
action="upload"
fileField="employeeFile"
destination="#uploadDir#"
nameConflict="makeunique"
result="uploadResult">
<cfscript>
uploadedFile = uploadResult.serverDirectory & "/" & uploadResult.serverFile;
</cfscript>
<div style="background: ##e8f5e9; border: 2px solid ##4caf50; padding: 15px; margin: 15px 0; border-radius: 5px;">
<h4 style="color: green; margin: 0;">✓ File Uploaded Successfully</h4>
<p><strong>Filename:</strong> #uploadResult.clientFile#</p>
<p><strong>Size:</strong> #numberFormat(uploadResult.fileSize / 1024, "0.00")# KB</p>
</div>
<!--- Read Excel file into query --->
<cfspreadsheet
action="read"
src="#uploadedFile#"
query="employeeData"
headerrow="1">
<!--- Display imported data --->
<h3>Imported Employee Data</h3>
<cfdump
var="#employeeData#"
label="Data from Excel (#employeeData.recordCount# records)"
expand="yes"
top="10">
<cfset continueWithValidation = true>
<cfcatch type="any">
<div style="background: ##ffebee; border: 2px solid ##f44336; padding: 20px; margin: 20px 0; border-radius: 5px;">
<h3 style="color: red; margin: 0;">✗ Upload Failed</h3>
<p><strong>Error:</strong> #cfcatch.message#</p>
<p><strong>Detail:</strong> #cfcatch.detail#</p>
<p>Please ensure the file is a valid Excel format with the correct column structure.</p>
</div>
<p><a href="?">Try Again</a></p>
<cfset continueWithValidation = false>
</cfcatch>
</cftry>
</cfif>
<!--- Continue with validation if we have data --->
<cfif (isDefined("continueWithValidation") AND continueWithValidation) OR useSampleData>
<!--- Validate and process data --->
<cfscript>
validRecords = [];
invalidRecords = [];
duplicateRecords = [];
processedCount = 0;
// Simulate existing employee IDs (in production, query database)
existingEmployeeIDs = ["EMP001", "EMP005"];
// Process each row
for (row = 1; row <= employeeData.recordCount; row++) {
employee = {
"employeeID": employeeData.EmployeeID[row],
"firstName": employeeData.FirstName[row],
"lastName": employeeData.LastName[row],
"email": employeeData.Email[row],
"department": employeeData.Department[row],
"position": employeeData.Position[row],
"hireDate": employeeData.HireDate[row],
"salary": employeeData.Salary[row],
"rowNumber": row
};
// Validation
isValid = true;
validationErrors = [];
// Check required fields
if (len(trim(employee.employeeID)) == 0) {
arrayAppend(validationErrors, "Employee ID is required");
isValid = false;
}
if (len(trim(employee.firstName)) == 0) {
arrayAppend(validationErrors, "First Name is required");
isValid = false;
}
if (len(trim(employee.email)) == 0) {
arrayAppend(validationErrors, "Email is required");
isValid = false;
}
// Check for duplicates
if (arrayFind(existingEmployeeIDs, employee.employeeID) > 0) {
arrayAppend(validationErrors, "Employee ID already exists");
employee.errors = validationErrors;
arrayAppend(duplicateRecords, employee);
continue;
}
// Categorize record
if (isValid) {
arrayAppend(validRecords, employee);
processedCount++;
} else {
employee.errors = validationErrors;
arrayAppend(invalidRecords, employee);
}
}
// Import summary
importSummary = {
"totalRecords": employeeData.recordCount,
"validRecords": arrayLen(validRecords),
"invalidRecords": arrayLen(invalidRecords),
"duplicateRecords": arrayLen(duplicateRecords),
"importDate": dateTimeFormat(now(), "yyyy-mm-dd HH:nn:ss"),
"filename": uploadResult.clientFile
};
</cfscript>
<!--- Display import summary --->
<h3>Import Summary</h3>
<cfdump
var="#importSummary#"
label="Import Results"
expand="yes">
<!--- Show valid records --->
<cfif arrayLen(validRecords) GT 0>
<h3 style="color: green;">✓ Valid Records (Ready to Import)</h3>
<cfdump
var="#validRecords#"
label="Records that passed validation"
expand="yes">
<div style="background: ##e8f5e9; border: 2px solid ##4caf50; padding: 15px; margin: 15px 0; border-radius: 5px;">
<h4 style="color: green; margin: 0;">Ready for Database Import</h4>
<p>#arrayLen(validRecords)# employee record(s) validated successfully.</p>
<p><em>In production, these would be inserted into the database.</em></p>
</div>
</cfif>
<!--- Show invalid records --->
<cfif arrayLen(invalidRecords) GT 0>
<h3 style="color: red;">✗ Invalid Records (Errors Found)</h3>
<cfdump
var="#invalidRecords#"
label="Records with validation errors"
expand="yes">
</cfif>
<!--- Show duplicate records --->
<cfif arrayLen(duplicateRecords) GT 0>
<h3 style="color: orange;">⚠ Duplicate Records (Already Exist)</h3>
<cfdump
var="#duplicateRecords#"
label="Records with duplicate Employee IDs"
expand="yes">
</cfif>
<!--- Success/Error summary --->
<cfif arrayLen(invalidRecords) EQ 0 AND arrayLen(duplicateRecords) EQ 0>
<div style="background: ##e8f5e9; border: 2px solid ##4caf50; padding: 20px; margin: 20px 0; border-radius: 5px;">
<h3 style="color: green; margin: 0;">🎉 Import Successful!</h3>
<p>All #importSummary.totalRecords# employee record(s) were validated successfully and are ready for database import.</p>
</div>
<cfelse>
<div style="background: ##fff3e0; border: 2px solid ##ff9800; padding: 20px; margin: 20px 0; border-radius: 5px;">
<h3 style="color: orange; margin: 0;">⚠ Import Completed with Issues</h3>
<p><strong>Valid:</strong> #arrayLen(validRecords)# records</p>
<p><strong>Invalid:</strong> #arrayLen(invalidRecords)# records</p>
<p><strong>Duplicates:</strong> #arrayLen(duplicateRecords)# records</p>
<p>Please correct the errors and re-upload the file.</p>
</div>
</cfif>
<!--- Clean up uploaded file --->
<cfif NOT useSampleData AND isDefined("uploadedFile") AND fileExists(uploadedFile)>
<cftry>
<cffile action="delete" file="#uploadedFile#">
<cfcatch type="any">
<!--- Ignore cleanup errors --->
</cfcatch>
</cftry>
</cfif>
<cfif canUploadFiles>
<p><a href="?" style="padding: 10px 20px; background: ##2196f3; color: white; text-decoration: none; border-radius: 5px; display: inline-block; margin-top: 20px;">
Upload Another File
</a></p>
<cfelse>
<p><a href="?" style="padding: 10px 20px; background: ##2196f3; color: white; text-decoration: none; border-radius: 5px; display: inline-block; margin-top: 20px;">
View Demo Again
</a></p>
</cfif>
</cfif>
<!--- Show alternative when file system is not available --->
<cfif NOT canUploadFiles AND NOT isDefined("form.employeeFile") AND NOT useSampleData>
<div style="background: ##f5f5f5; border: 1px solid ##ccc; padding: 15px; margin: 20px 0; border-radius: 5px;">
<h4>💡 Alternative: Process Excel Data Without File Upload</h4>
<p>When file system access is limited, you can still process Excel data by:</p>
<ol>
<li><strong>Reading from URL:</strong> Use cfhttp to fetch Excel files from external URLs</li>
<li><strong>Binary Upload:</strong> Read uploaded file directly to memory without saving to disk</li>
<li><strong>Database Storage:</strong> Store uploaded files in database BLOB fields</li>
</ol>
<pre style="background: ##fff; padding: 10px; border: 1px solid ##ddd; border-radius: 3px; overflow-x: auto;">
<!--- Example: Read Excel from form without saving to disk --->
<cffile action="readBinary" filefield="employeeFile" variable="excelBinary">
<cfset tempFile = getTempFile(getTempDirectory(), "upload")>
<cffile action="write" file="##tempFile##" output="##excelBinary##">
<cfspreadsheet action="read" src="##tempFile##" query="employeeData">
<cffile action="delete" file="##tempFile##"></pre>
</div>
</cfif>
Monthly sales report generation
Your finance department requires monthly sales reports with detailed formatting, charts-ready data, and multiple worksheets showing different views of sales performance. The reports must be professional, include company branding, and be distributed to executive leadership.
Problem statement
- Need automated monthly sales report generation
- Reports must be professionally formatted
- Require multiple data views in separate sheets
- Must include summary statistics and totals
- Headers and formatting must be consistent
- Reports distributed on first business day of month
- Manual report creation is time-consuming and error-prone
Solution
Use cfspreadsheet with advanced formatting to create multi-sheet workbooks with professional styling.
<cfscript>
// Generate sample sales data for the month
salesData = queryNew(
"SaleDate,Region,SalesRep,ProductCategory,ProductName,Quantity,UnitPrice,TotalSale",
"date,varchar,varchar,varchar,varchar,integer,decimal,decimal"
);
regions = ["North", "South", "East", "West"];
salesReps = ["Alice Johnson", "Bob Martinez", "Carol White", "David Lee", "Emma Davis"];
categories = ["Electronics", "Software", "Hardware", "Accessories"];
// Generate 20 sales records
for (i = 1; i <= 20; i++) {
saleDate = dateAdd("d", -randRange(1, 30), now());
quantity = randRange(1, 10);
unitPrice = randRange(50, 500);
queryAddRow(salesData, {
SaleDate: saleDate,
Region: regions[randRange(1, arrayLen(regions))],
SalesRep: salesReps[randRange(1, arrayLen(salesReps))],
ProductCategory: categories[randRange(1, arrayLen(categories))],
ProductName: "Product " & i,
Quantity: quantity,
UnitPrice: unitPrice,
TotalSale: quantity * unitPrice
});
}
// Calculate summary statistics
totalSales = 0;
for (i = 1; i <= salesData.recordCount; i++) {
totalSales += salesData.TotalSale[i];
}
totalOrders = salesData.recordCount;
averageOrderValue = totalSales / totalOrders;
// Create summary by region
regionSummary = queryNew(
"Region,OrderCount,TotalSales,AvgOrderValue",
"varchar,integer,decimal,decimal"
);
for (region in regions) {
regionOrders = 0;
regionTotal = 0;
for (row = 1; row <= salesData.recordCount; row++) {
if (salesData.Region[row] == region) {
regionOrders++;
regionTotal += salesData.TotalSale[row];
}
}
queryAddRow(regionSummary, {
Region: region,
OrderCount: regionOrders,
TotalSales: regionTotal,
AvgOrderValue: regionOrders > 0 ? regionTotal / regionOrders : 0
});
}
// Set report directory (use expandPath for web-accessible directory)
reportDir = expandPath("./monthly-reports/");
// Create directory if it doesn't exist (with error handling)
try {
if (!directoryExists(reportDir)) {
directoryCreate(reportDir);
}
canWriteFiles = true;
} catch (any e) {
// If we can't create directory, work in memory only
canWriteFiles = false;
reportDir = "File system access not available";
}
reportMonth = dateFormat(now(), "mmmm yyyy");
reportFileName = "Monthly_Sales_Report_" & dateFormat(now(), "yyyy-mm") & ".xlsx";
reportPath = canWriteFiles ? reportDir & reportFileName : "";
</cfscript>
<h2>Monthly Sales Report Generation</h2>
<cfif NOT canWriteFiles>
<div style="background: ##fff3e0; border: 2px solid ##ff9800; padding: 20px; margin: 20px 0; border-radius: 5px;">
<h3 style="color: orange; margin: 0;">⚠ File System Access Limited</h3>
<p>Unable to write files to disk. Report will be created in memory.</p>
<p><strong>For production:</strong> Configure a directory with proper write permissions.</p>
<p><strong>Alternative:</strong> Use cfheader/cfcontent to stream directly to browser.</p>
</div>
</cfif>
<div style="background: ##e8f5e9; border: 2px solid ##4caf50; padding: 20px; margin: 20px 0; border-radius: 5px;">
<h3 style="margin: 0;">📊 Generating Report for #reportMonth#</h3>
</div>
<!--- Display source data --->
<h3>Sales Data</h3>
<cfdump
var="#salesData#"
label="Detailed Sales Transactions (#salesData.recordCount# records)"
expand="no">
<h3>Regional Summary</h3>
<cfdump
var="#regionSummary#"
label="Sales by Region"
expand="yes">
<hr>
<!--- Create formatted Excel workbook --->
<cfscript>
// Create new workbook
workbook = SpreadsheetNew("Detailed Sales", true);
// ===== SHEET 1: Company Header and Sales Details =====
// Add company header (row 1)
SpreadsheetAddRow(workbook, "COMPANY NAME - MONTHLY SALES REPORT");
SpreadsheetMergeCells(workbook, 1, 1, 1, 8);
headerFormat = {};
headerFormat.bold = true;
headerFormat.fontsize = 16;
headerFormat.alignment = "center";
headerFormat.fgcolor = "dark_blue";
headerFormat.color = "white";
SpreadsheetFormatRow(workbook, headerFormat, 1);
// Add report period (row 2)
SpreadsheetAddRow(workbook, "Report Period: " & reportMonth);
SpreadsheetMergeCells(workbook, 2, 2, 1, 8);
periodFormat = {};
periodFormat.bold = true;
periodFormat.fontsize = 12;
periodFormat.alignment = "center";
periodFormat.fgcolor = "light_blue";
SpreadsheetFormatRow(workbook, periodFormat, 2);
// Add blank row
SpreadsheetAddRow(workbook, "");
// Add sales data starting at row 4
SpreadsheetAddRows(workbook, salesData, 4, 1);
// Format header row (row 4)
headerRowFormat = {};
headerRowFormat.bold = true;
headerRowFormat.fgcolor = "light_green";
headerRowFormat.alignment = "center";
headerRowFormat.border = "thin";
SpreadsheetFormatRow(workbook, headerRowFormat, 4);
// Format data rows with borders
borderFormat = {};
borderFormat.border = "thin";
for (row = 5; row <= salesData.recordCount + 4; row++) {
SpreadsheetFormatRow(workbook, borderFormat, row);
}
// Note: Currency formatting removed to simplify code
// Excel will display numbers, you can format them manually in Excel if needed
// Set column widths
SpreadsheetSetColumnWidth(workbook, 1, 12); // SaleDate
SpreadsheetSetColumnWidth(workbook, 2, 12); // Region
SpreadsheetSetColumnWidth(workbook, 3, 18); // SalesRep
SpreadsheetSetColumnWidth(workbook, 4, 15); // ProductCategory
SpreadsheetSetColumnWidth(workbook, 5, 20); // ProductName
SpreadsheetSetColumnWidth(workbook, 6, 10); // Quantity
SpreadsheetSetColumnWidth(workbook, 7, 12); // UnitPrice
SpreadsheetSetColumnWidth(workbook, 8, 12); // TotalSale
// Add totals row
totalRow = salesData.recordCount + 5;
SpreadsheetSetCellValue(workbook, "TOTALS", totalRow, 5);
SpreadsheetSetCellValue(workbook, totalOrders, totalRow, 6);
SpreadsheetSetCellValue(workbook, totalSales, totalRow, 8);
totalRowFormat = {};
totalRowFormat.bold = true;
totalRowFormat.fgcolor = "gold";
totalRowFormat.border = "medium";
totalRowFormat.alignment = "right";
SpreadsheetFormatRow(workbook, totalRowFormat, totalRow);
// ===== SHEET 2: Regional Summary =====
SpreadsheetCreateSheet(workbook, "Regional Summary");
SpreadsheetSetActiveSheet(workbook, "Regional Summary");
// Add header
SpreadsheetAddRow(workbook, "REGIONAL SALES SUMMARY - " & reportMonth);
SpreadsheetMergeCells(workbook, 1, 1, 1, 4);
regionHeaderFormat = {};
regionHeaderFormat.bold = true;
regionHeaderFormat.fontsize = 14;
regionHeaderFormat.alignment = "center";
regionHeaderFormat.fgcolor = "dark_blue";
regionHeaderFormat.color = "white";
SpreadsheetFormatRow(workbook, regionHeaderFormat, 1);
SpreadsheetAddRow(workbook, "");
// Add summary data
SpreadsheetAddRows(workbook, regionSummary, 3, 1);
// Format header
regionDataHeaderFormat = {};
regionDataHeaderFormat.bold = true;
regionDataHeaderFormat.fgcolor = "light_green";
regionDataHeaderFormat.alignment = "center";
regionDataHeaderFormat.border = "thin";
SpreadsheetFormatRow(workbook, regionDataHeaderFormat, 3);
// Format data rows with borders
regionBorderFormat = {};
regionBorderFormat.border = "thin";
for (row = 4; row <= regionSummary.recordCount + 3; row++) {
SpreadsheetFormatRow(workbook, regionBorderFormat, row);
}
// Note: Currency formatting removed to simplify code
// Numbers will display in Excel and can be formatted there
// Set column widths
SpreadsheetSetColumnWidth(workbook, 1, 15);
SpreadsheetSetColumnWidth(workbook, 2, 12);
SpreadsheetSetColumnWidth(workbook, 3, 15);
SpreadsheetSetColumnWidth(workbook, 4, 15);
// ===== SHEET 3: Executive Summary =====
SpreadsheetCreateSheet(workbook, "Executive Summary");
SpreadsheetSetActiveSheet(workbook, "Executive Summary");
// Add title
SpreadsheetAddRow(workbook, "EXECUTIVE SUMMARY");
SpreadsheetMergeCells(workbook, 1, 1, 1, 2);
summaryTitleFormat = {};
summaryTitleFormat.bold = true;
summaryTitleFormat.fontsize = 16;
summaryTitleFormat.alignment = "center";
summaryTitleFormat.fgcolor = "dark_blue";
summaryTitleFormat.color = "white";
SpreadsheetFormatRow(workbook, summaryTitleFormat, 1);
// Add metrics
SpreadsheetAddRow(workbook, "");
SpreadsheetAddRow(workbook, ["Metric", "Value"]);
summaryHeaderFormat = {};
summaryHeaderFormat.bold = true;
summaryHeaderFormat.fgcolor = "light_blue";
SpreadsheetFormatRow(workbook, summaryHeaderFormat, 3);
SpreadsheetAddRow(workbook, ["Total Sales", dollarFormat(totalSales)]);
SpreadsheetAddRow(workbook, ["Total Orders", totalOrders]);
SpreadsheetAddRow(workbook, ["Average Order Value", dollarFormat(averageOrderValue)]);
SpreadsheetAddRow(workbook, ["Report Month", reportMonth]);
SpreadsheetAddRow(workbook, ["Generated On", dateTimeFormat(now(), "yyyy-mm-dd HH:nn")]);
// Set column widths
SpreadsheetSetColumnWidth(workbook, 1, 25);
SpreadsheetSetColumnWidth(workbook, 2, 20);
// Try to save the workbook
if (canWriteFiles) {
try {
SpreadsheetWrite(workbook, reportPath, true);
reportSaved = true;
} catch (any e) {
reportSaved = false;
}
} else {
reportSaved = false;
}
</cfscript>
<cfif reportSaved>
<div style="background: ##e8f5e9; border: 2px solid ##4caf50; padding: 20px; margin: 20px 0; border-radius: 5px;">
<h3 style="color: green; margin: 0;">✓ Monthly Sales Report Generated Successfully</h3>
<p><strong>Filename:</strong> #reportFileName#</p>
<p><strong>Location:</strong> #reportPath#</p>
<p><strong>Sheets:</strong> Detailed Sales, Regional Summary, Executive Summary</p>
<p><strong>Total Records:</strong> #salesData.recordCount# sales transactions</p>
</div>
<cfelse>
<div style="background: ##e8f5e9; border: 2px solid ##4caf50; padding: 20px; margin: 20px 0; border-radius: 5px;">
<h3 style="color: green; margin: 0;">✓ Monthly Sales Report Created in Memory</h3>
<p><strong>Filename:</strong> #reportFileName#</p>
<p><strong>Sheets:</strong> Detailed Sales, Regional Summary, Executive Summary</p>
<p><strong>Total Records:</strong> #salesData.recordCount# sales transactions</p>
<p><em>In production with file permissions, this would be saved to disk.</em></p>
</div>
</cfif>
<!--- Display report statistics --->
<cfscript>
reportStats = {};
reportStats.reportMonth = reportMonth;
reportStats.totalSales = dollarFormat(totalSales);
reportStats.totalOrders = totalOrders;
reportStats.averageOrderValue = dollarFormat(averageOrderValue);
reportStats.generatedOn = dateTimeFormat(now(), "yyyy-mm-dd HH:nn:ss");
if (reportSaved) {
reportStats.fileSize = numberFormat(getFileInfo(reportPath).size / 1024, "0.00") & " KB";
} else {
reportStats.fileSize = "N/A (in memory)";
}
reportStats.sheets = "Detailed Sales, Regional Summary, Executive Summary";
reportStats.saved = reportSaved ? "Yes" : "No (memory only)";
</cfscript>
<h3>Report Statistics</h3>
<cfdump
var="#reportStats#"
label="Generated Report Details"
expand="yes">
<!--- Show alternative download method --->
<cfif NOT canWriteFiles>
<div style="background: ##f5f5f5; border: 1px solid ##ccc; padding: 15px; margin: 20px 0; border-radius: 5px;">
<h4>💡 Alternative: Stream Report to Browser</h4>
<p>When file system access is limited, stream the Excel report directly:</p>
<pre style="background: ##fff; padding: 10px; border: 1px solid ##ddd; border-radius: 3px; overflow-x: auto;">
<cfscript>
// Get binary data from workbook
binaryData = SpreadsheetReadBinary(invoice);
</cfscript>
<cfheader name="Content-Disposition"
value="attachment; filename=#reportFileName#">
<cfcontent type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
variable="##binaryData##" reset="true"></pre>
</div>
</cfif>
