Ask a Jedi: Two Y Axis for ColdFusion Charts

This post is more than 2 years old.

Danny asks:

I basically want to know if it's possible to have two different y-axis units/values and title? Let's say series #1 is random from 1-10 and then series #2 is random from 1000-10000. If you put those two series onto the same graph having only one y-axis, then the first series will not be readable. So, left y-axis would feature the first series and the right y-axis would feature the second series.

I have to admit - I wasn't sure what he meant at first. Then he provided a nice sample graph:

This made sense to me. Basically he has two sets of data with different ranges of Y values. Danny said he tried the chart editor, which as my readers know is the first place I always suggest folks to look. I tried as well and like Danny, I wasn't able to get it working. I did some quick Googling and came across this example. I played around with the source code, did some tests back in the chart editor, and finally figured it out.

In the style XML you can define a series as using a different y axis. For example:

<elements place="Default" shape="Line" drawShadow="true"> <series index="0" shape="Line" isSecondAxis="true"/> </elements>

This says that the first series (remember, it is 0 based, since lord forbid people start counting with 1 like sane folks) represents the second axis. The shape should match the type of graph you want of course. You can use index="1" to specify the second series as well.

Ok, so let's do a demo. First, I'll create two queries of data:

<cfset q = queryNew("year,sales","integer,integer")> <!--- generate random sales data ---> <cfloop index="y" from="1994" to="1998"> <cfscript> queryAddRow(q); querySetCell(q, "year", y); querySetCell(q, "sales", randRange(80,220)); </cfscript> </cfloop> <cfset q2 = queryNew("year,employees","integer,integer")> <!--- generate random sales data ---> <cfloop index="y" from="1994" to="1998"> <cfscript> queryAddRow(q2); querySetCell(q2, "year", y); querySetCell(q2, "employees", randRange(2,8)); </cfscript> </cfloop>

The first query represents sales figures over a 5 year period. The second query represents how many employees they had during those years.

Next up is the XML I'll use for the style:

<!--- style from webcharts ---> <cfsavecontent variable="style"> <?xml version="1.0" encoding="UTF-8"?> <frameChart is3d="false"> <elements place="Default" shape="Line" drawShadow="true"> <series index="0" shape="Line" isSecondAxis="true"/> </elements> </frameChart> </cfsavecontent>

Notice there my elements and series tags. Now lets render the charts:

<cfchart chartWidth="400" chartHeight="400" title="Sales" style="#style#"> <cfchartseries type="line" query="q" itemColumn="year" valueColumn="sales" serieslabel="Sales" /> <cfchartseries type="line" query="q2" itemColumn="year" valueColumn="employees" seriesLabel="Employees" /> </cfchart>

The important thing to note is that the first chart series, sales, is what will be on the right side of the chart. Here is the result:

There ya go. Hope this helps others, and here is the complete template if folks want to quickly test it.

<cfset q = queryNew("year,sales","integer,integer")> <!--- generate random sales data ---> <cfloop index="y" from="1994" to="1998"> <cfscript> queryAddRow(q); querySetCell(q, "year", y); querySetCell(q, "sales", randRange(80,220)); </cfscript> </cfloop> <cfdump var="#q#"> <cfset q2 = queryNew("year,employees","integer,integer")> <!--- generate random sales data ---> <cfloop index="y" from="1994" to="1998"> <cfscript> queryAddRow(q2); querySetCell(q2, "year", y); querySetCell(q2, "employees", randRange(2,8)); </cfscript> </cfloop> <cfdump var="#q2#">

<!--- style from webcharts ---> <cfsavecontent variable="style"> <?xml version="1.0" encoding="UTF-8"?> <frameChart is3d="false"> <elements place="Default" shape="Line" drawShadow="true"> <series index="0" shape="Line" isSecondAxis="true"/> </elements> </frameChart> </cfsavecontent>

<cfchart chartWidth="400" chartHeight="400" title="Sales" style="#style#"> <cfchartseries type="line" query="q" itemColumn="year" valueColumn="sales" serieslabel="Sales" /> <cfchartseries type="line" query="q2" itemColumn="year" valueColumn="employees" seriesLabel="Employees" /> </cfchart>

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 Brad Wood posted on 11/12/2008 at 11:05 AM

Well, whadduya know... I knew you could do this in Flex, but I never knew it was possible with CF charts.

Comment 2 by Jeremy Larter posted on 11/13/2008 at 11:11 AM

Nice example. I thought the random graph (now static) deserves some explanatory remarks:

