I'm displaying a chart with one or more line series. The data comes from a query and works correctly if there is more than on series on the chart. However, if only one series is returned it is not displaying correctly.
Here's the code used:
<cfchart format="flash" tipstyle="mouseover" showlegend="yes" xaxistitle="Date" yaxistitle="Hits" chartwidth="1200" chartheight="300">
<cfoutput query="qryReport" group="APP_SYS_NR">
<cfchartseries serieslabel="#qryReport.APP_NA#" type="line">
<cfoutput>
<cfchartdata item="#DateFormat(qryReport.CDR_DT, "mm/dd/yyyy")#" value="#qryReport.TOT_HIT_CNT#">
</cfoutput>
</cfchartseries>
</cfoutput>
</cfchart>
The blacked out area at the top of this chart lists the keys for what the two lines represent:
In this chart (when there is only one APP_SYS_NR returned), instead of only having a single label, all the dates are turned into labels. Obviously not what I want:
Edit: I've traced this to the showlegend attribute of cfchart. According to Adobe, it's whether to display the legend if the chart contains more than one data series. I guess when it contains only one data series, it completely craps itself and does the data points in the legend. I tested on ColdFusion 9 and ColdFusion 10.
The solution here is to set showlegend to no when there is only a single series to display. Instead you should use a chart title in that instance. See the following modified code:
<cfset VARIABLES.blnShowLegend = "no">
<cfset VARIABLES.strChartTitle = "#qryReport.APP_NA#">
<cfif ListLen(URL.lstApps) GT 1>
<cfset VARIABLES.blnShowLegend = "yes">
<cfset VARIABLES.strChartTitle = "">
</cfif>
<cfchart format="flash" title="#VARIABLES.strChartTitle#" tipstyle="mouseover" style="appstats" showlegend="#VARIABLES.blnShowLegend#" xaxistitle="Date" yaxistitle="Hits" chartwidth="1200" chartheight="300">
<cfoutput query="qryReport" group="APP_SYS_NR">
<cfchartseries serieslabel="#qryReport.APP_NA#" type="line">
<cfoutput>
<cfchartdata item="#DateFormat(qryReport.CDR_DT, "mm/dd/yyyy")#" value="#qryReport.TOT_HIT_CNT#">
</cfoutput>
</cfchartseries>
</cfoutput>
</cfchart>
Related
How do I display a % with the value. labelForms="percent" doesn't seem to work, its clunky adding it to the item, am I missing a way to format it?:
<CFSET PercentLocked = 0>
<cfset PercentUnlocked = 0>
<cfset PercentOpenQueries = 0>
<cfset PercentOpenErrors = 29>
<cfset PercentClean = 71>
<cfchart
type="pie"
chartWidth="800"
show3d="true"
font="times"
style="blue"
labelformat="percent">
<cfchartseries >
<cfchartdata item="Locked Forms (#Percentlocked#%)" value="#PercentLocked#" >
<cfchartdata item="unLocked Forms (#PercentUnlocked#%)" value="#PercentUnlocked#">
<cfchartdata item="Forms w/Open Queries (#PercentOpenQueries#%) " value="#PercentOpenQueries#">
<cfchartdata item="forms w/Errors (#PercentOpenErrors#%) " value="#PercentOpenErrors#">
<cfchartdata item="Clean forms (#PercentClean#%)" value = "#PercentClean#">
</cfchartseries>
</cfchart>
Googling led to this ZingChart example involving the "plot" attribute. According to the ZingChart pie chart docs, several "tokens" are supported for use in customizing the text/values displayed
%npv - The percentage value of the pie slice (node) relative to the entire pie (sum of all nodes)
%t - The text of the current plot, pulled from the text attribute in the plot/series object
This example displays both the item text and value (as a percentage):
TryCF.com Example
<cfset plot = { "value-box":{
"visible":true,
"placement":"out",
"text":"%t (%npv%)"
}}>
<cfchart
type="pie"
chartWidth="800"
show3d="true"
font="times"
style="blue"
plot="#plot#">
<cfchartseries >
<cfchartdata item="Locked Forms" value="0" >
<cfchartdata item="UnLocked Forms" value="0">
<cfchartdata item="Forms w/Open Queries" value="0">
<cfchartdata item="forms w/Errors" value="29">
<cfchartdata item="Clean Forms" value = "71">
</cfchartseries>
</cfchart>
I am trying to use cfchart to display numbers of messages and all works well but when I have a small amount of numbers it breaks it into decimals. Is there a way we can make it always set to whole numbers?
Here is the code:
<cfchart format="#display#" type="bar" show3d="no" showlegend="false" chartHeight="300" chartWidth="220">
<cfchartseries colorlist="##E18014,green,red" type="bar">
<cfchartdata item="Calls Made" value="#voice_messages.TotalMessages#">
<cfchartdata item="Successful" value="#voice_messages.ReceiptsReceived#">
<cfif #voice_messages.DeliveryFailures# neq "0">
<cfchartdata item="Bus/No Ans" value="#voice_messages.DeliveryFailures#">
</cfif>
</cfchartseries>
</cfchart>
And here is a pic of the graph
I looked all over on Stack and the web but didn't find anything. Any help would be greatly appreciated.
Thanks!!
<cfchart> has an attribute called yAxisValues. It accepts an array of values. For this situation, once I had my data, I would do something to produce a suitable array to use for this attribute.
Verify whether the chartdata values voice_messages.TotalMessages, voice_messages.ReceiptsReceived and are infact integers. Use something like:
<cfset displayChart=false>
<cfif (isNumeric(voice_messages.TotalMessages) and voice_messages.TotalMessages gte 0)
and (isNumeric(voice_messages.ReceiptsReceived) and voice_messages.ReceiptsReceived gte 0)
and (isNumeric(voice_messages.DeliveryFailures) and voice_messages.DeliveryFailures gte 0)>
<cfset numberOfMessages=int(voice_messages.TotalMessages)>
<cfset numberOfReceipts=int(voice_messages.ReceiptsReceived)>
<cfset numberOfFailures=int(voice_messages.DeliveryFailures)>
<cfset displayChart=true>
</cfif>
<cfif displayChart>
<!--- You may have to increase the chartWidth to make room for all the labels--->
<cfchart format="png" type="bar" show3d="no" showlegend="false" chartHeight="300" chartWidth="300">
<cfchartseries colorlist="##E18014,green,red" type="bar">
<cfchartdata item="Calls Made" value="#numberOfMessages#">
<cfchartdata item="Successful" value="#numberOfReceipts#">
<cfif numberOfFailures neq 0>
<cfchartdata item="Bus/No Ans" value="#numberOfFailures#">
</cfif>
</cfchartseries>
</cfchart>
<cfelse>
Sorry, chart cannot be displayed because chartdata are not all integers.
</cfif>
In any case, you should realize that the labels in the display you have shown do not correspond to those in the code.
I shall now give you another answer. It is an answer of last resort, because it involves a changing ColdFusion server settings. Perhaps the reason you cannot easily find it on the web. Again, please be warned beforehand: it is a change of server setting. So back up your files!
ColdFusion 2018 (my version) uses the settings for ZingCharts to configure style in cfcharts. You will find the relevant files at C:\ColdFusion2018\cfusion\charting\styles. You want to edit the style file for bar charts.
Open in a text editor the file C:\ColdFusion2018\cfusion\charting\styles\bar. It has JSON format.
Locate the element "scale-y". It begins with:
"scale-y" : {
"format" : "%v",
"font-size" : 16,
... and so on.
Prepend to it the key-value pair "decimals" : 0. The result should be:
"scale-y" : {
"decimals" : 0,
"format" : "%v",
"font-size" : 16,
... and so on.
This will ensure that the y-axis will have 0 decimal places.
Save the file and restart ColdFusion for the changes to take effect.
You have now configured the y-axis in cfchart's bar charts to no longer have decimals.
You will have noticed that the element "scale-y" is a sub-element of "graphset". Should you be interested in knowing more about their settings, then go to https://www.zingchart.com/docs/api/json-configuration/graphset
I have a bar chart with four data points. I am trying to add a line to represent the average of the bars. When I add the line as a chartseries, it adds the line, but it also as the fifth bar.
How do I get a single red line to represent the average?
<cfchart format="png" scalefrom="0" scaleto="5000">
<!--- four blue bars --->
<cfchartseries
type="bar"
serieslabel="Website Traffic 2006"
seriescolor="blue">
<cfchartdata item="January" value="1000">
<cfchartdata item="February" value="2000">
<cfchartdata item="March" value="3000">
<cfchartdata item="April" value="4000">
</cfchartseries>
<!--- one red line --->
<cfchartseries
type="line"
seriesColor="red"
paintStyle="plain"
seriesLabel="Contract Salaries">
<cfchartdata item="average" value="2500">
</cfchartseries></cfchart>
Here is a solution that works. Basically, you have to REUSE the same item name in the line chart as you do in the bar chart to ensure that you do not introduce a new bar/x-axis point. You do not have to define all four matching points, but to me it seems like that would be good practice. The key to your problem though is to not introduce a new "item" name that results in a new bar. In my example, I just reused "January".
<cfchart format="png" scalefrom="0" scaleto="5000">
<!--- four blue bars --->
<cfchartseries
type="bar"
serieslabel="Website Traffic 2006"
seriescolor="blue">
<cfchartdata item="January" value="1000">
<cfchartdata item="February" value="2000">
<cfchartdata item="March" value="3000">
<cfchartdata item="April" value="4000">
</cfchartseries>
<!--- one red line --->
<cfchartseries
type="line"
seriesColor="red"
paintStyle="plain"
seriesLabel="Contract Salaries">
<cfchartdata item="January" value="2500">
</cfchartseries>
</cfchart>
I would like to limit the x-axis of my chart that is created by cfchart. I see the attribute scaleFrom and scaleTo that limit the y-axis, but I see nothing that limits the x-axis.
Also, I saw a similar question here:
ColdFusion Chart x-axis label limits
but neither of the answers were appropriate. ScaleMin and ScaleMax do not exists as far as I can tell and the other answer is more complicated than what I'd like to do.
The scaleMin and scaleMax attributes Saul mentioned are only available when using a custom style. Note, using type "scale" means your xAxis values must be numeric. If you want to use strings, you will probably need to use Ben's approach instead.
Here is a quick example that creates a chart with 24 points on the xAxis. Even though the query only contains the first six (6) points.
<!--- bare bones style --->
<cfsavecontent variable="style">
<?xml version="1.0" encoding="UTF-8"?>
<frameChart is3D="false" isInterpolated="true">
<frame xDepth="3" yDepth="1" />
<xAxis type="Scale" scaleMin="0" scaleMax="24" labelCount="25" isBucketed="false" />
</frameChart>
</cfsavecontent>
<!--- sample query --->
<cfset qry = queryNew("")>
<cfset queryAddColumn(qry, "xValue", listToArray("1,2,3,4,5,6"))>
<cfset queryAddColumn(qry, "yValue", listToArray("30,15,22,14,45,5"))>
<!--- chart code --->
<cfchart format="jpg" style="#style#" width="600">
<cfchartseries type="line"
markerstyle="circle"
query="qry"
itemColumn="xValue"
valueColumn="yValue" />
</cfchart>
I mean that MIN should be on top and MAX on X-axis.
This needed to make chart more intuitive to read and related to object ranking, when 1st place is "better" than 3rd. That's why it'd be better to look this way:
(source: xantea.net) =>
(source: xantea.net)
This can be done using custom XML. I ran the Chart Designer (cfinstall/charting/webcharts.bar (or .sh) and simply worked with the YAxis setting. There is an isReversed setting which does what you want. Consider this code:
<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>
<cfsavecontent variable="chartxml">
<?xml version="1.0" encoding="UTF-8"?>
<frameChart is3D="false">
<yAxis isReversed="true">
</yAxis>
</frameChart>
</cfsavecontent>
<cfchart chartWidth="400" chartHeight="400" title="Sales" font="arial" style="#chartxml#">
<cfchartseries type="line" query="q2" itemColumn="year" valueColumn="employees" seriesLabel="Employees" />
</cfchart>
The query on top was just used for testing. The XML came from the chart designer. I removed everything but the yAxis stuff that used isReverse. Lastly, note how I specify style in the chart tag.