在VBA中使用大量命名单元格时,更简单/更简洁的方式来指定范围?

在我正在开发的一个相当大的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)) 

我想我总是可以设置简单的命名variables到这些不同的命名的单元格和范围在开始清理代码的外观,但我有相当一部分,并不真的要添加大量的行variables声明到所有我的潜艇的开始。

更容易阅读的方式 – 是的。 根据需要声明和分配对象variables。 您至less可以定义“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. 使用variables! ( Dim 's是一个小的代价)
  2. 利用其他范围属性。 在这些情况下, Resize是有用的

 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) 

如果你真的在很多不同的Subs中使用它,你也可以创build一个干掉你的代码的函数。

 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) 

你能简单地列出所有的命名Rnages,然后循环通过列表中的每个项目?

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

我不使用命名的范围,因为它们很难维护,很快就会变成一团糟。 我总是使用这两个function:

 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 。