ج#/اكسل:العمل حول الحد الأقصى لحجم السلسلة على الرسم البياني

StackOverflow https://stackoverflow.com/questions/1422779

  •  07-07-2019
  •  | 
  •  

سؤال

أحتاج إلى مساعدة في رسم بياني برمجي لنقاط أكثر مما يمكن احتواؤه في سلسلة Excel واحدة.

وفق http://office.microsoft.com/en-us/excel/HP100738491033.aspx الحد الأقصى لعدد النقاط التي يمكن عرضها على مخطط Excel 2007 هو 256000.نظرًا لأن كل سلسلة تصل إلى 32000 نقطة، يلزم وجود 8 سلاسل لرسم 256000 نقطة كاملة.يتطلب عميلي رسم الحد الأقصى من النقاط لكل مخطط نظرًا لمجموعات البيانات الكبيرة التي نعمل معها.

لدي خبرة متوسطة في التشغيل المتداخل لـ C#/Excel لذا اعتقدت أنه سيكون من السهل إنشاء ورقة عمل برمجيًا ثم تكرار كل مجموعة مكونة من 32000 نقطة وإضافتها إلى الرسم البياني كسلسلة، والتوقف عندما يتم رسم البيانات بالكامل أو 8 سلاسل تم التخطيط لها.إذا تم تلوينها بشكل صحيح، فلن يكون من الممكن تمييز السلسلة 8 بصريًا عن سلسلة واحدة.

لسوء الحظ أنا هنا.المشكلة الرئيسية التي أواجهها هي:

(الحجم الكامل) الحد الأقصى لعدد نقاط البيانات التي يمكنك استخدامها في سلسلة بيانات لمخطط ثنائي الأبعاد هو 32000...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 أن يكون ذكيًا هنا؟

كحل مؤقت، قمت بوضع عبارة Chart.ChartType = ChartType في كتلة محاولة الالتقاط حتى أتمكن من الاستمرار.

كما يظهر في ما يلي، فإن كود "التقطيع" الخاص بي يعمل على النحو المنشود، ولكنني ما زلت أواجه نفس المشكلة عند محاولة إضافة البيانات إلى الرسم البياني.يقول 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 قد افترض أنك تريد رسمها النطاق.

وحدد خلية فارغة وهي ليست بجانب البيانات، ثم إدراج الرسم البياني. وسوف يكون فارغا، بدلا من prepopulated.

نصائح أخرى

هل يجب أن يكون الرسم البياني الخاص بك بالفعل في Excel؟مع هذا العدد الكبير من نقاط البيانات، سيكون الأداء فظيعًا.

قد يكون أحد الاقتراحات هو استخدام مكون طرف ثالث لإنشاء الرسم البياني.تعتمد التقنية المحددة لكيفية تحقيق ذلك على ما إذا كان يجب أن تكون قادرًا على عرض البيانات في برنامج Excel أو ما إذا كان الرسم البياني الناتج يحتاج ببساطة إلى أن يكون متاحًا في مكان آخر.

إذا لم يكن من الضروري أن يكون الرسم البياني مرئيًا في برنامج Excel، فما عليك سوى تمرير نقاط البيانات وعرض الصورة في تطبيق الرسوم البيانية أو متصفح الويب.

إذا كنت بحاجة إلى عرض الرسم البياني باستخدام برنامج Excel، فيمكنك إجراء اتصال بتطبيق الرسوم البيانية الخارجي وتمرير مجموعة من نقاط البيانات إليه.عندما تقوم بإرجاع الصورة فقط قم بإدراجها في برنامج Excel باستخدام vba.

يمكنني أن أقدم لك المزيد من المعلومات حول كلا النهجين إذا كنت بحاجة.

بالإضافة إلى ذلك، قد تتضمن الاعتبارات الأخرى ما إذا كنت بحاجة إلى إمكانية التنقل لأسفل في الرسم البياني.مع نقاط البيانات العديدة هذه، لا أستطيع أن أتخيل أنك ستفعل ذلك.


إذا كان بإمكانك الإجابة على الأسئلة التالية، فقد يساعد الأشخاص في صياغة إجابات أفضل.

  1. ما نوع واجهة المستخدم التي ستقدم مخرجات هذه العناصر؟(على سبيل المثالExcel، وتطبيق ويب ASP.NET، وWindows Forms، وWPF، وSilverlight، وغيرها.)

  2. هل من المفترض أن يتم إنشاء هذه الرسوم البيانية في الوقت الفعلي بناءً على طلب المستخدم أم أنها يتم إنشاؤها وتخزينها؟إذا تم إنشاؤها عند الطلب، ما هو الحد الأقصى للوقت الذي يعتبره المستخدمون مقبولاً للانتظار؟

  3. ما مدى أهمية استخدام برنامج Excel بالفعل؟هل تستخدمه لأنه من متطلبات العرض، أم أن هذا هو ما هو مفيد فقط؟

  4. ما مدى أهمية "عامل الإبهار" لعرض الرسوم البيانية؟هل مجرد الحصول على الرسوم البيانية أم أنها يجب أن تكون جميلة للغاية؟

  5. هل يحتاج المستخدمون إلى أي قدرة على التعمق في الرسم البياني، أم أن مجرد القدرة على عرض الصورة كافية؟

لمساعدة أي شخص يأتي عبر هذا في المستقبل، وهنا وظيفة كاملة مع الإصلاح جون ل:

    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