- 최초 작성일: 2000-11-14
- 최종 수정일: 2026-09-30
- 조회수: 9 회
- 작성자: 권현욱 (엑셀러)
- 강의 제목: 어제없는 오늘은 없습니다: 입력값 누적하기
들어가기 전에
오래 전 엑셀 파일로 진행하던 강의를 웹 글로 복원한 것이라, "버튼을 눌러보세요"처럼 엑셀에서 직접 조작하라는 표현이 남아 있을 수 있습니다. 결과는 본문의 그림이나 표로 확인하실 수 있으며, 현재와 맞지 않는 내용은 보완하되 전반적인 스타일은 당시의 갬성(?)을 유지했습니다.
지난 시간에 우리가 가진 나쁜 습관, 즉 자기가 가진 것을 절대로 남에게 주지 않으려는 습관에 대해 언급을 했더니 몇 분이 수긍의 메일을 보내주셨습니다. 그래서 힘이 납니다("너나 잘해라!" 하는 메일이라도 올까봐 내심 걱정을 했지요. ^^;).
기왕 말이 나왔으니 얘긴데… 누가 뭐래도 우리 민족은 참으로 우수한 민족입니다. 유네스코 세계문화유산으로 지정이 된 석굴암, 팔만대장경을 비롯하여 얼마나 많은 문화유적을 가지고 있습니까? 하지만 "내 것 절대 남 안주기" 전통(?)을 고수해 왔기 때문에 오늘의 국가적 위기를 맞게 되었다고 한다면 Exceller의 지나친 억측일까요?
고려청자와 이조백자의 예를 들어 볼까요? 세계 어디에 내놔도 찬사를 받는 고려청자와 이조백자. 비록 우리가 도자기 제조기술은 초창기에는 중국의 기술을 수입했지만 그것을 내 것으로 체화하는 과정을 통해서 고려 상감청자라는 독특한 수작을 만들어 냈습니다. 하지만 "내 것 절대 남 안주기" 전통 때문에 그 제작 기술은 전수되지 못했습니다. 상감기술을 가진 절세의 장인은 자신이 보유한 기술을 살아 생전에는 그 누구에게도 전수하지 않았습니다. 자신의 수제자에게도…
그러다가 숨이 넘어가기 직전에 다행히 정신을 수습해서 말이라도 할 기력을 차린다면 그 기술은 다음 세대에 전수가 되는 것이고, 그냥 꼴까닥하면 그 아까운 기술이 그대로 사장되고 마는 것입니다. 이래서는 곤란하다는 것입니다. "세계 최초로 금속활자를 발명한 후손"이라는 이름이 무색할 지경입니다.
지지난주 토요일에 COEX에서 세미나가 있어 참석했습니다. 참으로 많은 것을 생각케 하는 모임이었는데 그 중에서도 한 연사가 하신 이런 말이 가장 뇌리에 남습니다.
The world is the place of sharing experience!
(세상은 (자신의) 경험을 서로 나누는 곳이다!)
내가 가진 것을 남에게 주고, 마찬가지로 남의 경험을 내가 공유함으로써 시행착오를 최소화하고… 이것이 바로 System Energy, 즉 시너지 효과이지요.
어디선가, 누구에게선가 들은 이야긴데…
우리나라 어느 단체에 계신 분들이 싱가폴로 연수를 갔답니다. 싱가폴의 청렴결백한 공무원 세계를 보고 배우기 위한 목적에서 였다는 군요. 한국에서도 우수한 집단, 그 중에서도 선택된 사람들만 참석했으니만큼 교육분위기는 아주 좋아서, 안내를 하는 현지 공무원의 말을 하나라도 놓칠세라 열심히 보고, 듣고, 적고 했답니다.
우리나라 사람들의 아주 세련된 경청 태도에 오히려 감명을 받은 이 공무원은 침을 튀겨가며(이것은 Exceller의 과장! ^^) 더 열심히 설명을 했고, 그들은 귀국을 했지요. 여기까지는 아무런 문제가 없습니다. 아주 좋습니다.
그런데… 그 이듬해. 2차 연수대가 이 기관으로 왔고, 작년의 그 침 튀기며 열심히 설명한 그 공무원이 또 안내를 맡게 되었습니다. 하지만 2차 연수대가 와서 해대는 질문들은 거의 대부분 자신이 했던 그 답변들… 이 공무원은 조금 의아해 하면서도 나름대로 열심히 응대해 주었다는군요.
또 그 다음해, 3차 연수대가 다시 그 곳을 찾아왔는데 그들의 질문은 2년 전에 다녀간 사람들이 해대던 질문을 그대로 다시 하더랍니다. 4차, 5차 연수대가 다녀가도 사람들 얼굴만 바뀔 뿐 그들이 궁금해 하던 점은 매 한가지 였습니다.
그 싱가폴 공무원은 차마 화를 내지는 않았지만 나중에 이런 얘기를 했다는군요. "한국에서 온 사람들은 참으로 이상해. 자기가 보고 들은 것을 돌아가서 다른 사람에게 얘기를 해주면 다시 오지 않아도 될 것을… 어떻게 재작년에 왔던 사람들이나 작년에 왔던 사람들이나 매번 똑같은 것을 물어보다니…"
Exceller의 강좌를 보시는 분들은 부디 이런 愚를 범하지 않기를 바랍니다.
정신없이 떠들었군요. "Exceller 너나 잘해라" 하시는 분께는 죄송!!! 이것도 공짜 강좌 보시는 대가라고 생각하세요. 항의하지 마시고… ^___^
사설 접고, 강좌로 들어 갑니다. 더 떠들면 채널 딴대로 돌리실테니까…
"무슨 VBA 강좌 제목이 이래? Exceller가 또 맛이 갔나?" 강좌 제목만 보면 이렇게 생각하실 분이 있겠지요? ^___^ 아래의 질문들을 보세요.
질문 하나
엑셀에서 한 셀에 숫자를 계속 입력해도 그 숫자들이 자연스럽게 더해져서 셀에는 합계만 나오게 하는 방법이 있겠지요?
비슷한 질문 또 하나
회사에서 스케줄에 관련한 진행(progress) 시트를 만들고 있는데, 날짜와 금액을 입력하면 다음 시트의 해당 기간(1~10일, 11~20일, 21~30일) 칸에 금액이 자동으로 더해지도록 만들고 싶다는 질문입니다. 예를 들어 9월 9일에 20원이 들어오고 9월 7일에 50원이 더 들어오면 9월의 1~10일 칸에 70원이 되게 하려는 것입니다. 날짜를 비교해서 기간에 들어가게 하는 방법까지는 생각했는데 그 다음을 모르겠다고 하셨습니다.
어제없는 오늘은 없습니다: 입력값 누적하기
핵심 요약: 입력값 누적하기
옵션 버튼으로 기간을 고르고 입력한 값을 해당 셀에 더하며, 모든 입력값은 프로시저 바깥에 선언한 동적 배열에 저장해 합계를 구합니다.
- 1단계: 기간별 셀과 합계 셀에 이름(First, Second, Third, Total)을 정의합니다.
- 2단계: 입력 버튼에서 IsNumeric으로 확인하고 선택한 기간의 셀에 값을 더합니다.
- 3단계: ReDim Preserve로 입력값을 배열에 쌓고 합계를 계산합니다.
Step 1: 이런 방식은 권하지 않습니다
이러한 종류의 질문들도 심심찮게 들어옵니다. 무슨 작업을 하시려는지 대충 짐작은 갑니다만 절대로(!) 이렇게는 하지 마시기 바랍니다. 즉 누계 자료가 필요하다면 하루하루의 데이터를 누적시켜 나가면 되는 것이지 어느 셀에다 값을 입력하고 같은 셀에 또다른 값을 입력하면 이전의 값과 자동으로 합산이 되도록 하는 식으로는 작업을 하지 마시라는 것입니다.
물론 그것이 불가능 한 것은 아닙니다. 충분히 가능하다는 것을 오늘 보여드리기 위해 예제를 하나 만들어 보겠지만 실제 업무에서는 이렇게 사용하지 마시고 '이렇게도 쓸 수 있구나!' 하는 것만 이해하시기 바랍니다.
좋은 질문을 주셔서 이 기회에 동적 배열변수의 사용방법과 외부 변수선언에 대해 이 기회에 확실히 이해하고 넘어가도록 하지요.
버튼을 누르면 유저폼이 하나 나타날 것입니다. 값을 입력하고 기간을 지정한 다음, "입력" 버튼을 클릭하면 해당 기간란에 값이 입력됩니다. 몇 개의 값을 입력하신 다음에 "입력 내용 보기" 버튼을 클릭하면 그동안 입력했던 값들이 표시가 됩니다.
예제 시트의 결과는 아래와 같은 형태입니다.
| 1~10일 | 11~20일 | 21~30일 | 합계 |
|---|---|---|---|
| 40 | 20 | 30 | 100 |
Step 2: 셀 이름 정의와 유저폼 만들기
(1) 먼저 각 셀에 이름을 지정하였습니다. First, Second, Third, Total이라고 이름을 지었으니 확인해 보시고…
(2) 아래와 같은 UserForm을 하나 만듭니다.
Step 3: 입력 버튼 코드 작성하기
(3) "입력" 버튼을 더블클릭하고 아래와 같은 코드를 작성합니다.
Dim intAllValues() As Integer
Dim i As Integer
'//프로시저 외부에 변수를 선언해 주었습니다. 이 intAllValues 변수는 사용자가 입력한 값들을
'//저장해 두기 위한 것입니다. 그러면 왜 프로시저 내부가 아닌 외부에 선언해 주었을까요?
'//이렇게 해 주면 다른 프로시저에서도 별도의 선언없이 이 변수를 사용할 수가 있습니다.
'//그리고 사용자가 몇 개의 숫자를 입력할 지 알 수 없으므로 배열의 크기를 미리 지정해 주지
'//않고 동적 배열변수로 지정을 하였습니다.
Private Sub btnContinue_Click()
Dim intTemp As Integer
Dim intSum As Integer
Dim intCount As Integer
'//필요한 변수들을 선언해 주고…
If Not IsNumeric(txtInput) Then
MsgBox "반드시 숫자값을 입력하세요", , "입력 오류//Exceller"
With txtInput
.SetFocus
.SelStart = 0
.SelLength = Len(.Text)
End With
Exit Sub
End If
'//[입력할 값]란에 숫자값이 아닌 다른 형태의 값이 입력되면 에러 메시지를 표시하고
'//다시 입력할 것을 사용자에게 알립니다.
Select Case True
'//옵션 버튼 중에서 어떤 것이 눌려 졌는지 파악해서 입력받은 값을 해당 셀로 옮겨적는
'//과정입니다. 이 때 지금까지 입력된 내용을 동적 배열변수에 기억시키는 과정을 눈여겨
'//보시기 바랍니다.
'//Preserve 명령어로 배열의 크기를 보존시켜 놓고, 입력된 값을 배열변수 intAllValues(I)에
'//담습니다.
Case optFirst
intTemp = Val(txtInput)
Range("First") = Range("First").Value + intTemp
ReDim Preserve intAllValues(i)
intAllValues(i) = intTemp
Case optSecond
intTemp = Val(txtInput)
Range("Second") = Range("Second").Value + intTemp
ReDim Preserve intAllValues(i)
intAllValues(i) = intTemp
Case optThird
intTemp = Val(txtInput)
Range("Third") = Range("Third").Value + intTemp
ReDim Preserve intAllValues(i)
intAllValues(i) = intTemp
Case Else
MsgBox "기간을 선택하세요", , "기간 선택//Exceller"
Exit Sub
End Select
For intCount = LBound(intAllValues) To UBound(intAllValues)
intSum = intSum + intAllValues(intCount)
'//동적 배열변수에 저장된 값들을 모두 더해서 합계를 계산해 둡니다.
Next intCount
i = i + 1
Range("Total") = intSum
With txtInput
.Text = ""
.SetFocus
End With
'//합계 부분에 계산된 결과값을 뿌려주고 포커스를 [입력할 값]란으로 옮깁니다.
End Sub
Private Sub UserForm_Initialize()
Range("First") = 0
Range("Second") = 0
Range("Third") = 0
Range("Total") = 0
i = 0
End Sub
Private Sub btnExit_Click()
Unload Me
End Sub
Step 4: 입력 내용 보기 버튼 코드 작성하기
(4) "입력 내용 보기" 버튼을 눌렀을 때 지금까지 입력된 값들을 모두 보여주기 위한 코드를 작성합니다.
Private Sub btnShowInputData_Click()
Dim i As Integer
Dim strTemp As String
Dim Msg As String
On Error Resume Next
For i = LBound(intAllValues) To UBound(intAllValues)
strTemp = strTemp & CStr(intAllValues(i)) & vbCr
'//배열의 모든 값을 strTemp 변수에 담습니다. 여기서 Lbound와 Ubound에 대해서는
'//도움말을 찾아보시기 바랍니다.
Next i
Msg = "지금까지 입력하신 것은" & vbCr & vbCr
Msg = Msg & strTemp & vbCr & "입니다"
MsgBox Msg, , "입력 내용 보기//Exceller"
End Sub
모듈 수준(프로시저 바깥)에서 선언한 변수는 유저폼이 메모리에서 제거되면 초기화되므로, 폼을 다시 열 때 필요한 값은 UserForm_Initialize 이벤트에서 함께 초기화해 주는 것이 안전합니다.
마무리
다시 한번 말씀드리지만, 어제가 있어야 오늘이 있고 오늘을 바탕으로 내일이 있는 것입니다. 하루하루의 데이터를 축적해 두면 누계는 저절로 구해지지요.
오늘은 여기까지…
정리 — 입력값 누적 핵심
| 구분 | 사용한 코드 | 역할 |
|---|---|---|
| 외부 변수 | Dim intAllValues() As Integer | 여러 프로시저에서 공유 |
| 입력 확인 | IsNumeric(txtInput) | 숫자인지 검사 |
| 기간 선택 | Select Case True / Case optFirst | 선택된 옵션 버튼 확인 |
| 배열 확장 | ReDim Preserve intAllValues(i) | 기존 값을 보존하며 추가 |
| 합계 | For intCount = LBound() To UBound() | 배열의 값을 모두 더하기 |
자주 묻는 질문 (FAQ)
Q1. 왜 변수를 프로시저 바깥에 선언하나요?
모듈 수준으로 선언하면 같은 모듈이나 폼의 다른 프로시저에서도 별도 선언 없이 그 변수를 사용할 수 있기 때문입니다.
Q2. 동적 배열은 언제 쓰나요?
입력할 값이 몇 개인지 알 수 없을 때 크기를 미리 정하지 않고 ReDim Preserve로 늘려 가며 사용합니다.
Q3. 같은 셀에 값을 계속 더하는 방식이 좋은가요?
권하지 않습니다. 누계가 필요하면 하루하루의 데이터를 쌓아 두고 합계를 구하는 방식이 바람직합니다.
마치며
어제가 있어야 오늘이 있듯이, 하루하루의 데이터를 쌓아 두면 누계는 저절로 구해집니다.