VBA: Creating charts dynamically, inconsistent output

时间:2017-06-19 14:04:10

标签: vba dynamic charts

I think the issue is that I am using series and not overwriting them, but I am uncertain how to write code that will not store/delete a series after a chart has been generated. Also, sometimes the charts generate as intended and other times they generate with both series and I can't discern a pattern in this behavior. Basically looking to create a chart that will only use the columns I am passing in on that particular iteration of the loop rather than storing previously generated series.

The loop I'm using for generation:

'Loop for charts
Dim vGen As Variant
Dim vCurrent As Variant
vGen = Array("NOx EFL", "NOx EFH", "NOx UAF", "NOx_EFA") ', "NOx DAF")
For Each vCurrent In vGen
    Set Search = Cells.Find(What:=vCurrent, _
        After:=Cells(1, 1), _
        LookIn:=xlValues, _
        LookAt:=xlPart, _
        SearchOrder:=xlByRows, _
        SearchDirection:=xlNext, _
        MatchCase:=False, _
        SearchFormat:=False)
    If Not Search Is Nothing Then
        Set Row_Start = Range(Search.Address).Offset(1, 0)
        Set Row_End = Range(Search.Address).Offset(row_count, 0)
        Set Data_Rng = Range(Row_Start, Row_End)
        Call make_chart(Fam_Rng, Data_Rng, Row_Start)
    End If
Next vCurrent

The chart creation function:

    Function make_chart(Fam, Data, Row_Start)
    Dim wbsheet As String
    sheetName = ActiveSheet.Name
    'Dim Char As Chart'
    Title_Str = Range("A2").Value & " " & Row_Start.Offset(-1, 0).Value

    Set Char = Charts.Add

    'With Worksheets("Charts").ChartObjects(Title_Str).Chart
    With Char
        .SeriesCollection(1).Values = Data
        .SeriesCollection(1).XValues = Fam
        '.ChartType = xlColumnClustered
        .HasTitle = True
        .ChartTitle.Text = Title_Str
        .HasLegend = False
        .Name = Title_Str
    End With

    Worksheets(sheetName).Activate
End Function

2 个答案:

答案 0 :(得分:0)

创建图表时选择的范围/数据会影响结果:我通常首先从我在代码中创建的任何图表中删除所有系列,然后添加我想要查看的特定数据。

未测试:

Sub make_chart(Fam, Data, Row_Start)
    Dim wbsheet As String
    sheetName = ActiveSheet.Name
    Dim Char As Chart
    Title_Str = Range("A2").Value & " " & Row_Start.Offset(-1, 0).Value

    Set Char = Charts.Add
    With Char
        For Each s In .SeriesCollection 
            s.Delete 
        Next s 

        With .SeriesCollection.NewSeries()
            .Values = Data
            .XValues = Fam
        End With

        '.ChartType = xlColumnClustered
        .HasTitle = True
        .ChartTitle.Text = Title_Str
        .HasLegend = False
        .Name = Title_Str
    End With

    Worksheets(sheetName).Activate
End Sub

答案 1 :(得分:0)

  

其他时候他们用两个系列生成,我无法辨别此行为中的模式

那么,它实际上取决于当前选择以及Excel如何通过查看当前活动工作表中的当前选择(及其邻域)来尝试评估哪些数据系列应该是图表的输入。

  • 如果当前选择是多个,则所选数据是输入数据。

  • 如果当前选择是单个单元格,则Excel对输入数据应该是什么有点“贪婪”。它试图在附近查找看起来像数据系列的所有内容。例如,如果您在填充列中并且两个相邻列都已填充,则将创建(至少)3个数据系列。我说至少是因为列表可以增长到任意数量的相邻列都填充了数据(region)。

  • 如果选择是单个,则在空白区域中,图表将创建为空。

我们如何从图表开始呢?有两种方法:

1-在创建图表后立即使用ChartArea.Clear清除图表区域(您也可以迭代系列集合并单独删除每个系列,但这很慢,我们会更好)

set cht = ThisWorkbooks.Charts.Add
cht.ChartArea.Clear

这个简单方法的唯一问题是,如果当前区域的数据列太多,可能会丢失很多CPU周期,因为会创建太多的系列以供不使用。

2-在创建图表之前,将选区设置为空区域中的单个单元格。一个明显的候选者是活动表的右下角单元格。请考虑使用以下自定义函数来创建空图表

Public Function createEmptyChart() As Excel.Chart
   Dim oldSelection As Range
   With ActiveSheet
     Set oldSelection = ActiveCell ' <--- ActiveCell not Selection, the latter might be a shape!
     .Cells(.Rows.count, .Columns.count).Select
     Set createEmptyChart = ThisWorkbook.Charts.Add
     Application.Goto oldSelection  <-- needed only if restoring the
     createEmptyChart.Activate      <-- old selection really matters
  End With
End Function

P.S。你注意到一些事情很棘手,因为你不能简单地依赖Selection对象,当前的选择可能是一个形状。此外,如果恢复旧选择并不重要,则可以简化该功能。

p.s.2 Pleaaase不要使用Char作为变量的名称:D