动态引用VBA中的UsedRange [英] Dynamic referencing the UsedRange in VBA

查看:210
本文介绍了动态引用VBA中的UsedRange的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个代码从表单获取数据并创建一个图形。在源表中,每列是一系列的,系列的数量可能会改变。



我的代码做了什么:范围,以便它可以绘制值。



Obs1:对于我创建的时间序列中的2个,数据是年化的,因此我向后计算,如果以前的数据少于一年,代码显示为不够数据。



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



问题: / strong>如何解决这个问题?



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



代码的相关部分:

$ b $函数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

设置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

'没有完整数据的资源
'设置范围
i = 3
如果SourceWorksheet =年度Ret或SourceWorksheet =Annualized Vol然后

尽管w.Worksheets(SourceWorksheet).Cells(i,2).Text =N / A

i = i + 1

循环

'#####这是我认为是出现问题的部分:
'#####引用最后一个单元格,从原始列计数中获取列数(范围)。

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

Else

设置RetRange = w.Sheets(SourceWorksheet).UsedRange

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

End If

'''' '''''''''''''''''''''''''''''''''$'
对于每个chrt RetChart = chrt
RetChart.Activate
p = 1
结束如果
下一个chrt

如果p < 1然后
Set RetChart = Charts.Add
End If

'计算时间序列中的月份数,执行比例
d1 = w.Sheets( Value(A2)。值
d2 = w.Sheets(SourceWorksheet).Range(A& LastRow).Value

numMonth = TestDates(d1,d2 )

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

'与期间大小的比例
如果x < 3然后
y = 1
ElseIf x> = 3而x < 7然后
y = 4
ElseIf x> 7然后
y = 6
如果

'创建图表
使用RetChart
。选择
.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

'设置修改源的标题名称
如果SourceWorksheet =Drawdown,然后
对于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

下一个lColumn

ElseIf SourceWorksheet =Annualized Ret然后
对于lColumn = 2 To LastColumn

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

下一个lColumn

ElseIf SourceWorksheet =Annualized Vol然后
对于lColumn = 2 To LastColumn

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

下一页lColumn

如果

结束

结束函数

Obs2:我的代码目前正在运行(有一些功能我还没有添加,浪费更多空间)



Obs3:当我减少列数(数据系列)时,这是一个问题:

解决方案

既然我找不到更好,更优雅的方式来解决这个问题(甚至表中出现相同的错误),我通过明确删除最后的额外系列,根据他们的名字进行了更正。



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



要添加到最后的代码:

 '删除额外的空系列
Dim nS As Series
'这必须被修复。对于永久解决方案,尝试使用表
对于每个nS In RetChart.SeriesCollection
如果nS.Name =Series2或nS.Name =Series3或nS.Name =Series4或nS .Name =Series5或nS.Name =Series6或nS.Name =Series7或nS.Name =Series8或nS.Name =然后
nS.Delete
结束如果
下一个nS


I have a code that gets data from a sheet and creates a graph. In the source sheet, each column is a series, and the number of series may change.

What my code does: it reads the used ranges so that it can graph the values.

Obs1: For 2 of the time series I create, the data is annualized, so as I count backwards for the calculation, if the data before is less than one year, the code shows as "Not Enough Data".

Problem: If I run the code with 2 time series (2 columns), I get two lines in the charts. But if I then delete one of the series and run it again, I get one line with values and a second empty line in the chart.

Question: How can this problem be solved?

What I already tried: I am trying to change the way I reference the ranges, so that it rerun the code, it returns to the graph only lines that have values. Issue is I cannot find a way to properly reference the range like that.

Relevant part of the code:

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: My code is currently functional (there are some functions I haven't added, so as not to waste more space).

Obs3: This is the problem when I decrease the number of columns (data series):

解决方案

Since I could find no better, more elegant way to approach this problem (even the tables where yielding the same error), I corrected, by explicitly deleting the extra series in the end, based on their names.

Obs: If the Series contained no data, the new inserted code will change that series name to one of the ones below, and delete that series altogether.

Code to be added to the end:

'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

这篇关于动态引用VBA中的UsedRange的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