Company X (withheld) started with 6 people in 1994 and had sales of $150k. There were a few bad eggs not carrying their weight that were summarily dismissed. As expected, profits rose to a record high of $200k in 1995 with only two remaining people. The bad eggs, after begging for their jobs back, were re-hired in 1996 (along with some clerical support). Company X's sales then plummeted as the bad eggs insulted customers. The clerical staff had to be let go in 1997 and then the rest of the bad eggs were fired by 1998. Sales started to increase with the two original people in Company X but it was not good enough. The company declared bankruptsy in 1998 after only having sales of just over $100k.

Comment 3 by Raymond Camden posted on 11/13/2008 at 8:06 PM

@Jeremy: Awesome. :)

Comment 4 by Asaf posted on 2/26/2009 at 2:49 AM

I'm wondering is there an XSD file for this style xml?

I'm trying to create a graph with two axises but it's more complicated than the examples above and having an XSD file that would show me what attributes and elements I can place in a "Style.XML" would be really helpful.

Comment 5 by Raymond Camden posted on 2/26/2009 at 3:01 AM

Why not use the chart editor?

Comment 6 by Asaf posted on 2/26/2009 at 4:11 AM

Wow, I just opened the chart editor for the first time...that's another world of its own. I'm now planning to invest some time reading the documentation on this stuff.

With that said I'm not going to ask "how do you do this?" without putting in the time myself to learn how to use the chart editor but I do want to share what I'm trying to do just to see if you think it is hypothetically possible (I believe it should be after checking out the chart editor).

I'm creating a CFChart with a variable number of series. Based on a users input I use a CFLoop/query that creates CFChartSeries on the fly. My chart also has line and bar graphs; I want the bar graphs to use the left axis and the line charts to use the right.

I realize that my style also has to be created on the fly to account for each additional series created in the chart but this led to strange behavior. The series using bar charts became stacked even when I specified that the CFChart placement parameter as "default" or "cluster".

Obviously, this is why I will have to play around with the chart editor. Like I said I'm not looking for a "how to guide" but rather I'd like to know for sanity/encouragement if it is possible to achieve my desired results.

Comment 7 by Raymond Camden posted on 2/27/2009 at 1:58 AM

One thing I have found is that - sometimes - there are some odd collisions between attributes sent via the tag and stuff sent in via XML. You may want to remove the stacked attribute and try to set it in XML instead.

Comment 8 by Ken posted on 4/13/2009 at 8:23 AM

This is exactly what I need. But instead of line, I want two bars side by side and a line for the second y axis. But the bars are stacked instead of next to each other. Is there a way in xml to get the bars side by side ?

Comment 9 by Raymond Camden posted on 4/13/2009 at 3:39 PM

Did you try the seriesPlacement argument?

Comment 10 by Will T posted on 4/23/2009 at 11:39 PM

This tip has been very useful to me, but I'm still having problems with the placement argument. My chart is similar to what Asaf was working on, it has two bar series using the left axis and two line series using the right. Got that to work, but unfortunately the bars are stacked instead of clustered. Tried doing the placement in the xml file as well as back in the cfchart definition, but can't get it to cooperate.

Comment 11 by Raymond Camden posted on 4/23/2009 at 11:42 PM

Will, I went into the chart editor, found a stacked chart, switched to clustered, and back and forth. This XML was used for stacked:

<elements place="Stacked" drawShadow="true">
<morph morph="Grow"/>
</elements>

This for clustered

<elements drawShadow="true">
<morph morph="Grow"/>
</elements>

Notice no place attribute. Try the XML above. (You should be able to leave off morph and dropShadow I think.)

Comment 12 by Will posted on 4/24/2009 at 8:06 PM

Thanks, that helped as well. If anyone else runs into this problem, note that in the XML attributes for place are a little different than cfchart seriesPlacement, (i.e. elements place="clustered" , as oppose to using the cfchart seriesPlacement="cluster").

Got one more issue to resolve and I think I'll be done messing with this chart for a while. Is there a way to get a "title" on the secondary (right) axis?

Sure wish I had access to that/any web chart editor.

Comment 13 by Raymond Camden posted on 4/24/2009 at 8:08 PM

You do have access. It comes with ColdFusion.

Comment 14 by Will T posted on 4/24/2009 at 8:15 PM

I'm using Eclipse to code, I've searched high and low and it can't be found on my pc. I think my organization has Coldfusion on a server, but I think it's locked down.

Comment 15 by Raymond Camden posted on 4/24/2009 at 8:24 PM

