运行时错误 '424' 需要对象 - 不确定我在此代码中写错了什么?


Sub automated_gr_lookup()
Dim st As Long
Dim en As Long
Dim c1 As Long
Dim c2 As Long
Dim iRowAsset As Integer
Dim table As Range
Dim tmpRiskID As Variant
Sheets("Geotechnical Risk Register").Select
Application.ScreenUpdating = False
Set assetTbl = Application.Range("M002_") 'Asset table = DES M002
Set riskTbl = Application.Range("geotechRisks") 'GRR
Set compiledTbl = Application.Range("CompiledM002") 'Output for M002

For iRowRisk = 1 To riskTbl.Rows.Count 'loop through risks
tmpRiskID = riskTbl.Row.Range("Ref No. ID") 'Temporary risk as it gets overridden

'if assets chainage match risk iRowRisk (4 conditions)
If (en > c1 And en < c2) Or (st > c1 And en < c2) Or (st > c1 And st < c2) Or (st < c1 And en > c2) Then
'copy asset row
assetTbl.Rows(iRowAsset).Copy
'paste row in compiled
compiledTbl.Rows(xlEndRow).PasteSpecial xlPasteValues
'paste risk id in last column of that row
compiledTbl.Cells(xlEndRow, ColumnH).Value = tmpRiskID
End If
Next iRowRisk
End Sub

tmpRiskID = riskTbl.Row.Range("Ref No. ID")在线遇到runtime error 424,不知道为什么?我目前正在尝试将其分配给表标题。

Sheets("Geotechnical Risk Register").Select

这就是问题开始的地方。此工作表在哪里?如果它位于碰巧处于活动状态的任何工作簿中,则运行时错误 9"下标超出范围"等待提醒您,无论碰巧处于活动状态的工作簿,都不一定具有该名称的工作表。

如果工作表位于托管VBA代码的同一工作簿中,那么您不希望"当前处于活动状态的任何工作簿",而是ThisWorkbook- 这已经更好了:

ThisWorkbook.Worksheets("Geotechnical Risk Register").Select

但是,您无需.Select任何事情。考虑:

Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Geotechnical Risk Register")

好多了:现在我们可以针对该特定工作表进行成员调用,并且我们知道我们正在针对正确的工作表进行工作。

除非,如果工作表在编译时存在于ThisWorkbook中,那么它是完全多余的。

在 VBE 的项目资源管理器工具窗口中选择 Tab 模块 (Ctrl+R(,然后显示其属性(F4(。属性列表的顶部是一个(Name)属性,目前可能类似于Sheet42- 将其更改为更有意义的内容,例如GeotechRiskRegisterSheet。现在,您有一个名为GeotechRiskRegisterSheet的全局范围(实际上是项目范围(对象变量,您可以在 VBA 项目中的任何位置使用它来引用该特定工作表

本答案的其余部分假设您已经这样做了。如果工作表不在ThisWorkbook中,则坚持为其声明局部Worksheet变量,并从您要使用的工作簿的Workbook.Worksheets集合中提取Worksheet对象引用。

Set assetTbl = Application.Range("M002_")

这是分配给一个变量,该变量似乎想要成为局部变量,但未在本地范围内的任何地方声明。Application.Range仅比Range略好,并且距离最明确的ActiveSheet.Range只有一个级别的间接寻址 - 但话又说回来,你并不是要解决ActiveSheet 是什么,虽然表确实定义了命名范围,并且可以使用Range属性访问命名范围,但这将更加清晰和绝对明确:

Dim assetTbl As ListObject
Set assetTbl = GeotechRiskRegisterSheet.ListObjects("M002_")

这同样适用于其他两个:

Set riskTbl = Application.Range("geotechRisks") 'GRR
Set compiledTbl = Application.Range("CompiledM002") 'Output for M002

选择:

Dim riskTbl As ListObject
Set riskTbl = GeotechRisksSheet.ListObjects("geotechRisks")
Dim compiledTbl As ListObject
Set compiledTbl = CompiledSheet.ListObjects("CompiledM002")

然后我们开始循环:

For iRowRisk = 1 To riskTbl.Rows.Count 'loop through risks

如果riskTbl只是另一个Range,那么这就可以了。如果riskTbl是一个ListObject,我们可以做得更简单、更快:

Dim currentRow As ListRow
For Each currentRow In riskTbl.ListRows

然后我们得到你问的运行时错误:

tmpRiskID = riskTbl.Row.Range("Ref No. ID") 'Temporary risk as it gets overridden

这是错误 424"需要对象",因为riskTbl.Row是一个Long整数值:它没有Range成员,所以你不能这样做Range.Row.Range。如果您正在使用该For iRowRisk循环迭代普通Range,那么您希望它看起来像这样:

tmpRiskID = riskTbl.Cells(iRowRisk, 12).Value

其中12是硬编码的列索引,指的是"Ref No.ID"列。不理想,是吗?与利用ListObjectAPI 相比:

Dim refIDColumn As Long
refIDColumn = riskTbl.ListColumns("Ref No. ID").Index
tmpRiskID = currentRow.Range.Cells(ColumnIndex:=refIDColumn).Value

如果在循环外部定义refIDColumn变量,则每次迭代都可以重用其值,并且只要标题标题保持"Ref No.ID",该列可以是用户想要的任何位置 - 而对于硬编码的列索引,如果用户插入新列,代码就会中断。

'if assets chainage match risk iRowRisk (4 conditions)
If (en > c1 And en < c2) Or (st > c1 And en < c2) Or (st > c1 And st < c2) Or (st < c1 And en > c2) Then

我希望您在实际代码中声明并分配了这些变量 - 否则无法可靠地计算此条件表达式,因为这些标识符都没有值。考虑使用有意义的名称来传达使用意图:enstc1c2对于任何不太熟悉编写该代码的人的思维过程的人来说,绝对没有任何意义。无论如何,请确保模块的顶部显示Option Explicit某处。

'copy asset row
assetTbl.Rows(iRowAsset).Copy
'paste row in compiled
compiledTbl.Rows(xlEndRow).PasteSpecial xlPasteValues
'paste risk id in last column of that row
compiledTbl.Cells(xlEndRow, ColumnH).Value = tmpRiskID

我不相信你真的需要在这里涉及剪贴板。同样,考虑利用ListObjectAPI - 这应该有效(未经测试(:

With compiledTbl.ListRows.Add
.Range.Value = currentRow.Range.Value
.Range.Cells(ColumnIndex:=compiledRiskIdColumn).Value = tmpRiskID
End With

在循环体之前声明和分配compiledRiskIdColumn

Dim compiledRiskIdColumn As Long
compiledRiskIdColumn = compieldTbl.ListColumns("Risk ID").Index '<~ verify column title

最新更新