簡體   English   中英

C#/ Excel:解決圖表上的最大序列大小

[英]C#/Excel: Working Around Maximum Series Size On Chart

我需要以編程方式繪制比單個Excel系列中更多的點的幫助。

根據http://office.microsoft.com/zh-cn/excel/HP100738491033.aspx,Excel 2007圖表上可顯示的最大點數為256000。鑒於每個系列的上限為32000點,因此需要8個系列繪制全部256000點。 由於我們要處理大量數據,因此我的客戶需要繪制每個圖表的最大點數。

我對C#/ Excel互操作有一定的經驗,因此我認為以編程方式創建工作表,然后遍歷每組32000點並將它們作為一個序列添加到圖形中會很容易,在完全繪制數據或8個序列時停止被繪制。 如果上色正確,則8系列與單個系列在視覺上無法區分。

不幸的是我在這里。 我遇到的主要問題是:

(完整大小) 您可以在一個數據系列中用於二維圖表的最大數據點數是32,000 ... http://img14.imageshack.us/img14/9630/errormessagen.png

奇怪的是,當我執行該行時會出現以下彈出窗口:

chart.ChartType = chartType(其中chartType為xlXYScatterLines)

並附有:

來自HRESULT的異常:0x800AC472 http://img21.imageshack.us/img21/5153/exceptionb.png

我什至在指定要繪制圖形的數據之前都不了解如何生成這樣的彈出窗口/警告/異常。 Excel試圖在這里變得聰明嗎?

作為臨時的解決方法,我將chart.ChartType = 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");
    }

您的圖形實際上必須在Excel中嗎? 擁有如此多的數據點,性能將非常糟糕。

一個建議可能是使用第三方組件來生成圖形。 如何完成此操作的具體技術取決於您是否必須能夠在excel中查看數據,或者輸出圖是否僅需要在其他地方使用。

如果在Excel中不需要顯示圖形,則只需傳遞數據點並在圖形應用程序或Web瀏覽器中查看圖像即可。

如果確實需要使用excel查看圖形,則可以調用外部圖形應用程序並將其傳遞給數據點的集合。 當它返回圖像時,只需使用vba將其插入excel。

如果需要,我可以為您提供有關這兩種方法的更多信息。

另外,其他注意事項可能包括是否需要在圖形上具有向下鑽取功能。 有了這么多數據點,我無法想象您會那樣。


如果您可以回答以下問題,則可能會幫助人們制定更好的答案。

  1. 什么樣的用戶界面將顯示這些項目的輸出? (例如,Excel,ASP.NET Web應用程序,Windows窗體,WPF,Silverlight等)。

  2. 這些圖是應該根據用戶的要求實時生成還是要生成和存儲? 如果它們是按需生成的,那么您的用戶認為可以等待的最長時間是多少?

  3. 實際使用Excel有多重要? 您使用它是因為它是顯示的必要條件,還是方便使用?

  4. “哇系數”對於圖形顯示有多重要? 只是擁有圖形,還是必須非常漂亮?

  5. 用戶是否需要任何能力來深入研究圖形,或者僅僅是能夠查看圖像就足夠了?

如果活動單元格在數據塊中,Excel可能會假定您要繪制范圍。

選擇一個不在數據旁邊的空白單元格,然后插入圖表。 它將為空白,而不是預先填充。

為了幫助將來遇到此問題的任何人,這是喬恩修復程序的完整功能:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM