C#/ Excel中:使用周围最大尺寸系列在图表上(C#/Excel: Working Around

2019-07-18 00:51发布

我需要帮助编程绘图多个百分点,比可容纳在一个Excel系列。

根据http://office.microsoft.com/en-us/excel/HP100738491033.aspx 2007年Excel图表上显示的点的最大数量256000假定每个系列在32000点帽出,8系列都必须绘制完整的256000点。 我的客户要求每个图表位的最大数量的绘制,由于与我们合作的大型数据集。

我有一个C#适度经验/ Excel的互操作,所以我认为这将是很容易通过每个组的32000点编程方式创建一个工作表,然后循环,并将其添加到图作为一个系列,停止当数据被完全绘制或8系列绘制。 如果有色正常,8系列是从一个单一的一系列可视没有区别。

不幸的是我在这里。 我遇到的主要问题是:

(全尺寸) 可以在一个数据序列使用的2-d图表数据点的最大数量是32000 ... http://img14.imageshack.us/img14/9630/errormessagen.png

这弹出,奇怪的是,似乎当我执行这一行:

并伴随有:

从HRESULT异常:0x800AC472 http://img21.imageshack.us/img21/5153/exceptionb.png

我不明白我怎么之前我甚至指定要绘制的数据可以产生这样的弹出/警告/异常。 是Excel的巧言令色这里?

作为暂时的解决办法,我已经把chart.ChartType =图图表类型语句转换成一个try-catch块,所以我可以继续下去。

如下面所示,我的“分块”代码工作为目的,而是试图将数据添加到图表时,我仍然遇到了同样的问题。 Excel中说,我想,当清楚我不是为了绘制太多了点。

( 全尺寸图像 ) 与监视窗口代码块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");
    }

Answer 1:

如果活动单元格在一个数据块,Excel可能会以为你要绘制的范围。

选择一个空白细胞,其是不相邻的数据,然后插入图表。 这将是空白的,而不是预先填充。



Answer 2:

请问您的图表居然要在Excel中? 与许多数据点的表现将是可怕的。

一个建议可能是使用第三方组件生成的图表。 对于如何做到这一点的具体技术取决于你是否有能在Excel或是否在输出图形只需要提供其他地方查看数据。

如果图形并不需要是在Excel中可见,则只是通过数据点并查看图形应用程序或Web浏览器的图像。

如果您还需要查看使用Excel图表,你可以拨打电话到外部图形应用程序,并通过它的数据点的集合。 当它返回的图像只是VBA将其插入Excel中。

我可以给你更多的信息在这两种方法,如果你需要。

此外,其他因素可能包括是否需要具备向下钻取功能的图形。 有了这么多的数据点,我无法想象,你会的。


如果你能回答以下问题,它可能会帮助人们制定更好的答案。

  1. 什么样的用户界面会呈现这些项目的输出? (如:Excel,ASP.NET Web应用程序,Windows窗体,WPF,Silverlight的,其他的。)

  2. 应该这些图表实时在用户的请求而产生或者他们生成并存储? 如果它们是按需生成的,什么是你的用户会考虑接受等待的最长时间?

  3. 它有多重要,你实际上使用Excel? 您是否在使用它,因为它是用于显示的要求,或者是,究竟什么是方便?

  4. 如何重要的是“哇因素”为图形的显示? 简直是具有图形,还是他们必须非常漂亮?

  5. 做用户需要的任何向下钻取到的图形能力,或者仅仅是能够查看图像是否足够?



Answer 3:

为了帮助任何人谁在将来遇到此,这里是与Jon的修复程序的完整功能:

    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");

        dataSheet.get_Range("Z1", "Z2").Select();   //we need to select some empty space
                                                    //so Excel doesn't try to jam the 
                                                    //potentially large data set into the 
                                                    //chart automatically

        ChartObjects charts = (ChartObjects)dataSheet.ChartObjects(Type.Missing);
        ChartObject chartObj = charts.Add(100, 300, 500, 300);
        Chart chart = chartObj.Chart;
        chart.ChartType = chartType;
        SeriesCollection seriesCollection = (SeriesCollection)chart.SeriesCollection(Type.Missing);

        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);

            foreach (Series s in seriesCollection)
            {
                s.XValues = xValues;
            }
        }
        else // we need to split the data across multiple series 
        {
            int startRow = 2; 

            while (startRow < totalRows)
            {
                int stopRow = (startRow + SizeOfSeries)-1;  
                if (stopRow > totalRows) stopRow = totalRows;

                Series s = seriesCollection.NewSeries();
                s.Name = "ChunkStartingAt" + startRow.ToString();
                s.XValues = dataSheet.get_Range(xColumnLetter + startRow.ToString(), xColumnLetter + stopRow.ToString());
                s.Values = dataSheet.get_Range(yColumnLetterStart + startRow.ToString(), yColumnLetterStop + stopRow.ToString());

                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");
    }


文章来源: C#/Excel: Working Around Maximum Series Size On Chart