【问题标题】:Cannot use named range when it is empty为空时不能使用命名范围
【发布时间】:2013-12-10 02:23:05
【问题描述】:

我有一个命名范围 lstVendors,它指的是:=OFFSET(Data!$W$2,0,0,COUNTA(Data!$W$2:$W$400),1)。我希望在工作簿打开时填充此范围。我有以下代码:

Private Sub Workbook_Open()
    Application.WindowState = xlMaximized
Dim rslt()
Dim i As Integer
Dim n As Integer
Dim startRng As Range
Dim DropDown1 As DropDown

ThisWorkbook.Sheets("Dashboard").Shapes("TextBox 6").Visible = False
'    Range("lstVendors").Offset(0, 0).Value = "Please Select..."
'    Set DropDown1 = ThisWorkbook.Sheets("Dashboard").DropDowns("Drop Down 1")
'    DropDown1.Value = 1
On Error Resume Next
If Not IsError(Range("lstVendors")) Then
    Range("lstVendors").ClearContents
End If
On Error GoTo 0
rslt = Application.Run("SQLite_Query", "path/to/my/sqlite", "SELECT PROGRAM_ID FROM VENDOR;")
Set startRng = Range("lstVendors")
i = 0
For n = 2 To UBound(rslt)
    Range("lstVendors").Offset(i, 0).Value = rslt(n)(0)
    i = i + 1
Next n
End Sub

Set startRng = Range("lstVendors") 出错。我知道这是因为当我尝试设置它时,该范围内没有任何内容,因为如果我将一个条目放入命名范围,则该集合可以工作,但是,我需要在每次打开时由 sqlite 查询填充它作为数据变化。

非常感谢任何建议。

【问题讨论】:

  • 您收到什么错误信息?另外,我不确定您的On Error Resume Next 使用得当。
  • 对不起,这是一个运行时错误“1004”:对象“_Global”的方法“范围”失败。它基本上认为命名范围不存在,因为它是空白的。 Application.Goto Worksheets("Data").Range("lstVendors") 返回相同的错误。
  • 错误是因为你的 sql 没有返回任何结果,所以它使公式的 COUNTA 部分无效?如果是这样,请尝试将其包装在 Max 语句中,如下所示: =OFFSET(Data!$W$2,0,0,MAX(COUNTA(Data!$W$2:$W$400),2),1)
  • @Methonis 清除后范围不存在。 Name 确实存在,但范围不存在。无论如何,您不需要在代码中使用它。在下面检查我的答案。

标签: vba excel


【解决方案1】:

试试这个。清除内容后,您有一个不评估的动态范围。为了避免这种情况,可能有几种方法,但很容易简单地硬编码startRange 变量,使其始终指向Data!$W$2 地址,这是(或者更确切地说,将成为)lstVendors 范围中的第一个单元格。

Private Sub Workbook_Open()

Dim rslt()
Dim i As Integer
Dim n As Integer
Dim startRng As Range
Dim DropDown1 As DropDown
Dim rngList As Range

'// Define your startRange -- always will be the first cell in your named range "lstVendors"
'   hardcode the address because the dynamic range may not evalaute.
Set startRange = Sheets("Data").Range("W2")

'// Empty th lstVendors range if it exists/filled
On Error Resume Next
    Range("lstVendors").Clear
On Error GoTo 0

'// Run your SQL query
rslt = Application.Run("SQLite_Query", "path/to/my/sqlite", "SELECT PROGRAM_ID FROM VENDOR;")
i = 0

'// Print results to the Worksheet, beginning in the startRange cell
For n = 2 To UBound(rslt)
    'Increment from the startRange cell
    startRange.Offset(i, 0).Value = rslt(n)(0)
    i = i + 1
    'Verify that "lstVendors" is being populated
    Debug.Print Range("lstVendors").Address
Next n


End Sub

【讨论】:

  • 谢谢,大卫。这很有效,尽管我希望 Excel 能够提供一种仍然使用范围名称的方法。这样做,它在某种程度上消除了命名范围的点,因为您必须首先引用特定的单元格位置(这意味着如果我更改命名范围的开头,我也必须更改 VBA)。但是,从我尝试过的所有事情来看,我都没有看到任何解决方法。
  • @Methonis 你看到我上面的建议了吗,将 counta 包装在 Max 参考中: =OFFSET(Data!$W$2,0,0,MAX(COUNTA(Data!$W$2:$W $400),2),1)
  • @sous2817 sql语句返回预期结果。我想我遇到了另一种解决方案。会在几张贴。感谢您的想法。
  • 另一种方法是创建一个命名的动态范围,该范围将始终评估为有效的范围参考。然后你就可以使用它了。但是您的参考无效 - 它减少到Range("W2").Resize(0,0)。你也许可以(我还没试过)试试Range("lstVendors").Resize(n,1).Offset(i, 0) = ...。不确定它是如何工作的,或者它是否适用于动态范围。
  • 编辑:不,这也不起作用,因为范围是动态的,它真的评估为 Nothing.Resize(0,0)Nothing.Offset(1,0) - 无法编译(从 what???)。当范围对象为Nothing 时,您不能使用范围方法。干杯。
【解决方案2】:

感谢您的建议。这是我最终为了解决我的问题所做的事情。它涉及在我原来的问题中添加一些我没有指定的东西,所以如果我做的不是一个选项,大卫的回答很好。我首先用“请选择...”和“全部”填充了命名范围中的前两个单元格。在 Sub Workbook_Open() 我们这样做:

Private Sub Workbook_Open()
Application.WindowState = xlMaximized
Dim rslt()
Dim i As Integer
Dim n As Integer
Dim startRng As Range
Dim DropDown1 As DropDown

' Disable our not found message
ThisWorkbook.Sheets("Dashboard").Shapes("TextBox 6").Visible = False
' Set our start range to our named range
Set startRng = Range("lstVendors")
' Grab all vendor names
rslt = Application.Run("SQLite_Query", "path/to/my/sqlite", "SELECT PROGRAM_ID FROM VENDOR;")
' Print result. Skip first two rows as constants "Please Select..." and "All" are populated there
i = 2
For n = 2 To UBound(rslt)
    startRng.Offset(i, 0).Value = rslt(n)(0)
    i = i + 1
Next n
End Sub

然后我们将创建 Sub Workbook_BeforeClose:

Private Sub Workbook_BeforeClose(Cancel As Boolean)
' Disable the save changes dialog. This workbook will be locked up for display only. No need to confuse the user.
Application.DisplayAlerts = False
' Clear everything below the "Please Select..." and "All" cells in the named range
On Error Resume Next
Range("lstVendors").Offset(2, 0).ClearContents
On Error GoTo 0
' Save the changes to the named range
ThisWorkbook.Save
Application.DisplayAlerts = True
End Sub

此信息将填充到下拉列表中,因此我可以接受将 Please Select 和 All 硬编码到命名范围中。如果该规定不适用于将来查看此内容的其他人,请使用 David 的建议!再次感谢!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-23
    相关资源
    最近更新 更多