Skip Navigation Links.
Expand VBAVBA
엑셀프로그래밍이 필요한 이유
Expand ExcelExcel
Expand External LibraryExternal Library
Expand SolutionSolution
Expand EssayEssay

WorkBook_6|Name|Names.Add|Cells|Like "test*"|
|RefersTo|Delete|On Error GoTo|
|Int|Rnd|Find|InStr|Visible=xlVeryHidden|

Name오브젝트의 활용

엑셀의 일반적인 사용에 있어서도 범위에 이름을 지어서
사용하는것은 아주 편리한 기능이다
그러나 이름을 지어서 사용할때 이것도 하나의 자원이므로
관리를 잘하여야 한다
말썽을 피우는 화일을 좀 봐달라고 갖여 오면 처음 열어보는것이
이름 상자이고 수식의 입력상태이다
대개가 이름이 참조하는 잘못된 주소 혹은 잘못된 이름을 참조하는
수식이 대부분의 말썽을 피우는 부분이다



또한 프로그래밍에 있어서도 사용자가 얼떨결에 이름이 지어진
범위를 삭제를 해버리는 경우에도 에러가 나버려
더 이상 진행할수 없게 되고 욕을 퍼먹게 된다
이름은 프로그래밍의 자원이므로 잘 관리하고 조심하여 다루어야한다
그래서 프로그래밍상에서 에러가 나도 살펴보는 순서가 변수와
더불어 범위에 지어준 이름이 손상되지 않았나 살펴보게 된다
편리한점이 있지만 잘 보살펴주지 않으면 악의 원천이 된다
아래와 같이 Name오브젝트의 성질머리를 살펴보자


아래의 프로시져를 실행시켜보시면

Sub makeNames()
Dim iX As Integer
Dim rName As Range
Worksheets.Add
For iX = 1 To 100
    Set rName = Cells(iX,iX)
    ThisWorkbook.Names.Add "test_" & iX, rName
    rName = "XXX"
Next
End Sub

Name오브젝트도 집합체로 관리를 하게 된다
그래서 Name오브젝트를 관리하는 Names오브젝트가 있고

Names.Add [Name오브젝트에 붙여주고 싶은 이름],[Range오브젝트]

하게 되면 새로운 이름오브젝트가 생성되는것이다


앞에서 만든 100개의 Name오브젝트가 참조하는
범위를 몽땅 삭제 시켜보자
Name오브젝트를 삭제하는것이 아니고 Name오브젝트가
참조하는 범위를 삭제하는것이다..Range에 들어 있는 정보가
아니고 Range오브젝트자체를 삭제하는것이다

Sub destroyNames()
Dim nameX As Name
For Each nameX In ThisWorkbook.Names
    If nameX.Name Like "test_*" Then
        Range(nameX.RefersTo).Delete
    End If
Next
End Sub

Names집합체오브젝트는 WorkBook오브젝트가 관리한다
그래서 ThisWorkBook.Names 로서 통합문서에 있는 모든 Name오브젝트를
순환하면서
Name오브젝트의 이름의 앞에 "test_" 로 시작하는 이름이면
찾아서 해당 Name오브젝트가 참조하는 범위를
Name오브젝트의 RefersTo속성으로 얻어낸다
여기서 얻어낸 값은 Range오브젝트의 주소를 말하고 ,문자열정보를 얻는것이다
이것을 Range("주소")로 접근하여 Delete메소드로 삭제해 버린것이다
이때 이름정의상자에는 그림과 같이 쓰레기가 남게 되는것이다



이런 쓰레기 주소를 참조하는 VBA의 구문이다
엑셀시트상에서의 수식,챠트,피봇테이블등은 모두 에러의 원흉이 되는것이다


=Sheet6!#REF!
와 같은 쓰레기 정보는 [Name오브젝트] 제거 하여야 한다
VBA를 모른다면 하나하나..이름정의상자에서 삭제를 하여야 할것이다
앞의 쌤플에서 100개의 이름을 지었으니 100번을 마우스를 딸그락거려야한다
한꺼번에 쓰레기 이름들을 지워버리도록 하자

Sub deleteBadName()
Dim nameX As Name
For Each nameX In ThisWorkbook.Names
    If nameX.RefersTo Like "*REF*" Then
        nameX.Delete
    End If
Next
End Sub

100번의 마우스딸그락작업을 100번의 순환으로 처리된다
순환의 시작과 순환의 종료두개만 알면 될것을
힘들어 한다
아무튼 깨끗하게 삭제 된것을 볼수 있을것이다
앞에서 Name오브젝트가 참조하는 Range오브젝트를 삭제하는것과
Name오브젝트를 삭제하는것과 틀리다는 점을 잘 이해하시기 바란다


프로그래밍을 잘한다고 하는것은
분석력과 관찰력과 기획력을 기본으로 한다
물론 시키는 하드코드만 계속 반복하여 작업하는 것을 말하는것이 아니다
엑셀프로그래밍은 다른 프로그래밍과는 틀린것이다
일을 하면서 일의 관찰,분석,기획을 하다 보니까..
남보다 빠르게 결과를 얻어내기 위하여 엑셀프로그래밍을 하는것이다
아무튼..
Name오브젝트도 귀중한 자원이라고 하였다
이것을 좀더 잘 관리하는 방법이 없을까
자원관리시트를 하나 자동으로 만들어서 보관하고 문제가 생기면
Name오브젝트를 복구 시켜보도록 한다


