문제

단일 Excel 시리즈에 맞는 것보다 더 많은 포인트를 프로그래밍 할 수있는 도움이 필요합니다.

에 따르면 http://office.microsoft.com/en-us/excel/hp100738491033.aspx Excel 2007 차트에 표시 가능한 최대 포인트 수는 256000입니다. 각 시리즈는 32000 포인트로 캡을 닫으려면 8 시리즈가 전체 256000 포인트를 플로팅하려면 필요합니다. 내 고객은 우리가 작업하는 대규모 데이터 세트로 인해 차트 당 최대 점수를 플로팅해야합니다.

C#/Excel Interop에 대한 적당한 경험이 있으므로 워크 시트를 프로그래밍 적으로 만들고 각 32000 포인트 세트를 통해 루프를 쉽게 만들고 시리즈로 그래프에 추가하여 데이터가 완전히 플롯 될 때 중지되거나 8 시리즈를 중지 할 수 있다고 생각했습니다. 그려졌다. 올바르게 착색되면 8 시리즈는 단일 시리즈와 시각적으로 구별 할 수 없습니다.

불행히도 여기에 있습니다. 내가 직면 한 주요 문제는 다음과 같습니다.

(전체 크기) 2-D 차트의 데이터 시리즈에서 사용할 수있는 최대 데이터 포인트 수는 32,000입니다 ... http://img14.imageshack.us/img14/9630/errormessagen.png

이상하게 도이 팝업은 내가 라인을 실행할 때 나타납니다.

chart.ChartType = chartType (where chartType is xlXYScatterLines)

그리고 다음과 함께합니다.

hresult의 예외 : 0x800ac472 http://img21.imageshack.us/img21/5153/exceptionb.png

그래프를 작성할 데이터를 지정하기 전에 팝업/경고/예외를 어떻게 생성 할 수 있는지 이해하지 못합니다. Excel이 여기서 영리 해지려고 노력하고 있습니까?

임시 해결 방법으로 차트를 넣습니다. 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에서 데이터를 볼 수 있어야하는지 또는 출력 그래프를 다른 곳에서 사용해야하는지 여부에 따라 다릅니다.

그래프를 Excel 내에서 볼 필요가 없으면 데이터 포인트를 전달하고 그래프 응용 프로그램 또는 웹 브라우저에서 이미지를보십시오.

Excel로 그래프를보아야하는 경우 외부 그래프 응용 프로그램을 호출하여 데이터 포인트 모음을 전달할 수 있습니다. 반환하면 이미지가 VBA와 함께 Excel에 삽입하십시오.

필요한 경우 두 접근 방식에 대해 더 많은 정보를 줄 수 있습니다.

또한 다른 고려 사항에는 그래프에서 드릴 다운 기능이 필요한지 여부가 포함될 수 있습니다. 이 많은 데이터 포인트로, 나는 당신이 그렇게 할 것이라고 상상할 수 없습니다.


다음 질문에 답할 수 있다면 사람들이 더 나은 답변을 공식화하는 데 도움이 될 수 있습니다.

  1. 이러한 항목의 출력을 어떤 종류의 사용자 인터페이스에 제시 할 것인가? (예 : Excel, ASP.NET 웹 응용 프로그램, Windows Forms, WPF, Silverlight, 기타.)

  2. 이 그래프는 사용자의 요청에 따라 실시간으로 생성되어야합니까, 아니면 생성 및 저장됩니까? 주문형으로 생성되면 사용자가 대기 할 수있는 최대 시간은 얼마입니까?

  3. 실제로 Excel을 사용하는 것이 얼마나 중요합니까? 디스플레이의 요구 사항이기 때문에 사용하고 있습니까, 아니면 편리한 것입니까?

  4. 그래프 표시의 "와우 요인"이 얼마나 중요합니까? 단순히 그래프를 가지고 있습니까, 아니면 매우 아름답게되어야합니까?

  5. 사용자는 그래프에 드릴 다운 할 수있는 능력이 필요하거나 단순히 이미지를 충분히 볼 수 있습니까?

미래 에이 문제를 해결하는 사람을 돕기 위해 Jon 's Fix와의 완전한 기능은 다음과 같습니다.

    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 ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top