2009-10-06 159 views
1

我正在使用Office对象模型生成Excel文档。我在编辑图表时遇到问题。 在一个模板文件我有一个条形图,它使用以下源: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'中间那样。

回答

1

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

(抱歉缺少代码注释)

 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++; 
       } 

      } 

     } 
0

没有保存图表的完整数据范围的属性。然而,每个系列保存有关它的范围的信息。

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

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 

根据你的数据。例如,所述代码将输出此

= SERIES(Sheet 1中$ B $ 1,工作表Sheet $ A $ 2:!$ A $ 5中,工作表Sheet $ B $ 2:$ B $ 5,1) =系列(Sheet1!$ C $ 1,Sheet1!$ A $ 2:$ A $ 5,Sheet1!$ C $ 2:$ C $ 5,2) =系列(Sheet1!$ D $ 1,Sheet1!$ A $ 2:$ A $ 5 Sheet1中$ d $ 2:$ d $ 5,3)

系列由四个参数组成:

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

+0

谢谢,但在我的示例中的行A,B,C&d是各系列。如果没有数据,我想删除一个类别(2008,2009,2010)。 – user168998