遍历每个打开的工作簿和工作表中的所有单元格并获得评论

时间:2015-05-29 08:48:50

标签: excel vba excel-vba

我正在尝试从一组工作簿和工作表中提取所有标题字段及其注释。我正在尝试找到所有已锁定的单元格,而不是空单元格,而不是计算单元格。我把这段代码放在一起,但它在cell.comment.text行引发了错误。它返回错误:

Run-time error '91': Object Variable or With block variable not set

Sub extract()
Dim WB As Workbook
Dim ws As Worksheet: Dim Db As Worksheet
Dim NoRow As Integer: Dim i As Integer: Dim j As Integer
Dim cell

'   On Error GoTo extract_Error
Set Db = ThisWorkbook.Sheets("Data")

With Application
    .ScreenUpdating = False
End With

For Each WB In Application.Workbooks
    If Not WB.Name = ThisWorkbook.Name Then
        For Each ws In WB.Sheets
            i = Db.Cells(Db.Rows.Count, 1).End(xlUp).Row
            For Each cell In ws.UsedRange.Cells
                If cell.Locked = True And IsEmpty(cell) = False And cell.HasFormula = False Then
                    i = i + 1
                    Db.Cells(i, 1) = WB.Name
                    Db.Cells(i, 2) = ws.Name
                    Db.Cells(i, 3) = cell.Value
                    Db.Cells(i, 4) = cell.Comment.Text
                End If
            Next cell
        Next ws
    End If
Next WB

With Application
    .ScreenUpdating = True
End With

On Error GoTo 0
   Exit Sub

extract_Error:

MsgBox "Error " & Err.Number & " (" & Err.Description & ") in procedure extract of Module Module1"
End Sub

3 个答案:

答案 0 :(得分:3)

或者你可以在之前测试它:

If Not cell.Comment Is Nothing Then Db.Cells(i, 4) = cell.Comment.Text

答案 1 :(得分:1)

因为Cell.Comment可以为null,如果要跳过任何错误,可以在其前面添加On Error Resume Next,您可以始终将On Error GoTo 0置为抛出其他错误:

For Each WB In Application.Workbooks
   If Not WB.Name = ThisWorkbook.Name Then
       For Each ws In WB.Sheets
           i = Db.Cells(Db.Rows.Count, 1).End(xlUp).Row
           For Each cell In ws.UsedRange.Cells
               If cell.Locked = True And IsEmpty(cell) = False And cell.HasFormula = False Then
                   i = i + 1
                   Db.Cells(i, 1) = WB.Name
                   Db.Cells(i, 2) = ws.Name
                   Db.Cells(i, 3) = cell.Value
                   On Error Resume Next
                   Db.Cells(i, 4) = cell.Comment.Text
                   On Error GoTo 0
               End If
           Next cell
       Next ws
   End If
Next WB

如果要捕获并打印错误,请执行以下操作:

Sub test()
    On Error Resume Next
    a = 5 / 0
    If Err.Number > 1 Then
        Debug.Print Err.Description
    End If
End Sub

编辑:正如@CmPi所建议的那样 - 让异常泡沫化的速度可能比事先测试案例要慢:

If Not cell.Comments Is Nothing Then
  Db.Cells(i, 4) = cell.Comment.Text
End If

答案 2 :(得分:0)

我目前在linux机器上无法尝试代码,但是您尝试将cell.comment.text转换为字符串,因此即使它是空的,它也应该返回一个空字符串值

Db.Cells(i, 4) = CStr(cell.Comment.Text)

如果不是这样,您的代码也将返回空注释,那么您需要添加

if CStr(cell.comment.text) <> "" then
    Db.Cells(i, 4) = CStr(cell.Comment.Text)
end if