I am attempting to create a stacked chart using the relatively new Microsoft Chart Controls. I am sure that I am missing something obvious but a bit of help will go a long way. The below code creates a chart with two columns. I'd like the columns to be stacked on top of each other. Further, I'd like the total of the two to be displayed on the chart. Any help would be much appreciated.
Series activeSeries = new Series("Active");
activeSeries.ChartType = SeriesChartType.StackedColumn;
activeSeries.BorderWidth = 3;
activeSeries.ShadowOffset = 2;
activeSeries.Points.AddY(3000);
LaptopChart.Series.Add(activeSeries);
Series inactiveSeries = new Series("Inactive");
inactiveSeries.ChartType = SeriesChartType.StackedColumn;
inactiveSeries.BorderWidth = 3;
inactiveSeries.ShadowOffset = 2;
activeSeries.Points.AddY(987);
LaptopChart.Series.Add(inactiveSeries);
Bone head move when creating the second series I added the inactive points to the active series. Sometimes no matter how often you walk through your own code it takes a second set of eyes to find things. Sorry for wasting anyone's time looking at this. The second reference to activeSeries.Points.AddY(987); should be inactiveSeries.Points.AddY(987);
Related
I'm trying to draw minor gridlines in the center between major gridlines.
chart1.ChartAreas[0].AxisX.MajorGrid.Interval = 4;
chart1.ChartAreas[0].AxisX.MinorGrid.Enabled = true;
chart1.ChartAreas[0].AxisX.MinorGrid.Interval = 3;
chart1.ChartAreas[0].AxisX.MinorGrid.LineColor = Color.Cornsilk;
chart1.ChartAreas[0].AxisX.MinorGrid.LineDashStyle= ChartDashStyle.Solid;
I tried to set different values of chart1.ChartAreas[0].AxisX.MinorGrid.Interval but didn't get expected result.Here what I got so far.
Arrow points to right located minor gridline
I tried to change chart1.ChartAreas[0].AxisX.MinorGrid.IntervalOffset property but it does not change anything. Has someone any suggestions? Thank you in advance.
EDIT
Based on TaW's answer tried to set intervals
chart1.ChartAreas[0].AxisX.MajorGrid.Interval = 4;
chart1.ChartAreas[0].AxisX.MinorGrid.Interval = 2;
got
EDIT 2
It was a good idea proposed by TaW, but since for me was not important LineDashStyle and custom labels are used, I decided to abandon minor lines and instead use major lines and custom labels, plotted for each second line.
Issue resolved
If you want the MinorGrid lines centered between the MajorGrid their Interval ought to be half their value:
Axix ax = chart1.ChartAreas[0].AxisX;
ax.MajorGrid.Interval = 4;
ax.MinorGrid.Interval = ax.MajorGrid.Interval / 2;
If you want more MinorGrid lines the MajorGrid.Interval still should be divisible by MinorGrid.Interval.
In case you really want to set an Offset, both should have the same !
Since your X-Values are DateTimes, you also will want to control the IntervalTypes:
ax.MajorGrid.IntervalType = DateTimeIntervalType.Days;
ax.MinorGrid.IntervalType = DateTimeIntervalType.Days;
Note that, as usual, every other major line overwrites a minor one. If this is a problem you can make the Intervals the same and offset one by half an Interval; but normally it will not matter.
I'm trying to find something like \vfill from Latex in iTextSharp (a way to insert spaces and place text at the bottom of the page). It's only for one page, not a footer.
I searched online and in the book iText in Action, but didn't find any answers.
OK, after a long time and trying many things, I have found a solution.
Some things I tried that "worked", but not good enough:
First I calculated the height of my paragraph (by writing it in a new table in a new document in the RAM), then I would add newlines until there was just enough room for my text. Result: NOT a good way, the text would by off by a few points (the y position in the document, because of the newlines).
Then I tried to do this with ColumnText: too many calculations (since my document is dynamic) and I didn't like positioning it absolute.
So my solution is to use a PdfPTable:
var t = new PdfPTable(1);
t.ExtendLastRow = true;
t.WidthPercentage = 100;
var c = new PdfPCell();
c.VerticalAlignment = Element.ALIGN_BOTTOM;
c.DisableBorderSide(Rectangle.BOX);
var p = new Paragraph("This is a test. This is a test. This is a test. This is a test. This is a test. This is a test. This is a test. This is a test. This is a test.");
p.Alignment = Element.ALIGN_JUSTIFIED;
c.AddElement(p);
t.AddCell(c);
doc.Add(t);
Pretty simple, but I lost a lot of time on this. I hope this helps others too.
I have been tasked to clean up a piece of code that handles the drawing of a chart, this chart will represent changes in voltage[kV] over a period of time. My problem is that as of now, it is working rather poorly, grinding to a halt after a few switches between lables.
You see, there is two radio buttons, they are used to switch the lables on the datapoints, as you go along and switch these back and forth, the application slows down until it stops completly.
I'm lost in the woods here since I'm a novice my self and was not involved with creating this function in the first place, these two factors adding up to a very confused intern.
I think the problem lies in the logic for switching between labels:
var newSerie = new Series();
var newSerie2 = new Series();
newSerie.ChartType = SeriesChartType.Line;
newSerie.ChartType = SeriesChartType.Line;
DataPoint dp = _dataPointList[i]; // FROM
DataPoint dp2 = _dataPointList2[i]; // TO
newSerie.Color = Color.Orange;
newSerie2.Color = Color.MidnightBlue;
string txt1 = _voltageList[i].Endvalue.ToString();
string txt2 = _voltageList[i].StartValue.ToString();
dp.Label = txt2;
dp2.Label = txt1;
newSerie.Points.Add(dp);
newSerie2.Points.Add(dp2);
newSerie.AxisLabel = _voltageList[i].MyStr;
newSerie2.AxisLabel = _voltageList[i].MyStr;
_localChart.Series.Add(newSerie);
_localChart.Series.Add(newSerie2);
_localChart.Update();
newSerie.Points.Remove(dp);
newSerie2.Points.Remove(dp2);
This is then looped through for each individual datapoint in a list.
Looking at your original post it's clear it needs refactoring. Whoever wrote it originally didn't like to call functions that's for sure!
Start by refactoring all the stuff that is nothing to do the
graphing, like calculating the number of seconds in a given month.
Refactor this stuff in to functions, or even helper classes.
Then refactor other small bits of functionality out and you will soon
start to boil this monster of a method down to something more
manageable and debugable.
My guess is that the toggle button adds 2 new series, but I can't see
old series getting removed.
I have a few question about charts in .NET in C#, I'm currently working on an app which will display data comming from serial port in real time.
I'm using a simple chart from .NET toolbox with spline series and there are two main feautures which I want to achieve.
The first one - I'd like the comming data points to be displayed on the right part of the chart and I'd like them to move to the left as the new data comes, I don't know how to describe it properly, I hope you can get the main idea since I can't post images yet.
I've achieved this kind of behaviour by reloading all the data points each time I refresh the chart, at first they are all empty and as the data comes I put the bigger and bigger queue of values in the end.
To clarify that the code may be like that:
chartAccelerationX.Series["XSeries"].Points.Clear();
dataPointTable = dataPointQueue.ToArray();
for (int i = 0; i < 1000; i++)
{
DataPoint dataPointX = new DataPoint();
if (1000 - dataPointTable.Length < i)
{
dataPointX.SetValueXY(i + 1, dataPointTable[i - 1000 + dataPointTable.Length].x);
}
else
{
dataPointX.IsEmpty = true;
}
chartAccelerationX.Series["XSeries"].Points.Add(dataPointX);
}
chartAccelerationX.Update();
It works pretty well, but as I said, I'm creating all the 1000 data points each time I update the chart (and I do it every 100ms) so it's probably disastrous in terms of performance (I'll need to have about 6-8 charts in total) and it's limited by the exact number od data points (1000 here).
Isn't there any easier way to achieve something like that with increasing amount of data points dynamically and with the second feature that I wanted to have - an auto matching scroll bar showing for example only 50 records at once?
I've been using a scrollbar as well, but it was just set to show 50 records out of 1000 and I could have scroll through all these empty data points right now.
I can probably make the scrollbar appear after an exact number of data points are on the chart and update it every time the data is added but maybe theres any easier way?
I hope you understood what I was trying to say, I'm still working on my English.
If you can use WPF, there is http://dynamicdatadisplay.codeplex.com/ and for the older WPF version http://dynamicdatadisplay.codeplex.com/wikipage?title=D3v1
which is pretty good, I've used it for some pretty high speed data sampling before
I've posted this question in the MS forums, but the only response (create a macro and extrapolate from the VBA code) didn't help. The only vague hint I got was to use TickLabelPosition -- which apparently is something only useful if you're using VB, and I'm using C#
What I'm trying to do SHOULD be the most simple and common thing in the world: I just want to move the X Axes label to the bottom of the chart. How hard could that be? Well, I'll admit I'm not overly experienced in either C# or the Excel interop, but currently it seems impossible.
I am writing a C# program (VS2010) to create Excel spreadsheets from imported data. I have no problem actually creating the spread sheet with all the correct data and ranges. What I CANNOT figure out is how to move the label for the X Axis. It's got to be something simple that I'm missing, but the thing always appears right at the zero line and since my values go negative, that means it's right in the middle of the chart. Now I can get the thing to where I want it to be if I use a template, but I don't want to do that.
Here is a code snippit:
const string topLeft = "A9";
const string bottomRight = "B18";
const string graphTitle = "Graph Title";
const string xAxis = "Time";
const string yAxis = "Value";
string chartTabName;
var range = workSheet.get_Range(topLeft, bottomRight);
// Add chart.
var charts = workSheet.ChartObjects() as
Microsoft.Office.Interop.Excel.ChartObjects;
var chartObject = charts.Add(20, 20, 750, 500) as
Microsoft.Office.Interop.Excel.ChartObject;
var chart = chartObject.Chart;
// Set chart range.
chart.SetSourceData(range);
chart.ChartType = Microsoft.Office.Interop.Excel.XlChartType.xlXYScatterSmooth;
// chart.ApplyChartTemplate(#"Chart1.crtx"); (<- template)
chart.ChartWizard(Source: range,
Title: graphTitle,
CategoryTitle: xAxis,
ValueTitle: yAxis);
Using this puts the Horizontal Value axis in the middle of the chart, since the x axis goes negative. Now I can move this MANUALLY, or by using a chart template (as I did), but that's not the best plan. The best plan would be to move it programmatically, but I can't find a way to do it. I can find a way to move the LEGEND (chart.Legend) but not the Value.
Thanks for any help.
ALthough it's completely undocumented, this command will work:
chart.Axes(2).CrossesAt = chart.Axes(2).MinimumScale;
If you want to move the X Axis labels to the "Low" position, here is the code in VBA which might help:
chart.Axes(xlCategory).TickLabelPosition = xlLow
And the constants are defined as:
Const xlCategory = 1
Const xlLow = -4134 (&HFFFFEFDA)
If you want to move the whole X Axis (labels and ticks), here the VBA code for that:
chart.Axes(xlValue).CrossesAt = -15
where -15 is the minimum number in the Y range. Notice the we're actually modifying the Y Axis here:
Const xlValue = 2
I realized you asked for C# code, but this should be easy to translate to C# (and I didn't have a Visual Studio project handy to test Excel Interop).