Coolest CFCHART Trick Ever

This post is more than 2 years old.

Ok, maybe not ever, but interesting nonetheless. A few days ago a reader pinged me to ask about gauge charts. Those are charts that act like speedometers. I knew it wasn't supported by ColdFusion out of the box, but I recommended he take a look at the WebCharts design tool that ships with ColdFusion. When I did so - I saw right off the bat that it was supported, and there were quite a few of them.

I generated my style xml, passed it to the CFCHART, and promptly got an error about gauge charts not being supported. Darn. I was as frustrated as Britney Spears in a library.

Yesterday the topic of CFCHART came up again, this time on the CFAUSSIE mail list. When I made the same point there, a user named Simon Haddan shared an interesting fact. You can actually use Java to speak directly to the WebCharts engine embedded in ColdFusion. (Christopher Wigginton blogged on this as well back in 2005.)

Essentially, you can use the WebChart's designed to create a WCP file, which is just an XML file. You can then grab the relevant bits out and speak directly to WebCharts. And guess what?

No limits.

Not as far as I can tell. I made this lovely PNG gauge below. (And yes, SWF is supported too.)

The code is a bit complex, and involves some string manipulation, but could be made easier if someone felt like creating a nice CFC for it. Here is the code, and remember credit goes to Simon and Christopher:

<!--- Read the WCP file ---> <cfset sChartStyle = fileRead(expandPath("./raygauge.wcp"))>

<!--- Get the frameChart component ---> <cfset iStart = findNoCase("<gauge",sChartStyle)> <cfset iEnd = findNoCase("</gauge>",sChartStyle)> <cfsavecontent variable="chartStyle"> <cfoutput><?xml version="1.0" encoding="UTF-8"?> #mid(sChartStyle,iStart,iEnd-iStart+13)# </cfoutput> </cfsavecontent>

<cfsavecontent variable="chartModel"><?xml version="1.0" encoding="UTF-8"?> <XML type="default"> <COL>2000</COL> <ROW col0="88.0">Sample 0:</ROW> </XML></cfsavecontent>

<cfscript> oMyWebChart = createObject("Java","com.gp.api.jsp.MxServerComponent"); oMyApp = getPageContext().getServletContext(); oSvr = oMyWebChart.getDefaultInstance(oMyApp); oMyChart2 = oSvr.newImageSpec(); oMyChart2.width = 375; oMyChart2.height= 375; oMyChart2.type = "png"; oMyChart2.style = "#chartStyle#"; oMyChart2.model = "#chartModel#"; </cfscript> <!--- Create html tag set ---> <cfsavecontent variable="chartImgTag"> <cfoutput>#oSvr.getImageTag(oMyChart2,"http://192.168.1.108/CFIDE/GraphData.cfm?graphCache=wc50&graphID=")#</cfoutput> </cfsavecontent> <!--- Good old Webcharts loves to add an extra /Images/ to the URL ---> <cfset chartImgTag = replace(chartImgTag,"http://192.168.1.108/Images/","http://localhost/","All")>

<cfoutput> #htmlEditFormat(chartimgtag)# <p> #chartimgtag# </cfoutput>

The first part of the file grabs the style portion from the WCP file. I believe this is the same XML you would normally grab from the style tab. The chartModel section is the data. For a gauge it is rather simple - one value. I'm not sure where "Sample 0:" is even used, but the value, 88, is.

Next up we do the Java magic. Note the getImageTag portion expects a URL. This URL represents the same "magic" URL ColdFusion uses to display images/SWF stuff. You probably wouldn't want to hard code an IP like I did. WebCharts also wants to add /Images to this so it has to be stripped out.

The last thing I do is output the HTML in a form I can read, and as is, which works just fine.

Pretty cool, eh? In theory, one could build a custom tag that lets you paste in a MCP and it would run form that, but the data would be hard coded.

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by Joey Krabacher posted on 1/19/2008 at 3:25 AM

In this entry you speak of both a WCP file and a MCP file. Is this a typo or are these two different files?

