运行-当我指的是未命名的范围时出现错误“1004”

Run-time error '1004' when I'm referring to a range that is not named

我正在尝试在另一个工作簿中的 Excel 作品sheet 中放置一个下拉菜单,其中包含另一个作品sheet 中的选项。我正在使用 VBA,因为 我想根据另一个下拉菜单 自定义这些选项。我设法通过在源 sheet 中命名范围来做到这一点,但该文件是只读的,所以我无法保存名称来自动执行该过程。所以我试着只使用引用中的列名(比如 $B:$B,我只需要 B 列),但是当我 运行 宏停止时出现 运行-time error 1004 .

Private Sub Worksheet_Change(ByVal Target As Range)
    Dim KeyCells As Range
    Set KeyCells = Range("H6")

    If Not Application.Intersect(KeyCells, Range(Target.Address)) Is Nothing Then
        Call main
    End If
End Sub

Private Sub main()
    reason = Range("H6").Value
    List = ""

    If reason = "Project ID/Task ID" Then
        List = "=PIDTID"
    Else
        List = "=Cost_Center"
    End If

    With Range("I6").Validation
        .Delete
        .Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, _
            Operator:=xlBetween, Formula1:=List
        .IgnoreBlank = True
        .InCellDropdown = True
        .InputTitle = ""
        .ErrorTitle = ""
        .InputMessage = ""
        .ErrorMessage = ""
        .ShowInput = True
        .ShowError = True
    End With
End Sub

这是我的宏,如您所见,main() 是在更改 H6 时调用的,因为那是我的其他下拉菜单所在的位置。然后,根据该单元格的值,List 被分配一个等于定义的名称的值,该名称引用其他作品中的范围sheet。

例如,如果 PIDTID 名称等于 ='[20190812_WP_and_CostCenters_Responsible.xls]Projects responsibles'!WBSName,则脚本有效。请注意,WBSName 是为源 sheet 中的列 B 指定的名称。

如果我将 PIDTID 设置为 ='[20190812_WP_and_CostCenters_Responsible.xls]Projects responsibles'!$B:$B,我将在

行收到错误

.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, _ Operator:=xlBetween, Formula1:=List

Cost_Center 名称作用相同。

我想提一下,这些测试是在打开源文件的情况下完成的。如果我尝试关闭它,我会得到同样的错误。

有没有办法消除错误,或者我可以通过另一种方法在不命名的情况下引用其他工作簿的 sheet 中的单元格?我也想在不打开源文件的情况下工作。谢谢!

正如 JvdV 在评论中所写,这是因为您不能在列表引用另一个工作簿的地方使用数据验证,至少不能以简单的方式进行验证。

您可以通过使用此公式向可写工作簿添加命名范围来规避它(假设 Cost_Center 在 C 列中)

=IF(Sheet1!H6="PIDTID",OFFSET('[20190812_WP_and_CostCenters_Responsible.xls]Projects responsibles'!$B:$B,0,0),OFFSET('[20190812_WP_and_CostCenters_Responsible.xls]Projects responsibles'!$C:$C,0,0))

然后在您的数据验证/宏中使用这个命名范围。 缺点是源工作簿必须打开下拉菜单才能工作

"Is there a way to get rid of the error, or another way by which I can refer to cells in sheets of other workbooks without naming them? I would also like to work without having to open the source file. Thank you!"

让我试一试:)

根据 this 文档,您不能使用对另一个工作簿的引用(没有命名范围)。当然不是在封闭的工作簿中。参考@Gh3ttoKinG 他的回答:).

所以这可能会做得更聪明,但要做到这一点 无需打开 我考虑使用 ExecuteExcel4Macro 的工作簿。在@SiddharthRout 的 this 回答的帮助下,我们可以开始从已关闭的工作簿中提取信息:

Sub Test()

Dim wbPath As String, wbName As String
Dim wsName As String, cellRef As String
Dim Ret As String
Dim lr As Long
Dim arr() As String

wbPath = "C:\Users\....\SO\"
wbName = "SO.xlsx"
wsName = "Sheet1"

'Get the last row from B column, notice we need R1C1 notation for Excel4Macro
lr = ExecuteExcel4Macro("COUNTA('" & wbPath & "[" & wbName & "]" & wsName & "'!C2)")

'Let's use an array to fill our validation list with later on
ReDim arr(1 To lr)
For x = 1 To lr
    arr(x) = ExecuteExcel4Macro("'" & wbPath & "[" & wbName & "]" & wsName & "'!R" & x & "C2")
Next x

'Join the array together to make a string which will be accepted in the validation list
With Range("I6").Validation
    .Delete
    .Add Type:=xlValidateList, Formula1:=Join(arr, ",")
    .IgnoreBlank = True
    .InCellDropdown = True
    .InputTitle = ""
    .ErrorTitle = ""
    .InputMessage = ""
    .ErrorMessage = ""
    .ShowInput = True
    .ShowError = True
End With

End Sub

有些事情我会尝试 "smoothen" 例如 COUNTA 不是获得 lr 变量的最佳方法,而且可能有一种方法可以提取完整的立即进入 arr() 变量范围。

不过,这可能会激发一些创意 ;)


编辑

另一种检索字符串数据最后一行的方法是使用 MATCH,如下所示:

lr = ExecuteExcel4Macro("MATCH(""zzz"",'" & wbPath & "[" & wbName & "]" & wsName & "'!C2)")