【问题标题】:Dynamic referencing the UsedRange in VBA在 VBA 中动态引用 UsedRange
【发布时间】:2017-02-20 09:22:16
【问题描述】:

我有一个从工作表中获取数据并创建图表的代码。在源表中,每一列都是一个系列,系列的数量可能会发生变化。

我的代码的作用:它读取使用的范围,以便绘制值。

Obs1:我创建的时间序列中的2个,数据是年化的,所以我倒数计算,如果之前的数据小于一年,代码显示为“没有足够的数据”。

问题:如果我使用 2 个时间序列(2 列)运行代码,我会在图表中得到两条线。但是,如果我随后删除其中一个系列并再次运行它,我会在图表中得到一条带值的线和第二条空线。

问题:如何解决这个问题?

我已经尝试过的: 我正在尝试更改引用范围的方式,以便它重新运行代码,它只返回到图表中具有值的行。问题是我找不到这样正确引用范围的方法。

相关部分代码:

Function Grapher(ChartSheetName As String, SourceWorksheet As String, ChartTitle As String, secAxisTitle As String)

Dim lColumn As Long, lRow As Long
Dim LastColumn As Long, LastRow As Long
Dim RetChart As Chart
Dim w As Workbook
Dim RetRange As Range
Dim chrt As Chart
Dim p As Integer
Dim x As Long, y As Long
Dim numMonth As Long
Dim d1 As Date, d2 As Date
Dim i As Long

Set w = ThisWorkbook

'find limit
LastColumn = w.Sheets(SourceWorksheet).Cells(1,   w.Sheets(SourceWorksheet).Columns.Count).End(xlToLeft).column
LastRow = w.Sheets(SourceWorksheet).Cells(w.Sheets(SourceWorksheet).Rows.Count, "A").End(xlUp).Row

'check for sources that do not have full data
'sets the range
i = 3
If SourceWorksheet = "Annualized Ret" Or SourceWorksheet = "Annualized Vol" Then

    Do While w.Worksheets(SourceWorksheet).Cells(i, 2).Text = "N/A"

        i = i + 1

    Loop

'##### this is the part I believe is giving the problem:
    '##### the way to reference the last cell keeps getting the number of columns (for the range) from the original column count. 

    Set RetRange =    w.Worksheets(SourceWorksheet).Range(w.Worksheets(SourceWorksheet).Cells(i, 1), w.Worksheets(SourceWorksheet).Cells.SpecialCells(xlLastCell)) '****************

Else

    Set RetRange = w.Sheets(SourceWorksheet).UsedRange

    'Set RetRange = w.Sheets(SourceWorksheet).Range("A1:" &   Col_Letter(LastColumn) & LastRow)

End If

'''''''''''''''''''''''

For Each chrt In w.Charts
    If chrt.Name = ChartSheetName Then
        Set RetChart = chrt
        RetChart.Activate
        p = 1
    End If
Next chrt

If p <> 1 Then
    Set RetChart = Charts.Add
End If

'count the number of months in the time series, do the ratio
d1 = w.Sheets(SourceWorksheet).Range("A2").Value
d2 = w.Sheets(SourceWorksheet).Range("A" & LastRow).Value

numMonth = TestDates(d1, d2)

x = Round((numMonth / 15), 1)

'ratio to account for period size
If x < 3 Then
    y = 1
ElseIf x >= 3 And x < 7 Then
    y = 4
ElseIf x > 7 Then
    y = 6
End If

'create chart
        With RetChart
            .Select
            .ChartType = xlLine
            .HasTitle = True
            .ChartTitle.Text = ChartTitle
            .SetSourceData Source:=RetRange
            .Axes(xlValue).MaximumScaleIsAuto = True
            .Axes(xlCategory, xlPrimary).HasTitle = True
            .Axes(xlCategory, xlPrimary).AxisTitle.Characters.Text = "Date"
            .Axes(xlValue, xlPrimary).HasTitle = True
            .Axes(xlValue, xlPrimary).AxisTitle.Characters.Text =  secAxisTitle
            .Name = ChartSheetName
            .SetElement (msoElementLegendBottom)
            .Axes(xlCategory).TickLabelPosition = xlLow
            .Axes(xlCategory).MajorUnit = y
            .Axes(xlCategory).MajorUnitScale = xlMonths

'sets header names for modified sources
            If SourceWorksheet = "Drawdown" Then
                For lColumn = 2 To LastColumn

                    .FullSeriesCollection(lColumn - 1).Name = "=DD!$" & Col_Letter(lColumn) & "$1"
                    .FullSeriesCollection(lColumn - 1).Values = "=DD!$" & Col_Letter(lColumn) & "$3:$" & Col_Letter(lColumn) & "$" & LastRow

                Next lColumn

            ElseIf SourceWorksheet = "Annualized Ret" Then
                For lColumn = 2 To LastColumn

                    .FullSeriesCollection(lColumn - 1).Name = "='Annualized Ret'!$" & Col_Letter(lColumn) & "$1"

                Next lColumn

            ElseIf SourceWorksheet = "Annualized Vol" Then
                For lColumn = 2 To LastColumn

                    .FullSeriesCollection(lColumn - 1).Name = "='Annualized Vol'!$" & Col_Letter(lColumn) & "$1"

                Next lColumn

            End If

        End With

End Function

Obs2:我的代码目前功能正常(有些功能我没有添加,以免浪费更多空间)。

Obs3:这是我减少列数(数据系列)时的问题:

【问题讨论】:

  • 您是否尝试过将数据转换为表格,然后图表会随着数据的变化而自动调整?
  • @SJR 不,我没有。愿意举例说明如何做到这一点?
  • @DGMS89 : support.office.com/en-us/article/… 这应该解释很多,简而言之,Excel 表是智能对象(VBA 中的ListObjects),如果您在之后的下一个可用行中添加数据,它将扩展表,所以应该有助于解决您的问题! ;)
  • @R3uK 我读过它,现在正尝试使用该表。一个问题:表格可以直接在图表中使用(作为一个范围)?
  • @DGMS89 :是的,当您选择数据时,您会看到它将使用表格而不是基本的 Excel 引用。记录一个宏,看看它在代码中的样子,并尝试用这种格式更新你的! ;)

标签: vba excel charts range


【解决方案1】:

由于我找不到更好、更优雅的方法来解决这个问题(即使是产生相同错误的表),我通过在最后根据它们的名称明确删除额外的系列来更正。

Obs:如果系列不包含数据,新插入的代码会将系列名称更改为以下名称之一,并完全删除该系列。

要添加到末尾的代码:

'deleting the extra empty series
        Dim nS As Series
        'this has to be fixed. For a permanent solution, try to use tables
        For Each nS In RetChart.SeriesCollection
            If nS.Name = "Series2" Or nS.Name = "Series3" Or nS.Name = "Series4" Or nS.Name = "Series5" Or nS.Name = "Series6" Or nS.Name = "Series7" Or nS.Name = "Series8" Or nS.Name = "" Then
                nS.Delete
            End If
        Next nS

【讨论】:

    猜你喜欢
    • 2020-12-21
    • 2015-02-09
    • 1970-01-01
    • 2018-03-29
    • 2014-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多