Comment 2 by Raymond Camden posted on 1/19/2008 at 3:27 AM

I meant WCP. Edited - and thanks.

Comment 3 by Peter J. Farrell posted on 1/19/2008 at 3:44 AM

Yeah, Matt and I talked about this way back in ColdFusion Weekly Podcast version 1.2b in April of 2006.

We use custom CFC API (that we built) for charting on GreatBizTools.com to create all the charts that WebCharts3D supports. There are a bunch of helper java classes for data manipulation and style changes. However I won't get into that here as it's mess to work with directly.

An example chart which is similar to yours is here:
http://coldfusionweekly.com...

Comment 4 by SigEpJedi posted on 1/19/2008 at 3:48 AM

Ray waves hand:
These are not the Droids you are looking for....

Comment 5 by Peter J. Farrell posted on 1/19/2008 at 3:51 AM

BTW, the sample: 0 is the label for the row. Since the gauge chart isn't using the label -- it's not shown.

Comment 6 by Rick O posted on 1/19/2008 at 4:42 AM

You can also have CF talk to Batik (which comes installed with CF7+8). Batik renders SVG files, which are just XML, into PNG or JPEG. I did exactly that to generate speedometer-type graphs (among many other things) for nowrists.com.

Comment 7 by Alan McCollough posted on 1/19/2008 at 5:52 AM

Quite slick. I bet this is one of those tricks that doesn't work with CF7, though. I made a guage-style .wcp file, and set up the example here, and ran it. With CF7, I get "Invalid style type: gauge".

Got to get our copies of CF8 installed...

Comment 8 by Peter J. Farrell posted on 1/19/2008 at 7:13 AM

I've most definitely done the "gauge" style charts on CF7, however I never used the .wcp files instead using the java classes that represent data and charting styles.

Comment 9 by Justice posted on 1/21/2008 at 6:03 PM

Dont forget the designer that is included with CF7, so you have a GUI you can design your chart with, then save it off and use it. =)

http://www.cfcode.net/index...

Comment 10 by Raymond Camden posted on 1/21/2008 at 6:11 PM

@Justice: Errr - isn't that I mentioned in the article? ;) I said that I used that - but it still failed when I passed the XML to cfchart.

@Peter: Sorry I missed your earlier posts!

Comment 11 by Justice posted on 1/22/2008 at 12:02 AM

Ray

Sorry bud, thats what I get for reading too quick =)

Comment 12 by randy posted on 1/22/2008 at 9:04 PM

Anyone have this issue:
When we (three of us now) open webcharts.bat in CF8, all the text is binary zero characters. Totally unreadable.

Comment 13 by J. Lyle Martin posted on 7/9/2008 at 8:45 PM

Hello,

When I try to run this example, with my own (non modified) gauge .wcp file I get the following text and no graph. What am I doing wrong, or missing?

<!-- WebCharts3D v5.1(2077) --> <IMG SRC="http://192.168.1.108/CFIDE/GraphData.cfm?graphCache=wc50&graphID=Images/3607960040100155.png" id="Images_3607960040100155_png" name="Images_3607960040100155_png" usemap="#Images_3607960040100155_png_map" border="0"/> <table cellpadding='0' cellspacing='1' style='visibility: hidden;display: none; position:absolute;font-family: Arial;font-size: 13px; font-weight:700;background:#FFFF00;foreground:#0000FF;color:#0000FF;-moz-opacity:.50;-opacity:.50;filter:alpha(opacity=50);border:1px solid #0000FF;' name='GP1215621759443AAAB' id='GP1215621759443AAAB'><tr><td width='8'> </td></table> <MAP name='Images_3607960040100155_png_map'> <AREA shape='rect' coords='0,0,1,1'/> <AREA shape="poly" coords="293,133,191,194,183,180,289,126"/> </MAP> <script language="javascript" src="http://192.168.1.108/CFIDE/GraphData.cfm?graphCache=wc50&graphID=script.js"></script>
Thanks so much!
-Lyle

Comment 14 by Raymond Camden posted on 7/9/2008 at 9:41 PM

