Posted in ColdFusion | Posted on 11-11-2008 | 5,865 views
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:
2<series index="0" shape="Line" isSecondAxis="true"/>
3</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:
2<!--- generate random sales data --->
3<cfloop index="y" from="1994" to="1998">
4 <cfscript>
5 queryAddRow(q);
6 querySetCell(q, "year", y);
7 querySetCell(q, "sales", randRange(80,220));
8 </cfscript>
9</cfloop>
10<cfset q2 = queryNew("year,employees","integer,integer")>
11<!--- generate random sales data --->
12<cfloop index="y" from="1994" to="1998">
13 <cfscript>
14 queryAddRow(q2);
15 querySetCell(q2, "year", y);
16 querySetCell(q2, "employees", randRange(2,8));
17 </cfscript>
18</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:
2<cfsavecontent variable="style">
3<?xml version="1.0" encoding="UTF-8"?>
4<frameChart is3d="false">
5<elements place="Default" shape="Line" drawShadow="true">
6<series index="0" shape="Line" isSecondAxis="true"/>
7</elements>
8</frameChart>
9</cfsavecontent>
Notice there my elements and series tags. Now lets render the charts:
2 <cfchartseries type="line" query="q" itemColumn="year" valueColumn="sales" serieslabel="Sales" />
3 <cfchartseries type="line" query="q2" itemColumn="year" valueColumn="employees" seriesLabel="Employees" />
4</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.
2<!--- generate random sales data --->
3<cfloop index="y" from="1994" to="1998">
4 <cfscript>
5 queryAddRow(q);
6 querySetCell(q, "year", y);
7 querySetCell(q, "sales", randRange(80,220));
8 </cfscript>
9</cfloop>
10<cfdump var="#q#">
11<cfset q2 = queryNew("year,employees","integer,integer")>
12<!--- generate random sales data --->
13<cfloop index="y" from="1994" to="1998">
14 <cfscript>
15 queryAddRow(q2);
16 querySetCell(q2, "year", y);
17 querySetCell(q2, "employees", randRange(2,8));
18 </cfscript>
19</cfloop>
20<cfdump var="#q2#">
21
22<!--- style from webcharts --->
23<cfsavecontent variable="style">
24<?xml version="1.0" encoding="UTF-8"?>
25<frameChart is3d="false">
26<elements place="Default" shape="Line" drawShadow="true">
27<series index="0" shape="Line" isSecondAxis="true"/>
28</elements>
29</frameChart>
30</cfsavecontent>
31
32<cfchart chartWidth="400" chartHeight="400" title="Sales" style="#style#">
33 <cfchartseries type="line" query="q" itemColumn="year" valueColumn="sales" serieslabel="Sales" />
34 <cfchartseries type="line" query="q2" itemColumn="year" valueColumn="employees" seriesLabel="Employees" />
35</cfchart>


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.
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.
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.
<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.)
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.
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?
<yAxis>
<titleStyle font="Arial Narrow-14">Monthly</titleStyle>
</yAxis>
<yAxis2>
<titleStyle font="Arial Narrow-11">Cumulative</titleStyle>
</yAxis2>
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
[Add Comment] [Subscribe to Comments]