【问题标题】:Excel change chart formulaExcel更改图表公式
【发布时间】:2010-12-04 05:34:53
【问题描述】:

我目前正在使用 Office 对象模型生成 Excel 文档。我在编辑图表时遇到问题。 在模板文件中,我得到了一个使用以下来源的条形图:

    2008    2009    2010
A   10%     25%     15%
B   20%     25%     35%
C   30%     25%     45%
D   40%     25%     5%

图表有以下公式: =sheet2!$A$1:$D$5

例如,当“2009”列为空时,我不想在图表中显示条形。所以我想将公式更改为: =sheet2!A$1:D$5;sheet2!C$1:C$5

我知道有一个方法setSourceData,但我需要先获取当前的公式或范围。

我的问题是;我怎样才能得到图表公式?或者也许有另一种方法可以做我想做的事?

我还在 Excel 中尝试了一些动态范围,但这似乎只适用于从范围末尾添加或删除的列,而不是像列“2009”这样的中间列。

【问题讨论】:

    标签: c# excel office-automation


    【解决方案1】:

    我编写了以下代码来解决我的问题。它重建了所有现有的系列公式。这不适用于所有可能的图表,但它适用于我目前拥有的图表。将来我可能会再次查看它并尝试改进它。欢迎对以下代码提出建议。

    (抱歉缺少代码cmets)

            foreach (Excel.ChartObject chart in (Excel.ChartObjects)sheet.ChartObjects(Type.Missing))
            {
                IDictionary<int, Boolean> colHasValues = new Dictionary<int, Boolean>(); 
                ArrayList seriesFormulas = new ArrayList(); 
    
                foreach (Excel.Series series in (Excel.SeriesCollection)chart.Chart.SeriesCollection(Type.Missing))
                {
                    seriesFormulas.Add(series.Formula);
    
                    Array sValues = (Array)series.Values;
                    int i = 1;
                    foreach (Object o in sValues)
                    {
                        if(!colHasValues.Keys.Contains(i)) colHasValues.Add(i, false);                        
                        if (o != null)
                        {
                            colHasValues[i] = true;                             
                        }
                        i++;
                    }
                }
    
                if (!colHasValues.Values.Contains(true))
                {   
                    chart.Delete();
                }
                else if (colHasValues.Values.Contains(false) && seriesFormulas.Count > 1)
                {    
    
                    ArrayList newSeriesFormulas = new ArrayList(); 
    
                    foreach (String formula in seriesFormulas)
                    {
    
                        String[] formulaBits = formula.Split(";".ToCharArray());
                        if (formulaBits.Length == 4)
                        { 
    
                            for (int arrNr = 1; arrNr <= 2; arrNr++)
                            {   //1 = XValues, 2 = Values
                                int indexFirstChar = formulaBits[arrNr].IndexOf(':');
                                int indexLastChar = formulaBits[arrNr].LastIndexOf('$', indexFirstChar) + 1;
    
                                String firstRow = formulaBits[arrNr].Substring(indexLastChar, indexFirstChar - indexLastChar);
                                String firstColumn = formulaBits[arrNr].Substring(indexLastChar - 2, 1);
    
                                formulaBits[arrNr] = "";
    
                                foreach (KeyValuePair<int, Boolean> cat in colHasValues)
                                {
                                    if (cat.Value == true)
                                    {
                                        formulaBits[arrNr] += "overzichten!$" + getExcelColumnName((getExcelColumnNumber(firstColumn) + cat.Key - 1)) + "$" + firstRow + ":$" + getExcelColumnName((getExcelColumnNumber(firstColumn) + cat.Key - 1)) + "$" + firstRow + ";";
                                    }
                                }
                                formulaBits[arrNr] = formulaBits[arrNr].TrimEnd(";".ToCharArray());
                                if (formulaBits[arrNr].Contains(';')) 
                                {
                                    formulaBits[arrNr] = "(" + formulaBits[arrNr] + ")";
                                }
                            }
    
                            newSeriesFormulas.Add(String.Join(";", formulaBits));
    
                        }
    
                    }
    
                    int seriesid = 0;
                    foreach (Excel.Series series in (Excel.SeriesCollection)chart.Chart.SeriesCollection(Type.Missing))
                    {
                        series.Formula = newSeriesFormulas[seriesid].ToString();
                        seriesid++;
                    }
    
                }
    
            }
    

    【讨论】:

      【解决方案2】:

      没有一个属性可以保存图表的完整数据范围。但是,每个系列都包含有关其范围的信息。

      下面的代码将列出所有系列,然后删除第二个。

      Sub ChartRanges()
      
      Dim lngSeries As Long
      
          ActiveSheet.ChartObjects("Chart 1").Select
      
          For lngSeries = 1 To ActiveChart.SeriesCollection.Count
              Debug.Print ActiveChart.SeriesCollection(lngSeries).Formula
          Next lngSeries
      'List out series in chart
      
          ActiveChart.SeriesCollection(2).Delete
      'Delete a series from the chart
      
      End Sub
      

      根据您的示例数据,代码将输出 this

      =系列(Sheet1!$B$1,Sheet1!$A$2:$A$5,Sheet1!$B$2:$B$5,1) =系列(Sheet1!$C$1,Sheet1!$A$2:$A$5,Sheet1!$C$2:$C$5,2) =SERIES(Sheet1!$D$1,Sheet1!$A$2:$A$5,Sheet1!$D$2:$D$5,3)

      系列由四个参数组成:

      (系列名称、XValues、值、绘图顺序)

      【讨论】:

      • 谢谢,但在我的示例中,A、B、C 和 D 行是系列。如果没有数据,我想删除一个类别(2008,2009,2010)。
      猜你喜欢
      • 1970-01-01
      • 2013-06-10
      • 1970-01-01
      • 1970-01-01
      • 2011-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多