I spoke with J off line - the issue was forgetting to update the URL in the code.

Comment 15 by Larry posted on 7/18/2008 at 9:26 PM

To randy:
I had a similar (the same?) issue. Most of the text visible was showing a square instead of the character. Numbers showed up ok. Called up Gpoint and was told to reload the java virtual machine. This did not work. Found out by accident that if instead of running webcharts.bat you find and doubleclick C:\ColdFusion8\lib\wc50.jar all appears to work ok.

Comment 16 by adam posted on 7/26/2008 at 1:10 AM

Am I correct in assuming the 'Adobe ColdFusion 8 Developer Edition' water mark will show up regardless of your Coldfusion server license?

Thanks,
Adam

Comment 17 by J. Lyle Martin posted on 7/26/2008 at 1:18 AM

You can develop charts on the Developer Edition, you will see the watermark there. When you move the same code to a licensed version of CF you will no longer see the watermark.

Hope that helps.

-Lyle

Comment 18 by adam posted on 7/26/2008 at 1:24 AM

I understand that in general. I'm asking because I'm on a server that should be legitimately licensed, and doesn't show the watermark for normal graphs, but still shows it for any of the graphs that directly address webcharts3d classes.

But maybe there's something wrong in the server settings. I just thought since I haven't seen the behavior in any other charts it might be related to this specifically. So I was wondering if anyone knew for sure that the watermark shouldn't be there.

Thanks again,
Adam

Comment 19 by Raymond Camden posted on 7/29/2008 at 4:55 AM

I haven't tested this yet on production. It may be that it does indeed show the watermark. Has anyone else tried it?

Comment 20 by Rodell Basalo posted on 9/10/2008 at 10:16 AM

"You can develop charts on the Developer Edition, you will see the watermark there. When you move the same code to a licensed version of CF you will no longer see the watermark.

Hope that helps.

-Lyle
# Posted By J. Lyle Martin | 7/25/08 4:18 PM "

have you tried editing the watermark.png under \lib ?
i removed the text in the png and saved and overwrited the file without the Watermark text

Comment 21 by Reed Powell posted on 10/29/2008 at 10:38 PM

Be careful about doing this! I did it and it caused the Webcharts engine to put "Developer Edition" watermarks on all charts, including those that are created with <CFCHART> - waht a mess!

Comment 22 by Justin Cook posted on 6/16/2009 at 8:19 PM

Where does the GraphData.cfm come from in the reference? I don't believe we have that on our system.

Comment 23 by Raymond Camden posted on 6/16/2009 at 8:20 PM

It's a purely virtual file.

Comment 24 by Justin Cook posted on 6/16/2009 at 10:46 PM

Ray,

We have a Load Balancing situation though and if we create the chart, the page just shows an area that says that the chart expired. So typically, we have been writing charts to a file and then calling them back out immediately from a place where we wrote the chart to. Is it possible to write this chart to a file so that we can call it back out that way? Rather than serving it up live from the CF Server and the cache that it creates.

Comment 25 by Raymond Camden posted on 6/17/2009 at 3:44 PM

Not sure. You could maybe look at the Java API and see about setting it to a binary type, and see if the Java API lets you get the bits.

Comment 26 by Justin Cook posted on 6/17/2009 at 5:50 PM

My co-worker continued working on it and did save the file out as a binary to a local directory. Then we went back and recalled the saved SWF. We saved the SWF in a folder we named "charts". Here's the last half of the script:

<!--- initialize chart settings --->
<cfscript>
oMyWebChart = createObject("Java","com.gp.api.jsp.MxServerComponent"); oMyApp = getPageContext().getServletContext(); oSvr = oMyWebChart.getDefaultInstance(oMyApp); oMyChart2 = oSvr.newImageSpec();
oMyChart2.width = 400; oMyChart2.height= 300; oMyChart2.type = "swf"; oMyChart2.style = "#chartStyle#"; oMyChart2.model = "#chartModel#";
</cfscript><!--- Create html tag set --->
<cfsavecontent variable="chartImgTag">
<cfoutput>#oSvr.getImageTag(oMyChart2,"http://ourwebsite.com/CFIDE...")#</cfoutput>

