- 최초 작성일: 2000-12-12
- 최종 수정일: 2026-09-30
- 조회수: 9 회
- 작성자: 권현욱 (엑셀러)
- 강의 제목: 몇 가지 질문들
들어가기 전에
오래 전 엑셀 파일로 진행하던 강의를 웹 글로 복원한 것이라, "버튼을 눌러보세요"처럼 엑셀에서 직접 조작하라는 표현이 남아 있을 수 있습니다. 결과는 본문의 그림이나 표로 확인하실 수 있으며, 현재와 맞지 않는 내용은 보완하되 전반적인 스타일은 당시의 갬성(?)을 유지했습니다.
질문이 많이 멀려있어서 이번 강좌에서는 답변을 겸해서 진행을 해야할까 봅니다. 질문에 대해 제때 답변을 못드리면 꼭 무슨 빚을 진 것 처럼 마음 한켠이 영 찜찜합니다. 따라서 '메일 보낸 지가 언젠데 아직 답을 안주는 것이야?' 하고 짜증내거나 항의하는 분이 없으시기를… ^^;
몇 가지 질문들
핵심 요약: Union과 변수 선언
Union으로 떨어진 범위를 하나로 묶어 순환할 수 있고, 개체 변수는 Range 같은 구체적인 형식으로 선언하며, 셀 주소는 String 변수에 담습니다.
- Union: 연속되지 않은 여러 범위를 하나의 범위처럼 다룹니다.
- 변수 선언: Object보다 Range, Worksheet처럼 구체적인 형식이 빠르고 바람직합니다.
- Address: 셀 주소는 Range가 아니라 String 형식입니다.
질문 1: 양수는 양수끼리, 음수는 음수끼리 더하기
안녕하십니까?
선생님의 강의를 보고 엑셀에 많은 관심이 생겼습니다.
감사를 드리며 질문 하나 올립니다.
(문)여러 범위를 지정하여 같은 범위 안에서 양수는 양수끼리, 음수는 음수끼리
더하고 싶은데 방법이 없는지요?
질문에 나온 것과 같이 서로 떨어져 있는 두 범위(왼쪽 3열, 오른쪽 2열)에 숫자가 들어 있다고 가정합니다(소수점 이하는 둘째 자리까지만 표시했습니다).
| 열1 | 열2 | 열3 | 열4 | 열5 |
|---|---|---|---|---|
| 90.40 | 87.35 | 31.90 | 32.32 | 21.69 |
| 41.05 | 85.32 | 84.94 | 82.61 | -15.00 |
| 12.14 | -50.00 | 33.64 | 80.26 | 3.02 |
| 35.01 | 38.39 | -47.00 | -35.00 | 98.89 |
| -100.00 | 11.95 | 10.86 | 96.48 | 51.57 |
| 89.29 | 7.21 | -87.00 | 8.84 | -103.00 |
| 59.76 | 96.30 | 62.87 | 53.65 | 1.87 |
버튼을 눌러 보세요. 그러면 위에 있는 두 점선 부분에 대해 원하시는 계산을 할 것입니다.
이렇게 해서 나온 결과값이 맞나 안맞나 손바닥만한 전자계산기를 두드려가며 검산하는 분이 저쪽에 몇 분 보이는군요. ^^ 아직도 Excel을 사용하시는 분 중에 Excel로 작업한 계산 결과를 못 믿어서(사실은 못 믿는다는 것보다는 제대로 Excel을 다루지 못한다는 표현이 맞겠지만…) 이것을 쬐그만 계산기로 일일이 재확인하는 분이 많이 계십니다. 비극적인 일이지요. ^^; Excel 자체가 고성능 전자계산기, 그것도 수도 없이 많은 고성능 전자계산기의 복합체인 것을…
사실 Exceller도 전자계산기로 계산을 할 때가 가끔 있지만 그것은 아주 간단한 연산을 할 때, 화면상에서 왔다갔다하는 것이 번거롭게 여겨질 때 그러는 것이지 Excel의 결과를 못 믿어서 그런 것은 아닙니다. 어쨌거나 코드를 보도록 하지요.
Sub MyCalculation()
Dim rngCell As Range
Dim dblPlus As Double
Dim dblMinus As Double
Dim Msg As String
For Each rngCell In Union(Range("MyRange1"), Range("MyRange2"))
'//Range 오브젝트에 접근하는 데에는 몇 가지 방법이 있습니다. 가장 빈번하게 사용되는
'//것이 Range Method와 Cells Method일 것입니다. 그런데 위에서 보니까 Union이라는
'//새로운 방법이 하나 나왔군요. 이것은 연속적이지 않은 여러 범위를 지정할 때
'//사용하는 방법입니다.
If rngCell.Value >= 0 Then
dblPlus = dblPlus + rngCell.Value
ElseIf rngCell.Value < 0 Then
dblMinus = dblMinus + rngCell.Value
End If
'//그 다음은 아주 간단하지요? 각 셀을 돌면서 셀 값이 양수이면 dblPlus 변수에,
'//셀의 값이 음수이면 dblMinus 변수에 차곡차곡 담아둡니다.
Next rngCell
Msg = "선택하신 범위 내에서" & vbCr & vbCr
Msg = Msg & "양수의 합계는 " & Format(dblPlus, "#,##0") & " 이고," & vbCr
Msg = Msg & "음수의 합계는 " & Format(dblMinus, "#,##0") & " 입니다"
MsgBox Msg, vbExclamation, "계산 완료//Exceller"
'//순환이 끝났으면 변수에 저장된 값을 화면에 뿌려줍니다.
End Sub
질문 2: Object 변수와 Range 변수의 차이
변수를 선언해서 쓰는데 Object 변수는 이해하기가 어렵다는 질문입니다. Dim rngCell As Range를 Dim rngCell As Object로 바꿔도, Dim recRectangle As Rectangle을 Dim recRectangle As Object로 바꿔도 실행이 되는데 어떤 차이가 있는지 궁금하다고 하셨습니다.
변수의 타입과 선언방법만 잘 구분할 수 있어도 초보는 면할 수 있습니다. Integer, Long, Currency, Date 등과 같이 대부분의 변수는 선언을 할 때,
Dim I As Integer
Dim lngRow As Long
Dim curMoney As Currency
I=10
lngRow=ActiveCell.Row
curMoney=1000000
이런 식으로 사용하는데 비해 오브젝트 변수는
Set rngCell = Range("MyRange")
Set ovlMyOval = ActiveSheet.Ovals("MyOval1")
이런 식으로 변수에 값을 지정할 때 Set을 사용합니다.
Object 변수를 선언할 때
Dim rngCell As Object
Dim shtSheet As Object
이렇게 선언하는 것보다는 아래와 같이 선언하는 것이 더 효율적이고 바람직합니다.
Dim rngCell As Range
Dim shtSheet As Worksheet
기술적인(?) 용어로 설명을 하자면, 위의 것 RunTime으로 오브젝트에 접근하는 오브젝트에 접근하는 Generic(일반적인)한 방법이고, 아래의 것은 DesignTime 으로 오브젝트에 접근하는 Specific한 방법입니다. 따라서 아래의 방법이 더 수행속도가 빠르고 효율적이지요. 직접 확인해 보아야 직성이 풀리시지요? ^^
Method1/Method2 버튼을 누르세요.
Sub Method1()
Dim rngCell As Object
Dim i As Long
Dim sngStart As Single
sngStart = Timer
For i = 1 To 10000
Set rngCell = Range("A1")
rngCell.Value = i
Next i
Range("Test") = Timer - sngStart
End Sub
Sub Method2()
Dim rngCell As Range
Dim i As Long
Dim sngStart As Single
sngStart = Timer
For i = 1 To 10000
Set rngCell = Range("A1")
rngCell.Value = i
Next i
Range("Test2") = Timer - sngStart
End Sub
Method1은 Object로, Method2는 Range로 선언한 경우입니다. 실행해 보면 경과시간이 각각 약 2.58초, 2.48초로 나타나 약 0.1초의 차이를 보였습니다(당시 컴퓨터 기준).
아주 간단한 작업임에도 불구하고 수행속도에서 차이를 보이지요? 코드는 간단하니까 모듈시트를 살펴보시기 바랍니다.
Object로 선언하는 방식은 실행 시점에야 개체를 확인하는 후기 바인딩, Range·Worksheet처럼 구체적인 형식으로 선언하는 방식은 코드를 작성하는 시점에 확인하는 조기 바인딩입니다. 조기 바인딩은 속도가 빠를 뿐 아니라 코드 작성 중 자동 완성(IntelliSense)의 도움을 받을 수 있어 실수를 줄여 줍니다. 요즘 컴퓨터에서는 속도 차이가 크게 체감되지 않는 경우가 많지만 이 장점은 그대로입니다.
질문 3: 개체변수가 설정되어 있지 않다는 오류
다음은 질문하신 분의 코드입니다.
Sub ActiA()
Dim a As Range
Selection.End(xlDown).Select
a=ActiveCell.Address
Range(Selection,Selection.End(xlDown)).Select
MsgBox "셀 주소는 " & a & "입니다"
End Sub
실행해 보니 런타임오류 91: 개체변수 또는 With 블록의 변수가 설정되어 있지 않습니다라는 메시지가 표시된다는 질문입니다. 또한 이렇게 얻은 주소 2개로 원하는 셀에 =SUM(변수1:변수2)와 같이 사용할 수 있는지도 물으셨습니다.
이것도 변수의 형태에서 착오를 일으키셨기 때문에 발생하는 오류입니다. 셀은 (Range) 오브젝트 이지만 셀의 주소는 문자열(String)입니다. 따라서
첫째 줄의 변수 선언을 아래와 같이 고쳐 주시면 됩니다.
Dim a As Range
Selection.End(xlDown).Select
a = ActiveCell.Address
이렇게 하신 부분을…
Dim a As String
Selection.End(xlDown).Select
a = ActiveCell.Address
이렇게 고치시면 되겠습니다.
그리고 두번째 질문하신 것도 물론 가능합니다.
같은 데이터에서 이번에는 두 개의 떨어진 범위(범위1, 범위2)를 Union 메서드로 묶어 선택하고 주소와 합계, 평균을 구해 봅니다.
이것도 Union Method를 사용해 보았습니다.
Sub ActiAByExceller()
Dim Msg As String
Dim strAddress As String
'//선택된 영역의 셀주소를 받기 위해 strAddress라는 문자열 변수를 선언해 주었습니다.
'//셀 주소는 Range 오브젝트 변수가 아니라 String 변수라는 사실에 주의하시기 바랍니다.
Union(Range("범위1"), Range("범위2")).Select
strAddress = Selection.Address
'//Union Method를 사용해서 불연속적인 영역을 선택하고 그 주소를 strAddress 변수에
'//담아둡니다.
Msg = "선택된 영역의 주소: " & strAddress & vbCr
Msg = Msg & " 합계: " & Format(Application.Sum(Selection), "#,###.00") & vbCr
Msg = Msg & " 평균: " & Format(Application.Average(Selection), "#,###.00")
MsgBox Msg, vbExclamation, "계산 완료//Exceller"
End Sub
마무리
다음 시간에… (기가 막히게 네 페이지를 정확히 맞추었지요? ^^)
정리 — 질문 답변 핵심
| 구분 | 사용한 코드 | 역할 |
|---|---|---|
| 불연속 범위 | Union(Range("MyRange1"), Range("MyRange2")) | 두 범위를 하나로 묶기 |
| 양수·음수 합산 | If rngCell.Value >= 0 Then | 조건별 누적 |
| 개체 변수 대입 | Set rngCell = Range("MyRange") | 개체에는 Set 사용 |
| 주소 저장 | Dim a As String | 셀 주소는 문자열 |
| 합계·평균 | Application.Sum(Selection) | 선택 영역 계산 |
자주 묻는 질문 (FAQ)
Q1. Union 메서드는 무엇인가요?
연속되지 않은 여러 범위를 하나의 Range 개체로 묶어 주는 메서드입니다.
Q2. Object 변수와 Range 변수는 어떤 차이가 있나요?
Object는 실행 시점에 개체를 확인하는 일반적인 방식이고, Range는 코드 작성 시점에 확인하는 구체적인 방식이라 더 빠르고 효율적입니다.
Q3. 런타임 오류 91은 왜 발생하나요?
셀 주소는 Range가 아니라 문자열인데 Range 변수에 대입하려 했기 때문에 개체변수가 설정되지 않았다는 오류가 납니다. String으로 선언하면 해결됩니다.
마치며
Union으로 불연속 범위를 묶고, 변수는 구체적인 형식으로 선언하면 코드가 더 빠르고 안전해집니다.