I'm trying to create an RSS feed from data in database using cffeed in ColdFusion. But when I try to run it, I get an error on line 24 (which is the cffeed line):
Detail: value should be a String
Message: Exception while creating feed.
Here is the code:
<cfquery name="messages" datasource="showcase_Uk">
select * from t_items where pid = 2 and spid = 45 ORDER BY uploadDate DESC
</cfquery>
<cfset myStruct = StructNew() />
<cfset mystruct.link = "http://showcase.com" />
<cfset myStruct.title = "Examples" />
<cfset mystruct.description = "Examples from UK Showcase" />
<cfset mystruct.pubDate = Now() />
<cfset mystruct.version = "rss_2.0" />
<cfset myStruct.item = ArrayNew(1) />
<cfloop query="messages">
<cfset myStruct.item[currentRow] = StructNew() />
<cfset myStruct.item[currentRow].guid = structNew() />
<cfset myStruct.item[currentRow].guid.isPermaLink="YES" />
<cfset myStruct.item[currentRow].guid.value = '#messages.id#' />
<cfset myStruct.item[currentRow].pubDate = createDate(year(#messages.uploadDate#), month(#messages.uploadDate#), day(#messages.uploadDate#)) />
<cfset myStruct.item[currentRow].title = xmlFormat(#messages.name#) />
<cfset myStruct.item[currentRow].description = StructNew() />
<cfset myStruct.item[currentRow].description.value = xmlFormat(#messages.description#)>
</cfloop>
<cffeed action="create" name="#myStruct#" overwrite="true" xmlVar="myXML">
<cfoutput>#myXML#</cfoutput>
Any help would be great.
I've tested the following code at http://cflive.net/, where it works well under Adobe ColdFusion. Therefore I believe that the error lies within the query data.
<!--- Your query
<cfquery name="messages" datasource="showcase_Uk">
select * from t_items where pid = 2 and spid = 45 ORDER BY uploadDate DESC
</cfquery>
--->
<!--- Building a new Query --->
<cfset messages = QueryNew("id,uploadDate,name,description")>
<cfset QueryAddRow(messages, 1)>
<cfset QuerySetCell(messages, "id", "123", 1)>
<cfset QuerySetCell(messages, "description", "a string", 1)>
<cfset QuerySetCell(messages, "name", "another string", 1)>
<cfset QuerySetCell(messages, "uploadDate", Now(), 1)>
<!--- From here on it is your code again --->
<cfset myStruct = StructNew() />
<cfset mystruct.link = "http://showcase.com" />
<cfset myStruct.title = "Examples" />
<cfset mystruct.description = "Examples from UK Showcase" />
<cfset mystruct.pubDate = Now() />
<cfset mystruct.version = "rss_2.0" />
<cfset myStruct.item = ArrayNew(1) />
<cfloop query="messages">
<cfset myStruct.item[currentRow] = StructNew() />
<cfset myStruct.item[currentRow].guid = structNew() />
<cfset myStruct.item[currentRow].guid.isPermaLink="YES" />
<cfset myStruct.item[currentRow].guid.value = '#messages.id#' />
<cfset myStruct.item[currentRow].pubDate = createDate(year(#messages.uploadDate#), month(#messages.uploadDate#), day(#messages.uploadDate#)) />
<cfset myStruct.item[currentRow].title = xmlFormat(#messages.name#) />
<cfset myStruct.item[currentRow].description = StructNew() />
<cfset myStruct.item[currentRow].description.value = xmlFormat(#messages.description#)>
</cfloop>
<cffeed action="create" name="#myStruct#" overwrite="true" xmlVar="myXML">
<!--- Show the complete xml --->
<cfoutput>#myXML#</cfoutput>
<br><br>
<cfoutput>#XMLFormat(myXML)#</cfoutput>
Related
My function calls the SendGrid API. It returns an Array + structure. I'm writing a function to return a CFQuery dataset.
Goal
I want to pass a deserialized data object to my function and get a query dataset.
Here is my working code and the output:
<cfparam name="variables.ddata" default="#structnew()#">
<!--- API Call Code here --->
<cfset arr = DESerializeJSON(returnStruct.Filecontent) />
<cfdump var="#arr#">
My code:
<cfset arrayit(arrobj= arr) >
<cfdump var="#variables.ddata#" >
<cffunction name="arrayit" access="public" returntype="void">
<cfargument name="arrobj" type="array" required="yes">
<cfset var arr=arguments.arrobj />
<cfloop from="1" to = "#arrayLen(arr)#" index="i">
<cfif isValid("string", arr[i])>
<cfset StructInsert(variables.ddata, i, arr[i]) />
</cfif>
<cfif isstruct(arr[i])>
<cfset structit(structobj = arr[i]) />
</cfif>
</cfloop>
</cffunction>
<cffunction name="structit" access="public" returntype="void" output="yes">
<cfargument name="structobj" type="any" required="yes">
<cfset stru = arguments.structobj />
<cfloop collection="#stru#" item="S">
<cfif isValid("string", stru[S])>
<cfset StructInsert( variables.ddata, S, stru[S]) />
</cfif>
<cfif isarray(stru[S])>
<cfset arrayit(arrobj = stru[S]) >
</cfif>
</cfloop>
</cffunction>
Result:
When I add this line in my function
<cfif isstruct(stru[S])>
<cfset variables.ddata = arrayit(arrobj = stru[S]) />
</cfif>
An error occurs:
Element type is undefined in a CFML structure referenced as part of an
expression. The error occurred on line 71.
** Full Code**
<cfsavecontent variable="returnStruct.Filecontent">
[{"date":"2016-04-05","stats":[{"type":"category","name":"5","metrics":{"blocks":1,"bounce_drops":0,"bounces":9,"clicks":4,"deferred":1,"delivered":1,"invalid_emails":8,"opens":4,"processed":1,"requests":1,"spam_report_drops":0,"spam_reports":1,"unique_clicks":3,"unique_opens":3,"unsubscribe_drops":0,"unsubscribes":9}}]}]
</cfsavecontent>
<cfset arr = DESerializeJSON(returnStruct.Filecontent) />
<cfloop from="1" to="#arrayLen(arr)#" index="i">
<cfif isValid("string", arr[i])>
<cfset StructInsert(variables.ddata, i, arr[i],true ) />
</cfif>
<cfif isstruct(arr[i])>
<cfsavecontent variable="rr">
<cfdump var="#arr[i]#" label="Line 48 ERROR" >
</cfsavecontent>
<cfset NotifyErrorAdmin(emailBody = "#rr#" ,emailsubject = "Line 48") />
<cfset structit(structobj = arr[i]) />
</cfif>
<cfif isarray(arr[i])>
<cfsavecontent variable="rr">
<cfdump var="#arr[i]#" label="Line 54 ERROR" >
</cfsavecontent>
<cfset NotifyErrorAdmin(emailBody = "#rr#" ,emailsubject = "Line 54") />
<cfset arrayit(arrobj = arr[i]) >
</cfif>
</cfloop>
</cffunction>
<cffunction name = "structit" access="public" returntype="void" output="yes">
<cfargument name = "structobj" type="any" required="yes">
<cfset stru = arguments.structobj />
<cfloop collection="#stru#" item="S">
<cfif isValid("string", stru[S])>
<cfset StructInsert( variables.ddata, S, stru[S],true) />
</cfif>
<cfif isarray(stru[S])>
<cfsavecontent variable="rr">
<cfdump var="#stru[S]#" label="Line 86 ERROR" >
</cfsavecontent>
<cfset NotifyErrorAdmin(emailBody = "#rr#" ,emailsubject = "Line 87") />
<cfset arrayit(arrobj = stru[S]) >
</cfif>
<cfif isstruct(stru[S])>
<cfsavecontent variable="rr">
<cfdump var="#stru[S]#" label="Line 97 ERROR" >
</cfsavecontent>
<cfset NotifyErrorAdmin(emailBody = "#rr#" ,emailsubject = "Line 97") />
<cfset structit(structobj = stru[S]) />
</cfif>
</cfloop>
</cffunction>
ERROR
Your UDF arrayit accepts an argument of type array but when that condition is true then a struct is being passed so, the error.
i.e.,
<cfif isStruct(stru[S])>
<!--- This means stru[S] is a struct --->
<cfset variables.ddata = arrayit(arrobj = stru[S])>
<!--- arrObj should be of type 'array' --->
</cfif>
So, it should be:
<cfif isStruct(stru[S])>
<cfset variables.ddata = structit(structobj = stru[S])>
</cfif>
But, the error for this case will be different than that you have added.
Additionally,
StructInsert() takes an optional argument allowoverwrite which is by default false and according to docs:
if key exists and allowoverwrite = "False", ColdFusion throws an
exception.
I just did it! :) just wanted to share my project with you guys also hope it will help someone else also...
Request if you guys find anything you feel I can improve please share.
Special Thanks for response on my post. #Beginner & #Leigh
API Call Json Return: 1
<cfsavecontent variable="returnStruct.Filecontent">
[{"date":"2016-04-05","stats":[{"type":"category","name":"5","metrics":{"blocks":1,"bounce_drops":0,"bounces":9,"clicks":4,"deferred":1,"delivered":1,"invalid_emails":8,"opens":4,"processed":1,"requests":1,"spam_report_drops":0,"spam_reports":1,"unique_clicks":3,"unique_opens":3,"unsubscribe_drops":0,"unsubscribes":9}}]}]
</cfsavecontent>
<cfset arr = DESerializeJSON(returnStruct.Filecontent) />
CFC : 2
<cfcomponent>
<cfparam name="variables.qryclsvar" default="" type="any"/>
<cfparam name="variables.qryclsvarfg" default="true" type="any"/>
<cffunction name="APItoquery" access="public" returntype="any">
<cfargument name = "APIobj" type="any" required="yes">
<cfset var vAPIobj = arguments.APIobj />
<cfset var APIDATA = structnew() />
<cfset var APIDATAqr = "" />
<cftry>
<cfloop from="1" to="#arrayLen(vAPIobj)#" index="jj">
<cfif isarray(vAPIobj[jj])>
<cfset APIDATA = arrayit(structobj = vAPIobj[jj] ,datastruct = APIDATA) />
</cfif>
<cfif isstruct(vAPIobj[jj])>
<cfset APIDATA = structit(structobj = vAPIobj[jj],datastruct = APIDATA) />
</cfif>
<cfif NOT StructIsEmpty(APIDATA)>
<!--- Add in query object --->
<cfset APIDATAqr = structtoquery(structobj= APIDATA) />
<cfelse>
<cfset APIDATAqr ="NO Data Found!" />
</cfif>
</cfloop>
<cfcatch>
<cfdump var="#cfcatch#" label="APItoquery">
</cfcatch>
</cftry>
<cfreturn APIDATAqr>
</cffunction>
<cffunction name = "arrayit" access="public" returntype="any">
<cfargument name = "arrobj" type="any" required="yes">
<cfargument name = "datastruct" type="any" required="yes" >
<cfset var arr = arguments.arrobj />
<cfset var arrdata = arguments.datastruct />
<cftry>
<cfloop from="1" to="#arrayLen(arr)#" index="i">
<cfif ArrayContains(arr, i) >
<cfset StructInsert(arrdata, i, arr[i],true ) />
</cfif>
<cfif isarray(arr[i])>
<cfset arrdata = arrayit(arrobj = arr[i] ,datastruct = arrdata) >
</cfif>
<cfif isstruct(arr[i]) >
<cfset stdata = structit(structobj = arr[i],datastruct = arrdata) />
</cfif>
</cfloop>
<cfcatch>
<cfdump var="#cfcatch#" label="arrayit">
</cfcatch>
</cftry>
<cfreturn arrdata>
</cffunction>
<cffunction name = "structit" access="public" returntype="any" output="yes">
<cfargument name = "structobj" type="any" required="yes">
<cfargument name = "datastruct" type="any" required="yes">
<cfset var stru = arguments.structobj />
<cfset var stdata = arguments.datastruct />
<cftry>
<cfloop collection="#stru#" item="S">
<cfif isarray(stru[S])>
<cfset stdata = arrayit(arrobj = stru[S] ,datastruct = stdata) >
<cfelseif isstruct(stru[S]) >
<cfset stdata = structit(structobj = stru[S],datastruct = stdata) />
<cfelse>
<cfset StructInsert( stdata, S, stru[S],true) />
</cfif>
</cfloop>
<cfcatch>
<cfdump var="#cfcatch#" label="structit">
</cfcatch>
</cftry>
<cfreturn stdata>
</cffunction>
<cffunction name = "structtoquery" access="public" returntype="any" output="yes">
<cfargument name = "structobj" type="any" required="yes">
<cfset var vstructobj = arguments.structobj />
<cfset var cols = StructKeyList(vstructobj)>
<cfset var colstyp = "">
<cftry>
<cfif variables.qryclsvarfg EQ true>
<cfloop from="1" to="#listlen(cols,',')#" index="L">
<cfset colstyp = ListAppend(colstyp,"VarChar",",")>
</cfloop>
<!--- Create a new query. --->
<cfset variables.qryclsvar = queryNew(
'#cols#',
'#colstyp#'
)>
<cfset variables.qryclsvarfg = false>
</cfif>
<cfset QueryAddRow(variables.qryclsvar, 1)>
<cfloop collection="#vstructobj#" item="sd">
<cfset QuerySetCell(variables.qryclsvar, "#sd#", vstructobj[sd])>
</cfloop>
<cfcatch>
<cfdump var="#cfcatch#" label="structit">
</cfcatch>
</cftry>
<cfreturn variables.qryclsvar>
</cffunction>
</cfcomponent>
CFM : 3
<cfset sgObj = createobject("component","cfc.mycfc") />
<cfset mystruct = sgObj.APItoquery(APIobj= arr1) >
<cfdump var="#mystruct#" label="mystruct">
MA ! ....
We are getting this error in both ColdFusion 9 and ColdFusion 11 servers in production. I originally thought is related to ColdFusion 9 and JavaHeap space or not enough memory. We moved this process to run on a brand new server (ColdFusion 11) where nothing else is running and has a lot of memory and we still get the error. Here is some of the code for this cfm page:
<cfset variables.email_count = 0>
<!--- email notifications --->
<cfoutput query="getOrdersForNotification" group="order_id">
<cfset variables.inv = "">
<cfset variables.usePdf = false>
<cfif isDefined("application.feature_list_using_pdf_attachment")
and listFindNoCase(application.feature_list_using_pdf_attachment, "injection scheduler", ",")
>
<cfset variables.usePdf = true>
</cfif>
<cfthread name="InjectionSchdEmail#dateFormat(now(), 'mmdd')#_#timeFormat(now(), 'HHmmss')#_#getOrdersForNotification.order_id#"
threadOrderId="#getOrdersForNotification.order_id#"
threadMemberId="#getOrdersForNotification.member_id#"
threadNotificationEmail="#getOrdersForNotification.notification_email#"
threadDateReq="#getOrdersForNotification.date_req#"
threadStoreCode="#getOrdersForNotification.store_code#"
threadStoreName="#getOrdersForNotification.store_name#"
threadToGoLabel="#application.togo_label#"
threadOrderTotal="#getOrdersForNotification.order_total#"
threadDelTimeValueFront="#getOrdersForNotification.del_time_value_front#"
threadSubject="#variables.subjectAndBodyTemplates.subject#"
threadBody="#variables.subjectAndBodyTemplates.body#"
threadFromEmail="#variables.fromEmail#"
threadLocalNow="#variables.localNow#"
threadLocalNowInt="#variables.localNowInt#"
threadDs="#ds#"
threadUsePdf="#variables.usePdf#"
>
<cftry>
<cfset url.order_id = threadOrderId>
<cfset url.member_id = threadMemberId>
<cfsavecontent variable="variables.inv">
<cfinclude template="invoicedeska.cfm">
</cfsavecontent>
<cfset variables.order_day=dateFormat(application.UdfService.toSlashDate(threadDateReq), 'mmm dd')>
<cfset local.subject = threadSubject>
<cfset local.subject = ReplaceNoCase(local.subject, "[Store Code]", threadStoreCode, "all")>
<cfset local.subject = ReplaceNoCase(local.subject, "[Takeout Label]", threadToGoLabel, "all")>
<cfset local.subject = ReplaceNoCase(local.subject, "[Order ID]", threadOrderId, "all")>
<cfset local.subject = ReplaceNoCase(local.subject, "[Order Total]", NumberFormat(threadOrderTotal,"9,999.99"), "all")>
<cfset local.subject = ReplaceNoCase(local.subject, "[Required Time]", threadDelTimeValueFront, "all")>
<cfset local.subject = ReplaceNoCase(local.subject, "[Required Date]", variables.order_day, "all")>
<cfset local.body = threadBody>
<cfset local.body = ReplaceNoCase(local.body, "[Store Code]", threadStoreCode, "all")>
<cfset local.body = ReplaceNoCase(local.body, "[Store Name]", threadStoreName, "all")>
<cfset local.body = ReplaceNoCase(local.body, "[Order ID]", threadOrderId, "all")>
<cfset local.body = ReplaceNoCase(local.body, "[Order Total]", NumberFormat(threadOrderTotal,"9,999.99"), "all")>
<cfset local.body = ReplaceNoCase(local.body, "[Required Time]", threadDelTimeValueFront, "all")>
<cfset local.body = ReplaceNoCase(local.body, "[Required Date]", variables.order_day, "all")>
<cfset local.body = "<span style='font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px; color: ##000000'>#application.UdfService.multiLiner(local.body)#</span>">
<cfif threadUsePdf>
<!--- PDF version --->
<cfdocument
format="PDF"
name="variables.attachment"
localURL="#application.pdf_localURL#"
orientation="#application.pdf_orientation#"
marginleft="#application.pdf_marginleft#"
marginright="#application.pdf_marginright#"
margintop="#application.pdf_margintop#"
marginbottom="#application.pdf_marginbottom#"
unit="#application.pdf_unit#"
scale="#application.pdf_scale#"
>
#variables.inv#
</cfdocument>
<cfelse>
<!--- HTML version --->
<cfset variables.attachment = variables.inv>
</cfif>
<cfmail to="#threadNotificationEmail#" from="#threadFromEmail#" subject="#local.subject#" type="html">
#local.body#
<cfif isDefined("variables.attachment") and threadUsePdf eq false>
<cfmailparam
file="invoice_#threadOrderId#_#threadLocalNowInt#.html"
type="application/html"
content="#variables.attachment#"
/>
<cfelseif isDefined("variables.attachment") and threadUsePdf>
<cfmailparam
file="invoice_#threadOrderId#_#threadLocalNowInt#.pdf"
type="application/pdf"
content="#variables.attachment#"
/>
</cfif>
</cfmail>
<cfset invoice_emailed = application.MessageService.setEmailedInvoice(orderId = threadOrderId, localNow = threadLocalNow, emailAddress = threadNotificationEmail, datasource = threadDs)>
<cfcatch type="any">
<cfset variables.attachment = "">
<cfmail from="erroralerts#monkeymediasoftware.com" to="erroralerts#monkeymediasoftware.com" type="html" subject="POS injection notification email faliure">
<cfif isDefined("cgi.server_name")>
Server: <b>#cgi.server_name#</b>
</cfif>
<cfdump var="#cfcatch#" label="cfcatch"><br />
<cfdump var="#threadOrderId#" label="threadOrderId"><br />
<cfdump var="#threadMemberId#" label="threadMemberId"><br />
<cfdump var="#threadNotificationEmail#" label="threadNotificationEmail"><br />
<cfdump var="#threadDateReq#" label="threadDateReq"><br />
<cfdump var="#threadStoreCode#" label="threadStoreCode"><br />
<cfdump var="#threadStoreName#" label="threadStoreName"><br />
<cfdump var="#threadToGoLabel#" label="threadToGoLabel"><br />
<cfdump var="#threadOrderTotal#" label="threadOrderTotal"><br />
<cfdump var="#threadDelTimeValueFront#" label="threadDelTimeValueFront"><br />
<cfdump var="#local.subject#" label="local.subject"><br />
<cfdump var="#local.body#" label="local.body"><br />
<cfdump var="#threadFromEmail#" label="threadFromEmail"><br />
<cfdump var="#threadLocalNow#" label="threadLocalNow"><br />
<cfdump var="#threadLocalNowInt#" label="threadLocalNowInt"><br />
<cfdump var="#threadDs#" label="threadDs"><br />
<cfdump var="#threadUsePdf#" label="threadUsePdf"><br />
<cfdump var="#variables.inv#" label="variables.inv"><br />
</cfmail>
<cfrethrow />
</cfcatch>
</cftry>
</cfthread>
<cfset variables.email_count = variables.email_count + 1>
</cfoutput>
<p></p><cfoutput>#variables.email_count# emails sent # #local_now()#</cfoutput>
Error:
Element EMAIL_COUNT is undefined in VARIABLES.
The error occurred on line
I'm getting an error when producing a multi-page PDF.
The pages attribute is not specified for the MERGE action in the cfpdf tag.
The line that is causing the issue is: <cfpdf action="merge" source="#ArrayToList(variables.pdfList)#" destination="promega.pdf" overwrite="yes" />
I tried looking in Adobe's documentation bug cannot find an attribute pages for the merge action. Thoughts?
<!--- Append PDF to list for merge printing later --->
<cfset ArrayAppend(variables.pdfList, "#expandPath('.')#\general.pdf") />
<cfset variables.userAgenda = GetAttendeeSchedule(
variables.event_key,
variables.badgeNum
) />
<!--- Field CFID is the id of the agenda item; use this for certificate selection --->
<cfif variables.userAgenda.recordcount>
<cfloop query="variables.userAgenda">
<cfset variables.title = Trim(variables.userAgenda.CUSTOMFIELDNAMEONFORM) />
<cfpdfform source="#expandPath('.')#\promega_certificate.pdf" destination="#cfid#.pdf" action="populate">
<cfset variables.startdate = replace(CUSTOMFIELDSTARTDATE, "T", " ") />
<cfpdfformparam name="WORKSHOP" value="#variables.title#">
<cfpdfformparam name="NAME" value="#variables.badgeInfo.FirstName# #variables.badgeInfo.LastName#">
<cfpdfformparam name="STARTDATE" value="#DateFormat(variables.startdate, "medium" )#">
</cfpdfform>
<!--- Append PDF to list for merge printing later --->
<cfset ArrayAppend(variables.pdfList, "#expandPath('.')#\#cfid#.pdf") />
</cfloop>
</cfif>
<cfif ArrayLen(variables.pdfList)>
<cfpdf action="merge" source="#ArrayToList(variables.pdfList)#" destination="promega.pdf" overwrite="yes" />
<!--- Delete individual files --->
<cfloop list="#ArrayToList(variables.pdfList)#" index='i'>
<cffile action="delete" file="#i#" />
</cfloop>
<cftry>
<cffile action="delete" file="#expandPath('.')#\general.pdf" />
<cfcatch></cfcatch>
</cftry>
<cfheader name="Content-Disposition" value="attachment;filename=promega.pdf">
<cfcontent type="application/octet-stream" file="#expandPath('.')#\promega.pdf" deletefile="Yes">
<cflocation url="index.cfm" addtoken="false" />
</cfif>
This happens when source is a single file rather than a comma separated list of files. I'm guessing that if it's a single file is is expecting to extract some pages rather than add.
I tried the following on my coldfusion 9 machine and it worked just fine:
<cfset strPath = GetDirectoryFromPath(GetCurrentTemplatePath()) />
<Cfset pdflist = arrayNew(1)>
<Cfset pdflist[1] = "#strPath#page1.pdf">
<Cfset pdflist[2] = "#strPath#page2.pdf">
<cfpdf action="merge" source="#ArrayToList(pdflist)#" destination="#strPath#merged.pdf" overwrite="yes" />
You could try to merge the pages like this and check whether you still get an error:
<cfset strPath = GetDirectoryFromPath(GetCurrentTemplatePath()) />
<Cfset pdflist = arrayNew(1)>
<Cfset pdflist[1] = "#strPath#page1.pdf">
<Cfset pdflist[2] = "#strPath#page2.pdf">
<cfpdf action="merge" destination="#strPath#merged.pdf" overwrite="yes">
<Cfloop from=1 to="#arraylen(pdflist)#" index="x">
<cfpdfparam source="#pdfList[x]#">
</cfloop>
</cfpdf>
I am working on watermarking an image and am having a problem with my code. It does create a watermark in the bottom right side corner, but the text is not written.
Can anyone spot what is wrong with the code?
<cfset objImage = ImageRead("#UploadDir2#\#uploadfile#") />
<cfset objImage2 = ImageRead("#UploadDir2#\#uploadfile#") />
<cfset ImageResize(objImage,800,"")>
<cfif form.textonImage NEQ "">
<cfset objWatermark = ImageNew("",20,20,"rgb","##F0F0F0")/>
<cfset ImageSetDrawingColor(objWatermark,"##000000") />
<cfset ImageDrawRect(objWatermark,0,0,(objWatermark.GetWidth() - 1),(objWatermark.GetHeight() - 1)) />
<cfset ImageSetAntialiasing(objWatermark,"on") />
<cfset objAttributes = {Font = "Verdana",Size = "8",Style = "bold"} />
<cfset ImageDrawText(objWatermark,"#form.textonImage#",11,40,objAttributes) />
<cfset ImageSetDrawingTransparency(objImage,60) />
<cfset ImagePaste(objImage,objWatermark,(objImage.GetWidth() - objWatermark.GetWidth() - 0),(objImage.GetHeight() - objWatermark.GetHeight() - 0)) />
</cfif>
<cfset ImageWrite(objImage,"#UploadDir2#\#uploadfile#")>
<cfset ImageResize(objImage2,#request.pic_th_width#,"")>
<cfif form.textonImage IS NOT "">
<cfset objWatermark = ImageNew("",#request.pic_th_width#,#request.pic_th_width#,"rgb","##F0F0F0")/>
<cfset ImageSetDrawingColor(objWatermark,"##000000") />
<cfset ImageDrawRect(objWatermark,0,0,(objWatermark.GetWidth() - 0),(objWatermark.GetHeight() - 0)) />
<cfset ImageSetAntialiasing(objWatermark,"on") />
<cfset objAttributes = {Font = "Verdana",Size = "20",Style = "bold"} />
<cfset ImageDrawText(objWatermark,"#form.textonImage#",11,40,objAttributes) />
<cfset ImageSetDrawingTransparency(objImage2,60) />
<cfset ImagePaste(objImage2,objWatermark,(objImage2.GetWidth() - objWatermark.GetWidth() - 0),(objImage2.GetHeight() - objWatermark.GetHeight() - 0)) />
</cfif>
EDIT:
I answered my own question, so let's delete it or ignore it.
Does anyone have an example of this? Google is not my friend tonight. I have the newest version of FusionCharts. I'm trying to figure out how to save a graph as an image file to email it.
I know how to save and then insert images into HTML emails, and I've done this before with other graph products. I just cannot fine 1 good example of how to do this with Fusioncharts.
Thanks!
Use the following code in a template and point the imageSaveURL property at that template.
Your chart submits all necessary data for the chart to be reconstructed. In my example I'm serving it to the browser but you could save it locally and then attach to a cfmail if necessary.
I'm pretty sure I got this from the fusioncharts forums originally. This was updated for fusioncharts 3.1.
<cfif structKeyExists(Form, "width") >
<cfset width = int(Form.width) />
<cfelse>
<cfset width = int(Form.Meta_Width) />
</cfif>
<cfif structKeyExists(Form, "height") >
<cfset height = int(Form.height) />
<cfelse>
<cfset height = int(Form.Meta_Height) />
</cfif>
<cfif structKeyExists(Form, "data") >
<cfset Form.data = Form.data />
<cfelse>
<cfif structKeyExists(Form, "stream") >
<cfset Form.data = Form.stream />
</cfif>
</cfif>
<cfset user = viewState.getValue("user", structNew()) />
<!--- Impose some limits to mitigate DOS attacks --->
<cfif Not (0 lte width and width lte 5000)>
<cfthrow message="Width out of range." />
</cfif>
<cfif Not (0 lte height and height lte 5000)>
<cfthrow message="Height out of range." />
</cfif>
<!--- Check if we have the chart data --->
<cfif Not StructKeyExists(Form, "data") or Not Len(Trim( Form.data ))>
<cfthrow message="Image Data not supplied." />
</cfif>
<!--- Default background color is white --->
<cfif Not StructKeyExists(Form, "bgcolor") or Not Len(Trim( Form.bgcolor ))>
<cfset Form.bgcolor = "FFFFFF" />
</cfif>
<cfset gColor = CreateObject("java", "java.awt.Color") />
<cfset chart = CreateObject("java", "java.awt.image.BufferedImage") />
<cfset chart.init( JavaCast("int", width), JavaCast("int", height), chart.TYPE_3BYTE_BGR) />
<cfset gr = chart.createGraphics() />
<cfset gr.setColor( gColor.decode("##" & Form.bgcolor) ) />
<cfset gr.fillRect(0, 0, JavaCast("int", width), JavaCast("int", height)) />
<!--- Get rows with pixels --->
<cfset rows = ListToArray(Form.data, ";") />
<cfloop from="1" to="#ArrayLen(rows)#" index="i">
<cfset pixels = ListToArray(rows[i], ",") />
<!--- Horizontal index (x scale) --->
<cfset horizIndex = 0 />
<cfloop from="1" to="#ArrayLen(pixels)#" index="j">
<cfif ListLen(pixels[j], "_") eq 2>
<!--- We have the color and the number of times it must be repeated --->
<cfset color = ListGetAt(pixels[j], 1, "_") />
<cfset repeat = ListGetAt(pixels[j], 2, "_") />
<cfelse>
<!--- Background color; how many pixels to skip --->
<cfset color = "" />
<cfset repeat = ListGetAt(pixels[j], 1, "_") />
</cfif>
<cfif Len(Trim(color))>
<!--- If the hexadecimal code is less than 6 characters, prefix with 0 to get a 6 char color --->
<cfif Len(Trim(color)) lt 6>
<cfset color = RepeatString(0, 6 - Len(Trim(color))) & color />
</cfif>
<!--- Draw a horizontal line for the number of pixels we must repeat --->
<cfset gr.setColor(gColor.decode("##" & color)) />
<cfset gr.drawLine(JavaCast("int", horizIndex), JavaCast("int", i - 1), JavaCast("int", horizIndex + repeat -1), JavaCast("int", i - 1)) />
</cfif>
<cfset horizIndex = horizIndex + repeat />
</cfloop>
</cfloop>
<!--- Get writer for Jpeg --->
<cfset writer = "" />
<cfset iter = CreateObject("java", "javax.imageio.ImageIO").getImageWritersByFormatName("jpg") />
<cfloop condition="iter.hasNext()">
<cfset writer = iter.next() />
</cfloop>
<!--- Set Jpeg quality to maximum --->
<cfset jpgParams = CreateObject("java", "javax.imageio.plugins.jpeg.JPEGImageWriteParam").init( CreateObject("java", "java.util.Locale").init("en") ) />
<cfset jpgParams.setCompressionMode( jpgParams.MODE_EXPLICIT ) />
<cfset jpgParams.setCompressionQuality( 1 ) />
<!--- Write image to a memory stream --->
<cfset imageOutput = CreateObject("java", "java.io.ByteArrayOutputStream").init() />
<cfset writer.setOutput( CreateObject("java", "javax.imageio.stream.MemoryCacheImageOutputStream").init( imageOutput ) ) />
<cfset writer.write(JavaCast("null", 0), CreateObject("java", "javax.imageio.IIOImage").init(chart, JavaCast("null", 0), JavaCast("null", 0)), jpgParams) />
<!--- Stream the image to the browser (hint browser to display the Save dialog) --->
<cfset filename="whatever.jpg" />
<cfheader name="Content-Disposition" value="attachment; filename=""#filename#""">
<cfcontent type="image/jpeg" variable="#imageOutput.toByteArray()#">
Checkout out the latest blog post Export Chart Images at Server Side where two options (wkhtmltoimage and PhantomJS. ) has been described with step-by-step instructions for both.
For ColdFusion, you can try the below code:
For example:
<cfexecute name="C:\Program Files\wkhtmltopdf\wkhtmltoimage.exe" arguments="--javascript-delay 10000 http://docs.fusioncharts.com/charts/Code/MyFirstChart/ms-weekly-sales-no-animation.html savedimage.png" />
While executing the above script, we provide the following arguments:
Call wkhtmltoimage
Pass the URL of your webpage to it
Pass the path and name of the image file (with extension) where the image will be saved
If required, any additional delay to ensure the chart is completely rendered.