</cfsavecontent><!--- Good old Webcharts loves to add an extra /Images/ to the URL --->

<cfset chartImgTag = replace(chartImgTag,"http://ourwebsite.com/Images/","http://ourwebsite.com/","All")>
<cfoutput>

<p>
#chartimgtag#
</cfoutput>
<cfset listpos=listcontains(chartImgTag, "graphID", "=")><cfset listpos=listpos+1>
<cfset chartID=listgetat(chartImgTag,listpos,"=")>
<cfset chartID=listgetat(chartID,2,"/")><cfset chartID=replace(chartID, '"', '')>
<br>
<cfhttp url="http://ourwebsite.com/CFIDE..." getasbinary="yes">

<cffile action="write" file="#local_path#charts\untitled11.swf" output="#cfhttp.filecontent#">

Comment 27 by Red posted on 1/27/2010 at 4:13 AM

Since the chart is created in the CF cache directory, is there a way to determine the image attributes after it has been drawn? I currently have the chart style set as flash but I have no objection to using PNG or JPG instead. What I’m doing is plotting 22 points on the chart, and then below the chart, I'm outputing the some additional details about the point displayed on the graph. I can hard code the width of the table columns to align directly underneath the respective point on the chart and it looks great, almost as if it is all one image. This is when my monitor resolution is at 1200×800. If I move the web page to my other monitor and view it at 1600x1200, the charts is small when compared to the available screen real estate. LIkewise, if the report is viewed with a resoltuion of 800x600, scrolling is required. I’m trying to take it a step further and make the chart width dynamic for larger/higher resolutons but still keep the tabular data inline with the points on the chart.
I hope this make sense and is clear…

Red

Comment 28 by Raymond Camden posted on 1/27/2010 at 4:19 AM

Look at the NAME attribute for CFCHART. It stores the result in binary. So if you use a PNG/JPG chart and NAME, you can then make an image object out of it. See:

http://www.coldfusionjedi.c...

for an example.

Comment 29 by Red posted on 1/27/2010 at 8:23 PM

@Ray

That'd be too easy. :) I'm not using the cfchart tag though. I'm using the java api to create the chart for me. My code is very similar to yours except for a guage graph, I'm using the line graph (actually, four lines graphs on chart).

The image you have for the guage is named, dial.png. I'm assuming for the purpose of the post, you hard coded the image name to be dial.png. But if you didnt' hard code that and left it with the temp name CF would have created. Is there a way to find out that name?

Comment 30 by Raymond Camden posted on 1/27/2010 at 8:38 PM

Actually, I think dial.png is just the _background_, not the final image. (Not 100% sure though.)

Comment 31 by Dean Dragstedt posted on 7/22/2011 at 5:31 PM

Hello,

I am having the same problem as J Lyle, so I'm wondering, as a relative novice to this, where should that URL be pointing? What do you mean by "magic" URL? Is this something that should stay the same, or should it point to my current webpage in development?

Thanks,
Dean

Comment 32 by Raymond Camden posted on 7/24/2011 at 4:27 AM

The URL is a servlet set up by CF to help render the images. It isnt a real file. It would not stay the same between different machines, but be unique to each install. Make sense?

Comment 33 by Dean Dragstedt posted on 7/28/2011 at 8:03 PM

It does make sense. So I assume I need to point to wherever the CFIDE folder is? As for that, I'm working off a development server that I don't actually administer; so I'll have to contact the person who administers the server. Am I correct in my assumption above?

Thanks,
Dean

Comment 34 by Raymond Camden posted on 7/28/2011 at 8:12 PM

Well it should be just be the same host as what you are on now. You can get that via a CGI variable.

Comment 35 by Mark Metcalf posted on 8/18/2011 at 2:41 AM

I'm creating a gauge in flash format using this example. Now when the code is on an secure server (HTTPS) in IE I get the not secure content warning. Due to the <OBJECT tag that gets auto created by the server, the CODEBASE url is HTTP only. Is there a way to change the CODEBASE url to HTTPS for the Flash <OBJECT tag? Or switch the format to PNG?

