【问题标题】:For Loop to build chartsFor Loop 构建图表
【发布时间】:2020-10-08 16:45:28
【问题描述】:

我有以下数据集:

我正在尝试编写一个为每个位置构建图表的宏。我已经创建了创建新工作簿、命名工作表的代码,可以为位置 1 创建第一个图表,但我需要代码然后循环返回并对位置 2、位置 3 等执行相同操作。这是一个示例下图:

困难的部分 - 网站(A 列)将发生变化。有几个月我可能有多达 10 个位置。我需要代码足够动态,以便为每个唯一站点创建图表。正如您将在代码中看到的那样,我正在创建一个新工作簿,在旧文件中创建图表,然后剪切/粘贴到新工作簿中的选项卡中。然后我根据图表标题重命名工作表。然后我需要代码循环回到开头,并为 A 列中的每个唯一位置重复该过程。

代码如下:

    Sub ChartBuilder()
    
    Dim Wb As Workbook
        
    Set Wb = ActiveWorkbook
    Workbooks.Add
    ActiveWorkbook.SaveAs Filename:=Wb.Path & "\Outputs.xlsx"
    ActiveSheet.Name = "Results"
    
    Wb.Activate
    Sheets("Sheet1").Select
      
    '88888 Loop ends below and Loop should come back here
      
    ActiveSheet.Shapes.AddChart2(227, xlLine).Select
    With ActiveChart
    
    'Needs to be dynamic in both Chart Title Name and Data Range
    'Column A is the Location Name - will have duplicates
    'Column C has the weeks.  Weeks are limited to Week 1, Week 2, Week 3, Week 4
    'Column E thru I are the data columns that need to be displayed.
    
        .ChartTitle.Text = ActiveSheet.Range("A2")
        .SetSourceData Source:=Range("Sheet1!$C$2:$C$5,Sheet1!$E$2:$I$5")
        
        ActiveChart.PlotBy = xlColumns  'Chart was flipping and I couldn't figure out why, so wrote code to flip it
        
        Set Srs1 = ActiveChart.SeriesCollection(1)
        Srs1.Name = ActiveSheet.Range("$E$1")
        Set Srs2 = ActiveChart.SeriesCollection(2)
        Srs2.Name = ActiveSheet.Range("$F$1")
        Set Srs3 = ActiveChart.SeriesCollection(3)
        Srs3.Name = ActiveSheet.Range("$G$1")
        Set Srs4 = ActiveChart.SeriesCollection(4)
        Srs4.Name = ActiveSheet.Range("$H$1")
        Set Srs5 = ActiveChart.SeriesCollection(5)
        Srs5.Name = ActiveSheet.Range("$I$1")
    
    'Resizes chart
        With ActiveChart.Parent
             .Height = 300
             .Width = 600
             .Top = 100
             .Left = 100
        End With
    End With
    
    'Copy to new tab, name tab same as Chart Title
    'Loop back to beginning for next filter
    
    Dim OutSht As Worksheet
    Dim Chart As ChartObject
    Dim PlaceInRange As Range
    
    Workbooks("Outputs.xlsx").Activate
    Set OutSht = ActiveWorkbook.Sheets("Results") '<-- Output sheet
    Set PlaceInRange = OutSht.Range("B2:J21")        '<-- Output location
    
        Wb.Activate
        For Each Chart In Sheets("Sheet1").ChartObjects   '<-- Loop charts
            Chart.Cut 'Cut/paste charts
            OutSht.Paste PlaceInRange
        Next Chart
    
    Workbooks("Outputs.xlsx").Activate
    Worksheets("Results").Activate
    ActiveSheet.Name = ActiveChart.ChartTitle.Text
    Sheets.Add.Name = "Results"
    
    '88888 Loop back to beginning
    
    ActiveWorkbook.SaveAs Filename:=Wb.Path & "\" & Format(Now, "yyyymmdd") & " Outputs.xlsx"
    
    Kill Wb.Path & "\Outputs.xlsx"
    
    Wb.Activate
    
    End Sub

