在VBA中使用大量命名单元格时指定范围的更简单/更清晰的方法?

时间:2015-12-08 21:00:07

标签: excel vba excel-vba named-ranges

在我正在研究的一个相当大的Excel程序中,我在电子表格中有很多命名单元格,这些单元格填充了数据,以便在用户决定移动模板设置时帮助保持格式一致,并且避免硬编码各个子行中的行/列号。不幸的是,这导致我的代码中有许多丑陋的范围引用,下面的示例。是否有更简单/更清晰的外观,更容易阅读的方式来写这些我错过了?

'Examples of ugly range references:
Range(Range("GS_BeginData").Offset((counter + m), -1), Range("GS_BeginData").Offset((counter + m), 2))

Range(Range("GS_BeginData").Offset(counter, 1), Range("GS_BeginData").Offset((counter + fileCount), 1))

Range("SS_Unit", Range("SS_Unit").Offset(0, 1))

Range("SS_BeginData", Range("SS_BeginData").End(xlDown))

Cells((Range("SS_BeginData").Row + i), (Range("SS_BeginData").Column + 1))

我想我总是可以在Subs的开头为这些不同的命名单元和范围设置简单的命名变量来清理代码的外观,但是我有很多它们并且不想真的想添加大量的变量声明行到我所有的Subs的开头。

5 个答案:

答案 0 :(得分:1)

更易读的方式 - 是的。根据需要声明和分配对象变量。至少,您可以定义“GS_BeginData”和“SS_Unit”以及“SS_BeginData”的范围,这将使您的代码更易读和可维护。

这样,如果您更改了命名范围引用的名称,您只需要更新分配给初始对象的一些短代码,而不是每个文字引用,例如,到"GS_BeginData"等等。

Dim GSBegin as Range, SSBegin as Range, SSUnit as Range

Set GSBegin = Range("GS_BeginData")
Set SSBegin = Range("SS_BeginData")
Set SSUnit = Range("SS_Unit")

然后,您可以修改丑陋的引用:

Range(GSBegin.Offset((counter + m), -1), GSBegin.Offset((counter + m), 2))

Range(GSBegin.Offset(counter, 1), GSBegin.Offset((counter + fileCount), 1))

SSUnit.Offset(0, 1)

Range(SSBegin, SSBegin.End(xlDown))

Cells((SSBegin.Row + i), (SSBegin.Column + 1))

答案 1 :(得分:1)

  1. 使用变量! (Dim' s是一个很小的代价)
  2. 利用其他范围属性。在这些情况下Resize很有用
  3. Dim GS_BeginData As Range
    Set GS_BeginData = Range("GS_BeginData")
    'Set r = Range(Range("GS_BeginData").Offset((counter + m), -1), Range("GS_BeginData").Offset((counter + m), 2))
    Set r = GS_BeginData.Offset(counter + m, -1).Resize(, 3)
    
    'Set r = Range(Range("GS_BeginData").Offset(counter, 1), Range("GS_BeginData").Offset((counter + fileCount), 1))
    Set r = GS_BeginData.Offset(counter, 1).Resize(fileCount, 1)
    
    Dim SS_Unit As Range
    Set SS_Unit = Range("SS_Unit")
    'Set r = Range("SS_Unit", Range("SS_Unit").Offset(0, 1))
    Set r = SS_Unit.Resize(, 2)
    Set r = SS_Unit.Resize(, SS_Unit.Columns.Count + 1) ' if SS_Unit has more than 1 column
    
    Dim SS_BeginData As Range
    Set SS_BeginData = Range("SS_BeginData")
    'Set r = Range("SS_BeginData", Range("SS_BeginData").End(xlDown))
    Set r = Range(SS_BeginData, SS_BeginData.End(xlDown))
    
    'Set r = Cells((Range("SS_BeginData").Row + i), (Range("SS_BeginData").Column + 1))
    Set r = SS_BeginData.Offset(i, 1).Resize(1, 1)
    

答案 2 :(得分:1)

如果你真的在许多不同的子套件中使用它,你也可以使用DRY代码编写功能,例如。

Function GSBeginOffsetRange(a As Long, b As Long, c As Long, d As Long) As Range
    Dim GSBegin As Range
    Set GSBegin = Range("GS_BeginData")
    Set GSBeginOffsetRange = Range(GSBegin.Offset(a, b), GSBegin.Offset(c, d))
End Function

这将是你的第一行示例:

GSBeginOffsetRange((counter + m), -1, (counter + m), 2)

答案 3 :(得分:0)

您可以简单地列出所有命名的Rnages,然后遍历该列表中的每个项目吗?

http://www.mrexcel.com/forum/excel-questions/44907-list-out-named-ranges-visual-basic-applications.html

答案 4 :(得分:-1)

我没有使用命名范围,因为它们难以维护并很快变得一团糟。我总是使用这两个函数:

Function RowNumber(Header As String, _
             Optional Sh As Worksheet, _
             Optional FromColumn As Integer = 1, _
             Optional IgnoreError As Boolean = False) As Integer
  If Sh Is Nothing Then Set Sh = ActiveSheet

  Dim R As Integer
  For R = 1 To Sh.UsedRange.Row + Sh.UsedRange.Rows.Count - 1
    If Sh.Cells(R, FromColumn) = Header Then RowNumber = R: Exit Function
  Next R

  If Not IgnoreError Then MsgBox "Row """ & Header & """ not found", vbCritical
End Function

Function ColumnNumber(Header As String, _
             Optional Sh As Worksheet, _
             Optional FromRow As Integer = 1, _
             Optional IgnoreError As Boolean = False) As Integer
  If Sh Is Nothing Then Set Sh = ActiveSheet

  Dim C As Integer
  For C = 1 To Sh.UsedRange.Column + Sh.UsedRange.Columns.Count - 1
    If Sh.Cells(FromRow, C) = Header Then ColumnNumber = C: Exit Function
  Next C

  If Not IgnoreError Then MsgBox "Column """ & Header & """ not found", vbCritical
End Function

然后我得到的值如下:

Value = Sh.Cells(RowNumber("Header", Sh), 2)

我有时会使用memoization的其他版本。