Comment 36 by Raymond Camden posted on 8/18/2011 at 3:01 AM

Maybe wrap the output in cfsavecontent and do a regex replace on it?

Comment 37 by Lina Haddad posted on 8/24/2011 at 7:20 PM

i need to change the title style in <cfchart > for example make the font bigger and bold but only for the title, but how can we do that through the xml in the style?

Comment 38 by Raymond Camden posted on 8/24/2011 at 7:25 PM

Did you try the chart editor? It's right there in the settings - Title. Click on it and you get a box of various options.

Comment 39 by Lina Haddad posted on 8/24/2011 at 7:29 PM

what is chart editor ?i only have .cfm file i opened it as text file ;-)

Comment 40 by Raymond Camden posted on 8/24/2011 at 7:31 PM

I talked about it in this blog post. It's a program you run (you will find it in the charting subdirectory of your cf install) that allows you to design a chart and spit out an xml file.

Comment 41 by Varun Reddy Teeleru posted on 9/26/2011 at 9:05 AM

@Ray, can I modify the dial chart range ie from 100-200. Default is 0-100. Please let me know.

Thanks in Advance.
Varun Reddy Teeleru.

Comment 42 by Raymond Camden posted on 9/26/2011 at 8:15 PM

So... did you try the Chart Editor? :) If you dig into the settings for the dial chart, you will find it under Axis Style: scaleMin and scaleMax.

Comment 43 by Sergio posted on 1/14/2013 at 6:53 PM

I would like to get the image file for further manipulations such as watermarking etc.
Is it possible to obtain the image file from the applet ?
I would retrieve the file from the cache and then use the file for my other purposes.
Thanks for any help.

Comment 44 by Raymond Camden posted on 1/14/2013 at 7:54 PM

cfchart supports a PNG format. You can use that and then use cfimage functions on it.

Comment 45 by Harold posted on 5/1/2013 at 6:13 PM

You may have heard about the CFIDE hack going around. Well, we had to lock down CFIDE since we are using MX7 and that shut down our cfchart function. I've tried workarounds but no luck. Upgrading Coldfusion is not economically possible so it is what it is.

I did find that the graphic for the chart is saved to cfusionmx7/charting/cache, but the graphic doesn't resolve on the chart page.

Any suggestions on how to use cfsavecontent to make it work while the main CFIDE files are locked down?

Comment 46 by Raymond Camden posted on 5/1/2013 at 6:16 PM

This may be a silly question, but why not try one of the _many_ JavaScript-based charting solutions out there? There are a heck of a lot of them - many free.

Comment 47 by Harold posted on 5/1/2013 at 6:20 PM

Raymond, thanks.

That was the next step. The charting queries an Access database so the search is on. Any suggestions?

Comment 48 by Raymond Camden posted on 5/1/2013 at 6:23 PM

I've played with a bunch, but none that strike me "THE BEST EVER." I'd recommend what I'd do - Google. :)

Comment 49 by Raymond Camden posted on 5/1/2013 at 6:23 PM

Err, I should clarify. Google actually has a charting solution too. ;) I'd _search_ Google. ;)

Comment 50 by delroekid posted on 5/2/2013 at 2:05 AM

problem with cfchart is that at any time, the cache will expire and the chart in your page will output an error. i have been playing with cfchart since 2011 but i would not recommend it very much. if you are looking for free charts, there's a lot of jquery chart implementations which uses javascript . try jflot.

Comment 51 by Myron posted on 10/2/2014 at 10:20 PM

I've just moved from CF8, where this trick worked like a charm, to CF11. I've verified that code will work up through CF10. In CF11, when I get to the line that creates the object, I'm getting an error:
Object Instantiation Exception. Class not found: com.gp.api.jsp.MxServerComponent
The error occurred on line 395.

I'm not heavily skilled with this type of sorcery and wondered if anyone else may have run across this error after upgrading, and what might be a solution I can apply.
Thanks,
Myron