【问题讨论】:

    标签: excel vba loops for-loop linechart


    【解决方案1】:

    以下代码假定每个位置总是有四个星期。我不确定为什么原始代码创建了“Outputs.xlsx”,只是为了随后将其删除为“YYYYMMDDOutputs.xlsx”。我只是直接去了过时的文件名。我还取消了“结果”选项卡,只是将每个图表都做成了自己的选项卡。

    四分卫子程序ChartAllLocations:

    Public Sub ChartAllLocations()
    
        Dim location As String, WB As Workbook, ws As Worksheet
        Dim resultsWB As Workbook, data As Range, currLocation As Range
        Dim headers As Range
        
        Set WB = ThisWorkbook
        Set ws = WB.Worksheets("Data")
        Set resultsWB = ResultsWorkbook(WB.path)
        Set headers = ws.Range("E1:I1")
    
        locIdx = 2
        Do
            Set data = ws.Cells(locIdx, 1).Resize(4, 9)
            ChartBuilder2 resultsWB, data, headers
            locIdx = locIdx + 4
        Loop While ws.Cells(locIdx, 1).Value <> ""
        
        resultsWB.Worksheets("Sheet1").Delete
    
    End Sub
    

    新 Workook 的功能,ResultsWorkbook

    Private Function ResultsWorkbook(path As String) As Workbook
    
        Dim output As Workbook
        Dim ws As Worksheet
            
        Set output = Workbooks.Add
        output.SaveAs filename:=path & "\" & Format(Now, "yyyymmdd") & " Outputs.xlsx"
            
        Set ResultsWorkbook = output
    
    End Function
    

    构建每个图表的函数ChartBuilder2

    Public Sub ChartBuilder2(WB As Workbook, data As Range, hdrs As Range)
    
        Dim Chrt As Chart
        
        Set Chrt = WB.Charts.Add(After:=WB.Worksheets(WB.Worksheets.Count))
        Chrt.Name = data.Cells(1, 1)
        Chrt.HasTitle = True
        Chrt.ChartTitle.Text = data.Cells(1, 1)
        Chrt.SetSourceData Source:=data.Cells(1, 5).Resize(4, 5)
        Chrt.ChartType = xlLine
        Chrt.PlotBy = xlColumns
        Chrt.FullSeriesCollection(1).XValues = _
            "={""Week 1"",""Week 2"",""Week 3"",""Week 4""}"
        Chrt.Axes(xlValue).TickLabels.NumberFormat = "0%"
        
        
        For srsIdx = 1 To 5
            Chrt.SeriesCollection(srsIdx).Name = hdrs.Cells(1, srsIdx).Value
        Next srsIdx
    
    End Sub
    

    【讨论】:

    • 我使用 Outputs.xlsx 作为通用名称,在两个打开的工作簿之间来回切换,然后将其保存为一个过时的文件并删除不必要的 Outputs.xlsx。您如何建议实现上述代码,以便一个例程可以运行并且所有这三个子程序随后启动?我不熟悉如何在不手动添加的情况下将第二个函数添加到新工作簿中。
    • 四分卫常规已经这样做了。为了清楚起见,我只是将它们分开。将所有三个都放入一个模块并启动 QB 例程。
    • 好的,这几乎是完美的!我注意到的一件事是,我没有在所有地点同时安排四个星期。有些位置只会显示第 1 周、第 2 周、第 3 周 - 有些缺少第 2 周 - 这完全取决于该位置是否必须关闭以进行维护/ COVID。有什么建议吗?
    • 一种解决方案是计算包含当前城市名称的行数,然后使用该数字代替这一行中的4Chrt.SetSourceData Source:=data.Cells(1, 5).Resize(4, 5)。可能还需要进行其他更改,但这是我的方向。
    • 太棒了,非常感谢!目前,我至少可以进入数据集 4 周,然后再追逐这 4 部分。再次感谢!
    猜你喜欢
    • 1970-01-01
    • 2020-09-29
    • 2019-06-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多