programing

VBA: 사용자가 셀을 삭제하면 Range 객체는 어떻게 됩니까?

lastmoon 2023. 4. 22. 10:00
반응형

VBA: 사용자가 셀을 삭제하면 Range 객체는 어떻게 됩니까?

에 변수를 가진 모듈이 있다고 가정합니다.r타입의Range어느 시점에서 Range 객체(액티브 셀 등)를 저장한다고 가정합니다.자, 이제 질문하겠습니다.가치에는 어떤 변화가 있을까?r사용자가 셀(셀 값뿐만 아니라 셀)을 삭제했을 경우

나는 VBA에서 이것을 알아내려고 노력했지만 성공하지 못했다.결과는 이상하다. r아니다Nothing, 의 가치r유형으로 보고되다Range그러나 디버거 창에서 해당 속성을 확인하려고 하면 각 속성 값이 "개체 필요"로 보고됩니다.

프로그래밍 방식으로 변수인지 아닌지를 결정하려면 어떻게 해야 합니까?r이 상태인가요, 아닌가요?

에러를 생성하여 검출하지 않고 실행할 수 있습니까?

좋은 질문입니다!지금까지 이것에 대해 생각해 본 적은 없지만, 이 함수는 초기화된 범위(아무것도 아님)를 식별하지만 셀이 삭제되었기 때문에 현재 "개체 필요" 상태에 있는 범위를 식별합니다.

Function RangeWasDeclaredAndEntirelyDeleted(r As Range) As Boolean
Dim TestAddress As String

If r Is Nothing Then
    Exit Function
End If
On Error Resume Next
TestAddress = r.Address
If Err.Number = 424 Then    'object required
    RangeWasDeclaredAndEntirelyDeleted = True
End If
End Function

다음과 같이 테스트할 수 있습니다.

Sub test()
Dim r As Range

Debug.Print RangeWasDeclaredAndEntirelyDeleted(r)
Set r = ActiveSheet.Range("A1")
Debug.Print RangeWasDeclaredAndEntirelyDeleted(r)
r.EntireRow.Delete
Debug.Print RangeWasDeclaredAndEntirelyDeleted(r)
End Sub

VBA에서 Set 키워드를 사용하면 지정한 워크시트에 있는 워크시트의 Range 객체에 대한 포인터가 백그라운드에서 생성된다고 생각합니다(각 셀은 지정된 범위에 대한 워크시트의 셀 컬렉션에 있는 개체입니다).메모리 내에서 범위를 참조하고 있을 때 범위가 삭제되면 범위 변수가 가리킨 개체의 메모리가 할당 해제됩니다.

그러나 Range 변수에는 최근에 삭제한 Range 객체에 대한 포인터가 포함되어 있을 가능성이 매우 높기 때문에 아무것도 아니지만 이 객체가 가리키는 포인터는 더 이상 존재하지 않기 때문에 변수를 다시 사용하려고 하면 문제가 발생합니다.

이 코드를 체크하면 무슨 뜻인지 알 수 있습니다.

Public Sub test2()
    Dim r As Excel.Range
    Debug.Print ObjPtr(r)           ' 0

    Set r = ActiveSheet.Range("A1")
    Debug.Print ObjPtr(r)           ' some address

    r.Value = "Hello"

    r.Delete
    Debug.Print ObjPtr(r)           ' same address as before
End Sub

ObjPtr()에 대한 자세한 내용은 다음 문서를 참조하십시오.http://support.microsoft.com/kb/199824

따라서 객체에 대한 유효한 주소가 있는 동안 객체가 삭제되었기 때문에 객체는 더 이상 존재하지 않습니다.게다가 「Is Nothing」은, 포인터의 주소를 체크하는 것 뿐입니다(VBA는 변수를 「Set」라고 믿고 있는 것 같습니다).

이 문제를 어떻게 해결할 수 있을지 아쉽지만, 현재로선 깔끔한 방법을 찾을 수 없습니다(이 문제를 해결할 수 있는 좋은 방법을 찾는 사람이 있으면 게시해 주세요!).다음과 같이 On Error Resume Next를 사용할 수 있습니다.

Public Sub test3()
    Dim r As Excel.Range
    Debug.Print ObjPtr(r)           ' 0

    Set r = ActiveSheet.Range("A1")
    Debug.Print ObjPtr(r)           ' some address

    r.Value = "Hello"

    r.Delete
    Debug.Print ObjPtr(r)           ' same address as before

    On Error Resume Next
    Debug.Print r.Value
    If (Err.Number <> 0) Then
        Debug.Print "We have a problem here..."; Err.Number; Err.Description
    End If
    On Error GoTo 0
End Sub

변수 r이 이 상태인지 아닌지는 프로그래밍 방식으로 어떻게 판단할 수 있습니까?

에러를 생성하여 검출하지 않고 실행할 수 있습니까?

아니요.

제가 아는 한, 이 상태를 확실하게 테스트할 수 없습니다. 오류를 발생시키고 발견하지 않으면 안 됩니다.

귀하의 질문은 다른 곳에서 확인논의되었습니다.Excel/VBA 블로그의 거물 2명(Dick Kusleika와 Rob Bobey)이 조사했는데, 그 안에서 유익한 정보를 찾을 수 있을지도 모릅니다.하지만 대답은 '아니오'입니다.

대체로, 꽤 걱정스러운 답변이 있는 좋은 질문입니다.

범위 개체가 현재 유효하지 않은지 테스트하려면 다음 기능을 사용합니다.

Public Function InvalidRangeReference(r As Range) As Boolean    
    On Error Resume Next
    If r.Count = 0 Then
        InvalidRangeReference = Err
    End If    
End Function

언급URL : https://stackoverflow.com/questions/12127311/vba-what-happens-to-range-objects-if-user-deletes-cells

반응형