2009-08-05 5 views
0

Excel에서 명명 된 범위의 범위에 대해 약간 혼란 스럽습니다. 두 가지 버전의 Excel 통합 문서가 있습니다. 경우에 따라 사용자는 이전 버전의 통합 문서에서 더 새로운 버전으로 데이터를 복사해야합니다. 대부분의 셀 계산에는 사용자 지정 VBA 함수가 사용됩니다. 각 기능은 시트에서 4 ~ 12 개의 명명 된 범위를 찾습니다. 이것은 잘 작동하는 것처럼 보였습니다 ... 그러나 최근에 두 파일 버전이 열리면 모든 명명 된 범위에 대한 VBA 참조가 열린 첫 번째 파일의 값만 반환한다는 것을 알았습니다 (따라서 새 버전의 양식이 처음 열리면 이전 버전은 일부 데이터가 새 버전에서 나온 것처럼 작동합니다!). 두 번째 파일의 명명 된 범위는 두 파일이 모두 열려있는 한 VBA 코드에서 두 번째 파일에 의해 무시됩니다. 먼저 열린 통합 문서를 닫으면 두 번째 문서가 올바르게 계산됩니다. 통합 문서 사이에 중복 된 명명 된 범위로 인해 사용자 지정 함수가 혼동을 느낀다

가 나는 부분 수정을 발견하는 대신이 일을 :

Blah = Range("valueXYZ").Value 

내가이 대신 수행

Blah = ThisWorkbook.Names("namedCellXYZ").RefersToRange.Value 

이 있지만 통합 문서의 최신 버전에, 잘 작동합니다. 통합 문서의 이전 버전에서 VBA 코드를 업데이트 할 수 없습니다. 즉, 새 버전이 이미 열려 있어도 고객이 이전 버전을 열면 (두 버전 모두 열려 있지만 이전 버전은 두 번째로 열림) 이전 버전은 새 버전에서 값과 명명 된 범위를 가져 오게됩니다. 잘못된 숫자와 범위를보고합니다. 이것은 나쁘다. 이전 시트가 새 시트에서 명명 된 범위에 액세스하지 못하도록하는 좋은 방법이 필요하지만 새 시트 만 수정할 수 있습니다. 내가 생각할 수있는 유일한 것은 새로운 버전에서 모든 명명 된 범위의 이름을 바꾸고 많은 VBA 코드를 업데이트하는 것입니다. 오류 및 과도한 작업 같은 경향이있는 것입니다.

제안 사항? 예를 들어 두 번째 파일을 열 때 적어도 사용자에게 경고를 표시 할 수 있습니까? 또는 VBA를 사용하여 명명 된 범위의 범위를 제한 할 수 있습니까? 다른 아이디어?

답변

1

"ThisWorkbook"코드 창에서 WorkbookOpen Event을 처리해보십시오. 통합 문서의 새 버전이 열리면 열려있는 모든 통합 문서를 반복하고 목록에 이전 버전이 있는지 확인할 수 있습니다. 그렇다면 데이터가 최신 버전에서 읽혀지기 때문에 이전 버전의 스프레드 시트 값이 올바르지 않을 수 있음을 사용자에게 경고합니다.

+0

좋습니다. 그러나이 이벤트 처리기를 실행하는 데 문제가 있습니다. –

+0

나는 그것을 작동시켰다 - 나는 이벤트가 작동하기 시작하도록 Excel을 재시작해야했다. 감사!!흥미로운 측면에서, 내가 알 수있는 한, 새로운 버전은 이미 열려있는 통합 문서를 확인할 필요가 없습니다. 첫 번째 통합 문서가 우선권을가집니다. 따라서 이전 버전이 먼저 열리면 명명 된 범위가 작동합니다 올바르게 작동하도록 새로운 버전이 올바르게 설계되었습니다 (따라서 이전 버전이 두 번째로 열리는 경우에만 문제가됩니다). 따라서 가장 많이 업데이트 된 통합 문서를 확인하는 기능 만 설정하면됩니다. –

+0

예, 맞습니다. 사용자가 Old old, New를 열면 Old는 Old (처음 열렸 음)를 참조하고 New는 New (정규화 된 참조)를 참조하므로 아무런 문제가 없습니다. 사용자가 New, Old를 열면 사용자에게 경고해야합니다. 더 멀리 가고 싶다면 경고를 표시 한 다음 사용자에게 문제를 해결하기 위해 New를 닫았다가 다시 열 수 있는지 물어보십시오. New에 대한 저장되지 않은 변경 사항이있는 경우 사용자는 저장, 저장 또는 취소 중 하나를 수행해야합니다. – devuxer

