Мне нужна помощь, которая может программно отображать больше точек, чем может поместиться в одну серию Excel.C#/Excel: рабочий максимум Максимальный размер серии на диаграмме
В соответствии с http://office.microsoft.com/en-us/excel/HP100738491033.aspx максимальное количество точек, отображаемых на диаграмме Excel 2007, составляет 256000. Учитывая, что каждая серия закрывается на 32000 точек, для построения целых 256000 точек требуется 8 рядов. Мой клиент требует построения максимального количества точек на диаграмму из-за больших наборов данных, с которыми мы работаем.
У меня умеренный опыт взаимодействия с C#/Excel, поэтому я подумал, что было бы легко запрограммировать рабочий лист, а затем прокручивать каждый набор из 32000 точек и добавлять их к графику в виде серии, останавливаясь, когда данные будут полностью или 8-й серии. Если цвет правильно окрашен, серия 8 будет визуально неотличима от одной серии.
К сожалению, я здесь. Основной проблемой я сталкиваюсь является:
(full size) The maximum number of datapoints you can use in a data series for a 2-D chart is 32,000... http://img14.imageshack.us/img14/9630/errormessagen.png
Всплывающее, как ни странно, появляется, когда я исполняю строку:
и сопровождается:
Exception from HRESULT: 0x800AC472 http://img21.imageshack.us/img21/5153/exceptionb.png
Я не понимаю, как я мог бы генерировать такое всплывающее окно/предупреждение/исключение, прежде чем я даже укажу данные, которые нужно графипировать. Здесь Excel пытается быть умным?
Как временное обходное решение, я поместил инструкцию chart.ChartType = chartType в блок try-catch, чтобы я мог продолжать работу.
Как показано ниже, мой код «chunking» работает по назначению, но я все еще сталкиваюсь с той же проблемой при попытке добавить данные на график. Excel говорит, что я пытаюсь нарисовать слишком много баллов, когда я не уверен.
(full size image) code block with watch window http://img12.imageshack.us/img12/5360/snippet.png
Я понимаю, что не может иметь значения X правильно, связанные с каждой серией, но я пытаюсь получить эту работу, прежде чем пойти дальше.
Любая помощь была бы принята с благодарностью.
Вот полный код:
public void DrawScatterGraph(string xColumnLetter, string yColumnLetterStart, string yColumnLetterStop, string xAxisLabel, string yAxisLabel, string chartTitle, Microsoft.Office.Interop.Excel.XlChartType chartType, bool includeTrendline, bool includeLegend)
{
int totalRows = dataSheet.UsedRange.Rows.Count; //dataSheet is a private class variable that
//is already properly set to the worksheet
//we want to graph from
if (totalRows < 2) throw new Exception("Not generating graph for " + chartTitle.Replace('\n', ' ')
+ " because not enough data was present");
ChartObjects charts = (ChartObjects)dataSheet.ChartObjects(Type.Missing);
ChartObject chartObj = charts.Add(100, 300, 500, 300);
Chart chart = chartObj.Chart;
try { chart.ChartType = chartType; }
catch { } //i don't know why this is throwing an exception, but i'm
//going to bulldoze through this problem temporarily
if (totalRows < SizeOfSeries) //we can graph the data in a single series - yay!
{
Range xValues = dataSheet.get_Range(xColumnLetter + "2", xColumnLetter + totalRows.ToString());
Range yValues = dataSheet.get_Range(yColumnLetterStart + "1", yColumnLetterStop + totalRows.ToString());
chart.SetSourceData(yValues, XlRowCol.xlColumns);
SeriesCollection seriesCollection = (SeriesCollection)chart.SeriesCollection(Type.Missing);
foreach (Series s in seriesCollection)
{
s.XValues = xValues;
}
}
else // we need to split the data across multiple series -- this doesn't work yet
{
int startRow = 1;
while (startRow < totalRows)
{
int stopRow = (startRow + SizeOfSeries)-1;
if (stopRow > totalRows) stopRow = totalRows;
Range curRange = dataSheet.get_Range(yColumnLetterStart + startRow.ToString(), yColumnLetterStop + stopRow.ToString());
try
{
((SeriesCollection)chart.SeriesCollection(Type.Missing)).Add(curRange, XlRowCol.xlColumns,
Type.Missing, Type.Missing, Type.Missing);
}
catch (Exception exc)
{
throw new Exception(yColumnLetterStart + startRow.ToString() + "!" + yColumnLetterStop + stopRow.ToString() + "!" + exc.Message);
}
startRow = stopRow+1;
}
}
chart.HasLegend = includeLegend;
chart.HasTitle = true;
chart.ChartTitle.Text = chartTitle;
Axis axis;
axis = (Axis)chart.Axes(XlAxisType.xlCategory, XlAxisGroup.xlPrimary);
axis.HasTitle = true;
axis.AxisTitle.Text = xAxisLabel;
axis.HasMajorGridlines = false;
axis.HasMinorGridlines = false;
axis = (Axis)chart.Axes(XlAxisType.xlValue, XlAxisGroup.xlPrimary);
axis.HasTitle = true;
axis.AxisTitle.Text = yAxisLabel;
axis.HasMajorGridlines = true;
axis.HasMinorGridlines = false;
if (includeTrendline)
{
Trendlines t = (Trendlines)((Series)chart.SeriesCollection(1)).Trendlines(Type.Missing);
t.Add(XlTrendlineType.xlLinear, Type.Missing, Type.Missing, 0, 0, Type.Missing, false, false, "AutoTrendlineByChameleon");
}
chart.Location(XlChartLocation.xlLocationAsNewSheet, "Graph");
}
Спасибо, Джон! Я добавил следующее в верхней части моей функции: Диапазон tempRange = dataSheet.get_Range ("E1", "E2"); tempRange.Select(); Если столбец E пуст (мои данные указаны только в столбцах A - C). С этим изменением на месте все работало правильно. Еще раз спасибо! – Vincent