"Result"라는 이름을 지어서 어떤 분석의 결과를
분석작업후 전달하려고 할때

Range("Result")="분석의 결과"

사용자가 부주의로 삭제 하였다면 "Result"라는 이름의
범위는 접근 할수 없고 에러가 나게 된다
그렇다면 이것 하나때문에 전체 소루션이 먹통이 되게 된다
엑셀프로그래밍을 하는 사람으로서
참으로 중요하게 다뤄야 할일이다


Manage Name Object And Use Hidden Sheet


방법은 여러가지가 있겠지만
소루션을 개발할때(Design Time)

  • 통합문서내의 모든 Name오브젝트를 순환하면서
  • Name오브젝트의 이름과 참조하는 셀의 주소를
  • 별도의 시트에 기록 해둔다
    For Each X In ThisWorkBook.Names
    ....
    Next
  • 그리고 시트는 사용자가 볼수 없게 감춘다
    Worksheets("기록시트").Visible=xlVeryHidden


사용자가 사용을 할때(Run Time)

  • 어떤 이름이 지어진 범위에 접근하여
  • Range("Name").Value="결과값"을 입력하기전에
  • 해당이름이 지어진 Name오브젝트의 상태가
  • 안전한지 점검한다
  • 만약 안전하다면 그대로 사용하면 되고
  • 만약 손상된 이름이라면 숨겨진 자원등록시트에서
  • 해당이름의 Name오브젝트의 정보를 찾아서
  • 해당 Name오브젝트를 복구시킨후
  • 결과값을 전달하게 한다

숨겨진 워크시트에 값을 입력하거나,읽어낼수 있냐는
자주하는 질문의 답이 될수 있는 문제였고
또한 소루션을 위한 기본적으로 필요한 정보를
알뜰살뜰하게 잘 관리하는 하나의 방법으로서 숨겨진 시트의 역할을
잘 생각해 보시면 좋을것이다

프로그래밍이란 몇개 안되는 문법과 단어들을 사용하여
상황에 따라서 응용해 나가는것이다
몇개 안되는 내용을 숙달시키는것( Getting Used To~),
주어진 상황을 자꾸 풀어보면 내공이 쌓인다

통합문서레벨에서의 Name오브젝트와 워크시트레벨에서의 Name오브젝트

Names오브젝트는 WorkBook오브젝트의 하위 오브젝트이기도 하고
Worksheet오브젝트의 하위 오브젝트이기도 하다..
헷갈리게 이것이 뭔소리냐!! 싶을것이다
Sheet1,Sheet2,Sheet3라는 3장의 워크시트가 있는 통합문서에서
Sheet1의 Range("A1")에 이름을 "MyName"이라고 지어주었다고 했을때
ThisWokBook.Names.Count의 값은 1이다
현재 통합문서에 Name오브젝트는
1개라는 이야기다

이번에는 Sheet1을 복사하여 한장을 더 만들었을때
Sheet1 (2)이라는 이름으로 같은 시트가 만들어졌다
이때 다시
ThisWorkBook.Names.Count라고 하면 값은 2가 된다
시트가 새로 복사하여 만들어 지면서 Name오브젝트도 하나더 만들어진것이다
그렇다면 헷갈리지 않겠는가??
어떻게 구별하지??
각시트의 이름정의 상자에서 해당이름을 보면 아래의 그림과 같다



Worksheets("Sheet1").Names.Count의 값은 1이고
Worksheets("Sheet3").Names.Count의 값은 0이고
Worksheets("Sheet1(2)").Names.Count의 값은 1이고
ThisWorkBook.Names.Count의 값은 2인것이다

만약 Worksheets("Sheet1(2)")이 활성화된 상태에서
Range("MyName")=3이라고 하면
Sheet1(2)시트에 값이 들어가고
만약 Worksheets("Sheet3")나 Worksheets("Sheet1")을 활성화키기고
Range("MyName")=3이라고 하면 Sheet1의 해당셀에 값이 들어간다
이런 경우를 생각해서 항상
Worksheets("Sheet1").Range("MyName")=3이나
Worksheets("Sheet1(2)").Range("MyName")=3이라고 하거나
아예 이름을 시트별로 확실하게 구분되게 만들고 관리하여야 한다
복잡해 보이지만 원리를 알면 실수도 없고 관리도 편하다

엑셀소루션을 만들때 고물 박물관으로 만들던가
아니면 잘돌아가는 효율적인 도구로 만들던가..
이런 자원들을 잘 관리하는..즉
필요없는 것은 과감이 삭제하고,
중복되고 헷갈리는 이름은 배제하는 것에 습관이 되어있는가
아닌가에 따라서 틀려진다

자원관리를 잘 하기 위하여 위의 화일에서와 같이
자원관리정보시트를 하나씩은 소루션에 보관시키는
습관이 좋은것이다