You do know you can run CF for free on your own machine, right? :)

Comment 16 by Will T posted on 5/26/2009 at 5:46 PM

I'm back. I did find where my company was hiding CF/webcharts3d editor, and it has helped some but it'seems a little buggy. I'm having 2 format/style issues.

1. The title labels for my 2 y-scales are appearing different even though I haven't specified any style for either of them (i.e. the left axis title appears to be in plain text, while the right axis tile is bold and possible a little bigger in size).

2. I haven't set any scale max or min values for either y-axis, so they should default to the max/min of chartdata values (respectively) with a default rounding depending on the data values. Unfortunately, when the data values pulled have min of 0, yaxis2 (right axis) is rounding down into negative values instead of min'ing out at 0.

Has anyone else encountered these issues?

Comment 17 by Will T posted on 5/26/2009 at 5:59 PM

Found a work around for my first issue. I set a style for both axis titles and had to code the size of yaxis2 smaller than yaxis so that they would appear the same in an IE browser.

<yAxis>
<titleStyle font="Arial Narrow-14">Monthly</titleStyle>
</yAxis>
<yAxis2>
<titleStyle font="Arial Narrow-11">Cumulative</titleStyle>
</yAxis2>

Comment 18 by Maramandan posted on 2/11/2010 at 11:55 AM

Hi Ray

I have a normal chart ( type="horizontalbar") Is there any way by which I could put the X axis on the top ? Sort of like primaryXAxisplacement = Top|Bottom. I didn't find this setting in CF 8 / WebCharts3D 5.1. Any Idea how this could be done? Please help me

Thanks in Advance

Comment 19 by Raymond Camden posted on 2/11/2010 at 9:07 PM

Like you, I checked the charts editor. From what I see, there is no way of doing this.

Comment 20 by Sateesh posted on 8/24/2011 at 9:03 AM

Please can you guide to generate dual axis cf graph with stacked type. I need the xml style code for that.

Comment 21 by Raymond Camden posted on 8/24/2011 at 5:12 PM

I don't think it makes sense for a stack type - does it? Since the values are the same index, hence the stack.

Comment 22 by Chris posted on 3/13/2012 at 4:58 PM

Good stuff here. My issue is that I want my money data stacked on the first axis (several series of these), and my people data clustered on the second axis (several series of these, also). Anyone else find a solution for this one?

Comment 23 by Tony posted on 6/28/2014 at 5:03 PM

Thanks for great example Raymond. I did notice that some folks were having issues with bars getting stacked. Could it be that the need to specify the second series for the line. I noticed that you did mention to use series=1 for the second line but the example did not have it in the code. I ran into similar problem and once I specified series=0 and series=1 it fixed the problem (the bars being stacked problem).

Comment 24 by Tony posted on 6/28/2014 at 5:07 PM

Correction on my previous post. Series index="0" and series index="1". I had left the word index out. Sorry

Comment 25 by Raymond Camden posted on 6/28/2014 at 8:55 PM

Thanks for sharing. Honestly I don't do anything anymore with these old charts. :)

Comment 26 by Richard Davies posted on 9/12/2014 at 7:53 PM

Ray, I can understand migrating to the newer SVG/Canvas charting libraries for general web usage, but do you have an alternative or other suggestions for creating charts inside PDFs generated with cfdocument?

Comment 27 by Raymond Camden posted on 9/12/2014 at 9:54 PM

@Richard: No idea really. I haven't looked at server-side charting engines in a while.

Comment 28 by Thomas Oecknick posted on 2/11/2015 at 5:28 PM

Hi Raymond,
did not work the second axis in Railo.
Can you help with that?

Comment 29 (In reply to #28) by Raymond Camden posted on 2/11/2015 at 5:42 PM

Sorry - I don't use Railo, can't really help. Also, I don't recommend using cfchart anymore.

Comment 30 (In reply to #29) by Thomas Oecknick posted on 2/11/2015 at 5:48 PM

argh... thanks anyway.

Comment 31 by Adam Cockman posted on 3/18/2016 at 9:07 AM

Hi Raymond, use your site quite a bit for tips hints and generally saving my job ;) I was wondering if you could help, how do I force the range of the second y-axis, I need to make it start at 0 (zero) but whatever I try it always starts at -10. This Minimum value in my data is 0. Thanks Ads

Comment 32 (In reply to #31) by Raymond Camden posted on 3/18/2016 at 1:20 PM

If you are using the old style charts, you would need to open up the editor and play around a bit. I honestly don't know. I strongly recommend you move away from cfchart though.