0

[편집]

당신이 열려있는 모든 통합 문서에서 중복 명명 된 범위가있는 경우이 하위 당신을 말할 것이다. DanThMan 말했듯이, 당신은 ThisWorkbook 오브젝트 모듈에서 참조 할 수 있습니다 :

Sub CheckRangeDups() 
    Dim wb As Workbook 
    Dim nm As Name 
    Dim count As Integer, i As Integer 
    Dim arrNm() As String 
    Dim dup As Boolean 
    Dim rngChk As Range 

    ReDim arrNm(0) 
    'cycle through workbooks' 
    For Each wb In Workbooks 
     'cycle through names in workbook' 
     For Each nm In wb.Names 
      'check if name refers to a range' 
      On Error Resume Next 
      Set rngChk = Nothing 
      Set rngChk = nm.RefersToRange 
      On Error GoTo 0 
      If Not rngChk Is Nothing Then 
       dup = False 
       'check if name in array of names' 
       For i = 0 To UBound(arrNm) 
        If nm.Name = arrNm(i) Then 
         MsgBox "Named range " & nm.Name & " duplicated." 
         dup = True 
         Exit For 
        End If 
       Next i 
       'if not then add it' 
       If Not dup Then 
        arrNm(count) = nm.Name 
        count = count + 1 
        ReDim Preserve arrNm(count) 
       End If 
      End If 
     Next nm 
    Next wb 
End Sub 

나는 완전히 범위로 참조가 문제를 해결할 자격, 바로 당신을 이해한다면 [/ 편집]

. 예 : 두 파일이 file1 및 file2라는 이름으로 열리면 두 파일의 시트 1에 "arange"라는 셀의 이름을 지정합니다. file1에서 셀에 "file1"을 입력하고 file2에 "file2"를 입력합니다. 이제이 실행

Sub whichRange() 
    Dim f1 As Workbook, f2 As Workbook 
    Set f1 = Workbooks("file1.xls") 
    Set f2 = Workbooks("file2.xls") 
    Dim s1 As Worksheet, s2 As Worksheet 
    Set s1 = f1.Worksheets(1) 
    Set s2 = f2.Worksheets(1) 

    Dim r1 As Range, r2 As Range 
    Set r1 = s1.Range("arange") 
    Set r2 = s2.Range("arange") 

    Debug.Print "WB: "; f1.Name; " cell: "; r1.Name; " contents: "; r1 
    Debug.Print "WB: "; f2.Name; " cell: "; r2.Name; " contents: "; r2 
End Sub 

완전 자격은 엑셀 당신이 언급되는 알 수 있습니다.

+1

모든 이름을 완벽하게 한정하는 것은 모든 향후 버전에서 좋은 아이디어가 될 것입니다.하지만 OP를 올바르게 이해하고 있다면 이미 변경할 수없는 매크로가있는 기존 버전이 이미 있습니다 (이미 사용자의 컴퓨터에 있습니다). – devuxer

+0

새로운 통합 문서 버전에서 본질적으로 동일한 작업을 수행하는 방법에 대해 이미 설명했습니다. 위에 붙여 넣은 두 번째 코드 예제를 참조하십시오. - 코드 샘플에는 명명 된 범위가있는 워크 시트를 아는 데 의존하지 않는다는 보너스가 추가되었습니다. DanThMan이 맞습니다 - 소급하여 저에게 일하거나 적어도 사용자에게 문제에 대해 경고해야합니다. –

+0

"thisWorkbook.names의 각 nm에 대해"에 대한 for 루프의 값 "ThisWorkbook.Names ("nameXYZ "). RefersToRange.Value"를 사용하여 이미 재정의 된 명명 된 범위를 "if Range ("nameXYZ ")로 확인할 수 있습니다. 그리고 다시 한번이 작업을 소급 적용 할 수는 없으며, 마지막으로 기존 게시물의 두 번째 코드 샘플이 최신 버전의 문제를 우회한다는 점을 다시 한 번 강조합니다. 따라서 중복을 감지 할 필요가 없습니다. 즉, 귀하의 노력에 감사 드리지만 올바른 문제를 해결하지는 못합니다. –

관련 문제