Not having learned when enough is enough I've embarked on an adventure to try to get a composite UltraChart working.
So I have spent a good chunk of yesterday and today grinding through the documentation, the samples and the infragistics forums and stuff.
Step 1 was to simply replace an ordinary chart with a composite chart with just one layer. This, sort of, works.
However I wouldn't be posting if it worked perfectly And I'm posting here, rather than at infragistics because 1) I don't speak VB or C# particularly well and 2) I think my issues are largely a result of cognitive dissonance between my data oriented Progress 4GL mindset and the controls oriented VB/C# mindset.
I think that the core problem is that I don't grok the concept of a NumericSeries as it relates to a chart. I keep trying to think of it as a temp-table but that is clearly wrong. It doesn't really seem to be an array either. In particular it bothers me that:
series1:DataBind( dTable, dValue, dLabel ).
is supposed to mean something. "series1" is a NumericSeries. "dTable" is a "DataTable" which I have converted from a Progress temp-table (thanks to Haavard's help from the last go-roubnd with UltraCharts!). The DataTable at least makes sense to me. dTable has 20 rows and 2 columns, a label column and a data column. (The underlying temp-table has 4 colums -- 1 labels, 3 data.)
I can apparently add as many "series" to a chart as I'd like. But I do not really understand their function and how they are to be used and, from my perspective, the infragistics documentation seems very circular in terms of defining the term.
One theory that I've formed is that I need a data series for:
a) The x axis labels
b) The y values for anything that I want to chart
If that is correct then I would need to create a "series" for every column in the DataTable. And add each series to the UltraChart. Is that right? I don't think that it is quite right because it doesn't explain the 2 columns provided to Bind() nor does it work if I arbitrarily Add() additional series -- odd things happen then. So my conceptual model seems to be flawed.
This attached code, sort of works in a limited way. It displays a nice column chart.
But the idea is to have two layers and show two column charts super-imposed on one another. It seems to me that if I just uncomment the two lines down towards the bottom that that should happen. But instead the chart heads off into the twilight zone...
Ultimately I'm trying to get to a point where I can have one of the charts be a StackColumnChart and the other a LineChart. But neither of those chart types will work for me with my understanding of series right now.
Can anyone educate me?
[View:~/cfs-file.ashx/__key/communityserver-discussions-components-files/19/myCompositeChart.cls:550:0]
Well one problem turns out to be the the dolt who wrote the code above forgot to reopen the query between binding it to various sessions. Fixing that helps but it doesn't explain everything.
It's getting better but I still think I'm missing a clear understanding of what "series" are all about.
> Well one problem turns out to be the the dolt who wrote the code above forgot to reopen the query between binding it to various sessions. Fixing that helps but it doesn't explain everything.
Reposition-to-row(1) before the do while get-next seems to help also. Or change it to a do while with a get-first before and the get-next at bottom.
> It's getting better but I still think I'm missing a clear understanding of what "series" are all about.
The two following settings probably throws you off.
x2Axis:AxisNumber = AxisNumber:X2_Axis
y2Axis:AxisNumber = AxisNumber:Y2_Axis
This is moving the axis to the other (2) side and changes the position of the data area of the chart.
Try:
x2Axis:AxisNumber = AxisNumber:X_Axis
y2Axis:AxisNumber = AxisNumber:Y_Axis
Those were making the 2nd chart offset from the 1st but I had a couple of work-arounds for that.
Poking around last night on the IG boards I found an example that clarified a few minor points like that. One key thing is that I only need a single chartArea -- not two. So I cleaned that up which makes the code a bit smaller and easier to read.
I now have an example that reliably super-imposes one chart over the other (attached). But I still haven't figured out how to make the first chart a StackColumnChart and the second a LineChart. I'm clearly still missing something regarding the interactions between the chart and its data.
[View:~/cfs-file.ashx/__key/communityserver-discussions-components-files/19/7318.myCompositeChart.cls:550:0]
Oops -- slightly wrong version of code. To get the layered charts change the bit at the bottom to look like this:
One key thing is that I only need a single chartArea
-- not two. So I cleaned that up which makes the
code a bit smaller and easier to read.
I'm not sure about that.
In any case I'm attaching the example changed to super-impose a PieChart and ColumnChart on top of each other by ensuring that the Bounds of the ChartAreas are the same.
A LineChart is quite different according to Infragistics doc: Each row is drawn as a single line (or area) on the chart, with a number of points in the line equal to the count of numeric columns in the data set.
So you need at least two numeric columns for a line chart to show a line.
[View:~/cfs-file.ashx/__key/communityserver-discussions-components-files/19/5875.myCompositeChart.cls:550:0]
The single ChartArea approach does seem to work. It makes sense to me and simplified things quite nicely too. Plus it came from one of the IG guys who seems to know what he's talking about
Getting at least two numeric columns (series?) seems to be at the root of all of my current issues.
When I add 2 or more series to a chart they appear next to each other. (I can understand that that might sometimes be the desired behavior but, to me, it seems like it ought to be the exception rather than the rule.) This leads me to believe that adding additional "series" is not the right way to go. I suspect that I need a way to add more values to a series.
Specifically I think that my use of:
is the problem. I may be out in left field but I'm thinking that perhaps I need to make multiple passes through the DataTable? One to set it up like above and then another for each additional column of data? Maybe something like this:
Nope, that looks like a dead-end
For one things the 2nd form is subtly different -- the 1st parameter is a DataSet not a DataTable. The 2nd parameter is the index of the desired Table within the Set rather than the column.
But why have a method to bind a DataTable if it is only going to use a limited number of columns? That just doesn't seem sensible.
What is left of my brain is turning to mush and dribbling out my ears...
The single ChartArea approach does seem to work. It
makes sense to me and simplified things quite
nicely too. Plus it came from one of the IG guys who
seems to know what he's talking about
I certainly won't argue with that, but the WinChart/Composite/DataBind sample that we ship uses two ChartAreas and was transformed from an IG sample.
Getting at least two numeric columns (series?) seems to be at the root of all of my current issues.
You need to completely twist/invert the data to make them meaningful for the LineChart.
If you have two rows A and B with columns X, Y, Z a column chart shows it like this The graph height (y-axis) is set from the value of the column.
X | Y | Z | X | Y | Z |
Row A Row B
In a LineChart the same data is shown like this.
The y-axis position of the points is decided by the value of the columns
RowA XYZ
RowB XYZ
In your case you have many rows with one column (X)
|X| |X| |X| |X|
RowA RowB RowC RowD
If you want a LineChart to show the same data super imposed so that it matches the column chart, you need a column for each row, so to speak.
LineRow
- Column1 = RowA:X
- Column2 = RowB:X
- Column3 = RowC:X
- Column4 = RowD:X
I'm guessing that the same sort of "logic" applies to StackColumnChart.
That seems like what SwapRowsAndColumns does with a DataTable when you use a non-composite chart. But, so far as i can tell, there is nothing similar available when dealing with layers and series?
So the questions is... how do you make that happen? In good old 4GL code
It sort of sounds like I'm going to have to dynamically create a series that corresponds to every row in the data table? And an entry in the series for each column?
The mush is no longer dribbling -- it's gushing
The mush is no longer dribbling -- it's gushing
I guess that is what one has to expect when that which used to be ChUI is now GUI!
This little nugget from the IG docs looks promising:
I think that GetXYSeriesUnBound() is creating the sort of structure that I need... I'll have to fiddle with it later tonight.
Where is the Groan feedback button when I need it?
Probably hiding under some of that mush ...
The mush is no longer dribbling -- it's
gushing
I guess that is what one has to expect when that
which used to be ChUI is now GUI!
I guess the problem is amplified by the fact that you (and I) have to learn the components, but the core issue here is charting or reporting.
The reason why I tried to illustrate the 3 column sample case earlier was to illustrate why a column chart and line chart needs to be different.
In your case you have one column per row. This makes it possible to show the data as a line chart, but a line chart is really a single row of data.
Here's the important part; If you break your data down to satisfy the line chart then you can use the data to also feed a column chart in this case. You really do not need the column chart capability to show multiple rows when you have a single column in each row. You can show it as a single row and it should appear exactly as it currently does.
When this is said, I would look for options or settings for this particular one column per row situation. The SwapRowsAndColumns certainly sounds promising, or maybe a line chart can be shown as single column chart or something, or maybe there is a simpler type of column chart. Or it might be as simple as just feeding the data column by column to the chart while you traverse the rows. Tom's last posting might also be onto something .
Message was edited by:
Havard Danielsen
I guess the problem is amplified by the fact that you
(and I) have to learn the components, but the core
issue here is charting or reporting.
There is definitely an issue with vocabulary. I really don't think that I understand what they mean when they say "series". It almost seems like a one dimensional array or a column from a table but I don't think that either of those is really right because when I try to apply that idea I get burned. Repeatedly. (And how can it be either when the methods for building them take at least two and sometimes 3 data values?)
The reason why I tried to illustrate the 3 column
sample case earlier was to illustrate why a column
chart and line chart needs to be different.
Going back to that...
I'm not sure that I agree that they need to be different. They clearly are different but to my way of thinking the difference is entirely specious and quite antagonistic to mapping database tables (or temp tables) onto the chart.
In your case you have one column per row. This makes
it possible to show the data as a line chart, but a
line chart is really a single row of data.
In my mind a line chart and a column chart are (or should be) just two different ways of visualizing the same data. One draws columns from the X-Axis to the point, the other connects the points.
That is not, however, the way that IG controls seem to see the world. It may be that "reporting" people agree with IG. I wouldn't know. I do know that have had similar bouts of head banging and hair pulling with Excel charts so it probably isn't just IG that thinks in this messed up way.
Here's the important part; If you break your data down
to satisfy the line chart
I wish I could figure out how to do that...
... then you can use the data
to also feed a column chart in this case. You really
do not need the column chart capability to show
multiple rows when you have a single column in each
row. You can show it as a single row and it should
appear exactly as it currently does.
What? I completely lost you.
When this is said, I would look for options or
settings for this particular one column per row
situation. The SwapRowsAndColumns certainly sounds
promising,
It doesn't exist at this level. Or if it does exist it is very well hidden from me.
... or maybe a line chart can be shown as
single column chart or something, or maybe there is a
simpler type of column chart. Or it might be as
simple as just feeding the data column by column to
the chart while you traverse the rows. Tom's last
posting might also be onto something .
That seems to have turned out to be another rat-hole of circular logic and definitions
I am currently at a complete loss with no ideas for moving forward
I do not have the answer to how to make the line chart visible (yet), but it's not like we're not getting anywhere. We do have a layered chart working with different chart types.
> > I guess the problem is amplified by the fact that
you
(and I) have to learn the components, but the core
issue here is charting or reporting.
There is definitely an issue with vocabulary. I
really don't think that I understand what they mean
when they say "series". It almost seems like a one
dimensional array or a column from a table but I
don't think that either of those is really right
because when I try to apply that idea I get burned.
Repeatedly. (And how can it be either when the
methods for building them take at least two and
sometimes 3 data values?)
I see it as a a row with columns (different than an array as each column has a name)
The constructors provide a way to tell the chart which fields are the value field and the text field, basically making each row into a virtual name/value pair list. (3 parameters: table, valuefield, textfield)
You can also just describe only the value column. (2 parameters - no text field)
I think the confusion is that:
1. These constructors do not support more than one value column, while the chart is designed for and defaults to support multiple value columns.
Possible explanation:
- The default is to include all columns in the row in the chart.
- You use other methods like IncludeColumns to control which columns to chart
2. When there is obvious name/value pair support then one would expect it to work with a line chart. However, the line chart expects one row per line with a column for each value (like an array).
Possible explanation:
- The default makes sense if you want more than one line charted!
- I am 99% sure the SwapRowsAndColumns is for this case where you have a value in each row and only need a single line, but maybe it does not work with layers or series or something.
> Going back to that...
I'm not sure that I agree that they need to be
different. They clearly are different but to
my way of thinking the difference is entirely
specious and quite antagonistic to mapping database
tables (or temp tables) onto the chart.
They are kind of the same for all charts, but the Line chart is special since you need at least two column per line (row), since the line is drawn from one value to the other.
> > In your case you have one column per row. This
makes
it possible to show the data as a line chart, but
a
line chart is really a single row of data.
In my mind a line chart and a column chart are (or
should be) just two different ways of visualizing the
same data. One draws columns from the X-Axis to the
point, the other connects the points.
This is right, but the default is that each row is a chart item and with only one value there is nothing to draw. I'm sure it's there, just not visible...
> That is not, however, the way that IG controls seem
to see the world. It may be that "reporting" people
agree with IG. I wouldn't know. I do know that have
had similar bouts of head banging and hair pulling
with Excel charts so it probably isn't just IG
that thinks in this messed up way
The data requirements for 2D charting are based on laws of nature almost. Easy to use manually often, but tough to program generically.
Here's the important part; If you break your data
down
to satisfy the line chart
I wish I could figure out how to do that...
You can try to make a version of the DataTable method that adds the columns to a single row, but I still don't know how/if that would work with the current chart.
The SwapRowsAndColumns certainly sounds
promising,
It doesn't exist at this level. Or if it does exist
it is very well hidden from me.
Maybe not supported for layers or something?
> > ... or maybe a line chart can be shown as
single column chart or something, or maybe there is
a
simpler type of column chart. Or it might be as
simple as just feeding the data column by column
to
the chart while you traverse the rows. Tom's last
posting might also be onto something .
That seems to have turned out to be another rat-hole
of circular logic and definitions :(
> I am currently at a complete loss with no ideas for
moving forward :(
I would have tried to make a line chart work in a very simple case. (no layering or multiple areas.
Try the data you have and see if the SwapRowsAndColumns setting does some magic.
Try to create data in a single row instead and see if that works. (You can make a version of DataTable that does this, with some changes.
I haven't fiddled with this stuff at all, but just as an outsider observer, I wonder about:
They are kind of the same for all charts, but the Line chart is special since you need at least two column per line (row), since the line is drawn from one value to the other.
Seems to me that for any chart type which happens on an X-Y axis display, what one actually needs is N+1 sets of data for each indicator. For most chart types, one set provides the categories on the X axis (or vice versa if one flips the chart type) where each category occupies the same amount of space. For scatter plots this first set would be the distance along the X axis. The remaining sets represent values. In a non-stacked bar chart, each is a separate bar in the category. In a stacked bar chart each is drawn on top of the prior. In a line chart, the value designates a point above the X axis and a line is drawn from one to the next.
For all except the scatter plot, it is immaterial whether the values in the X-axis are uniformly distributed or not because they will be displayed uniformly regardless. They don't even have to be ordered or orderable. Only the scatter plot comes to mind where the X values have metric quality and where it might help to put them in in order if one wanted to connect them with lines.
Seems to me that for any chart type which happens on
an X-Y axis display, what one actually needs is N+1
sets of data for each indicator. For most chart
types, one set provides the categories on the X axis
(or vice versa if one flips the chart type) where
each category occupies the same amount of space. For
scatter plots this first set would be the distance
along the X axis.
The remaining sets represent
values. In a non-stacked bar chart, each is a
separate bar in the category. In a stacked bar chart
each is drawn on top of the prior. In a line chart,
the value designates a point above the X axis and a
line is drawn from one to the next.
For all except the scatter plot, it is immaterial
whether the values in the X-axis are uniformly
distributed or not because they will be displayed
uniformly regardless. They don't even have to be
ordered or orderable. Only the scatter plot comes to
mind where the X values have metric quality and where
it might help to put them in in order if one wanted
to connect them with lines.
I was pretty wrong about my assumption about a Line chart. It is actually not a point, but an area. So the x-axis distribution/ordering is thus very different from a column chart.
If one want to have a line chart or area chart in a composite chart then one need to set the x-axis to use continuousData, otherwise the chart wont render.
The only change needed to make the second chart show up in the previously attached sample (in addition to setting the ChartType to LineChart) is to:
x2Axis:SetLabelAxisType = SetLabelAxisType:ContinuousData
Tom's assumption about how this should work was thus quite right and the data can remain as is with one column per row and there is no need to use SwapRowsAndColumns, even if it actually is possible to set this on composite charts on the ChartLayoutAppearance. It does what it says, with quite different effect than I assumed.
Infragistics Online documentation Axis Requirements for Composite Charts has a table that outlines the requirements for each axis in a chart that is used as a layer of a Composite chart. It also says If any of the requirements are not met, the Composite chart will not render.
I still find the IG documentation to be fairly opaque I had found the table that you refer to but it really wasn't very helpful to me.
I heartily agree with Thomas regarding the nature of charts. This bizarre terminology seems, to me, to be a Windows thing. It sure isn't related to anything that was taught back in my school days. Other charting tools, like GnuPlot for example, use a much more straight-forward nomenclature that is a far better match for my vocabulary. Just guessing at the history but this feels like a group of people were building charting functionality in a spreadsheet program and adding features and making stuff up ad-hoc over a long period of time and without ever talking to each other nor ever stopping to refactor. And whatever they did was then copied by a couple of generations of similarly uncoordinated teams working on different projects and it has now become enshrined as "the windows way". Sort of reminds me of the UNIX vi editor.
On the bright side I posted a question on the IG forums yesterday seeking a simple example using a StackColumnChart and I have managed to translate the reply into working Progress code. I should have something ready to post here in a little bit.
I still find the IG documentation to be fairly opaque
I had found the table that you refer to but it
really wasn't very helpful to me.
Maybe it could have used better graphics and highlighted or underlined the "will not render", but it explains exactly why the line chart did not render.
I'm attaching the working version of this thread's chart.
[View:~/cfs-file.ashx/__key/communityserver-discussions-components-files/19/myCompositeChart2.cls:550:0]
The attached class works!
I think that we all sort of knew that the data needed to be "rotated" but getting there was difficult. The key was to abandon the DataTable, construct a NumericSeries for each row in the query and add each series to the ChartLayer.
So, as I said, the attached class does the job and displays what I had hoped for as a simple example.
For bonus points though I do have a few open items associated with this task:
1) I'd like to get the columns spaced out. In an non-composite chart "ultraChart1:ColumnChart:ColumnSpacing = 1." would do the trick. I'm not seeing how to translate that.
2) I'd like to get the 2nd layer's columns centered within the 1st layer's stacked columns. That might magically happen if the spacing above can get worked out but it might not. Any ideas on ways to accomplish that?
3) Making the 2nd layer's columns some other color.
[View:~/cfs-file.ashx/__key/communityserver-discussions-components-files/19/1200.myCompositeChart.cls:550:0]
Setting the color turns out to be easy. Just add a PaintElement to the series and set its color:
Setting the spacing still has me puzzled though.
I think that we all sort of knew that the data needed
to be "rotated" but getting there was difficult. The
key was to abandon the DataTable, construct a
NumericSeries for each row in the query and add each
series to the ChartLayer.
This is kind of the way I thought it needed to be, but it's actually not necessary to rotate the data.
The only problem with the original sample was that it did not render a LineChart. It seems you need to use continousData to make it work with a LineChart also with this approach.
Also note that with the extra rotated data you now actually need to use SwapRowsAndColumns on the ChartLayer to make the LineChart make sense.
1) I'd like to get the columns spaced out. In an
non-composite chart
"ultraChart1:ColumnChart:ColumnSpacing = 1." would do
the trick. I'm not seeing how to translate that.
The ColumnChartAppearance that controls this is accessible through the ChartTypeAppearance on the ChartLayer. You would need to cast it down to get the ColumnSpacing attribute.
Something like this should do the trick:
cast(ultraChart1:CompositeChart:ChartLayers:Item[0]:ChartTypeAppearance,ColumnChartAppearance):ColumnSpacing = 1.
On could possibly also new a ColumnChartAppearance with this and other settings and add it to the ChartLayer when you create it.
Ok, that works!
I'm starting to understand why it was so hard to find -- you have to know where to look first (You need to know what to cast it to.)
Would "other settings" also include things like the width of the column? How can I figure out what "other settings" are available?
I could never find a SwapRowsAndColumns at the ChartLayer level. This whole thing probably would have been solved 3 days ago if I had It would be nice to know, for reference, where that is if it exists.
Is that another one of those you've got to know what to cast() in order to know what to cast() circular documentation things?
In the end though I'm pretty happy with my addQuery2Layer() method. Eliminating that DataTable mapping is a big plus.
I could never find a SwapRowsAndColumns at the
ChartLayer level. This whole thing probably would
have been solved 3 days ago if I had It would be
nice to know, for reference, where that is if it
exists.
SwapRowsAndColumn would not have helped 3 days ago as the LineChart would have remained invisible.
The property is on the actual ChartLayerAppearance.
chartLayer2 = new ChartLayerAppearance().
...
chartLayer2:SwapRowsAndColumns = true.
You can also access the chart layer through the chart layer collection on the UltraChart as follows:
ultraChart1:CompositeChart:ChartLayers:Item[0]:SwapRowsAndColumns = true.
In the end though I'm pretty happy with my
addQuery2Layer() method. Eliminating that DataTable
mapping is a big plus.
I'm pretty sure it is a plus performance wise to eliminate the DataTable. But you might loose some advanced behavior by not using data binding. You probably do not need this in most of cases, but try the WinCharts/Composite/DataBind.cls example in our samples and edit something in the grid and the data in the chart will be refreshed. This happens automatically through data binding.
Ok, that works!
I'm starting to understand why it was so hard to find
-- you have to know where to look first (You need
to know what to cast it to.)
Yes, you need to know what to look for, but I had that information when you said that the non layered case used "ultraChart1:ColumnChart:ColumnSpacing = 1.
So I just needed to find the same type of appearance somewhere on the layer. (I also looked at the area, since I'm still a bit hazy on the chart concepts) Given that the layer is for all types, I did not expect an exact match to the ColumnChartAppearance, but looked at all appearances.
Would "other settings" also include things like the
width of the column? How can I figure out what
"other settings" are available?
I was mainly referring to the properties at the ColumnChartAppearance without really knowing what was there, but the use of appearance objects is very central in Infragistics and controls almost everything layout/appearance related.
Take a look at the ColumnChartAppearance in the documentation or object type browser.
I did. I somehow managed to miss ColumnSpacing. Or maybe I just couldn't get the cast() to work, I dunno, it's all becoming a haze... Even though there isn't actually much there. (I was really hoping for a ColumnWidth field somewhere -- but no luck :-(.) I looked in a million or so other places too. I get very lost searching for this stuff -- something leads to something else and before too long I've lost track of how I got to wherever I am... and the back button isn't very helpful.
In cases like this it would be really helpful if the class browser supported searching for properties and methods rather than just class names. (Or maybe it does and I'm just not aware of it?)
In cases like this it would be really helpful if the
class browser supported searching for properties and
methods rather than just class names. (Or maybe it
does and I'm just not aware of it?)
Unfortunately, it doesn't. I logged a bug for that : please feel free to have your name added to bug OE00175205
-- peter