그런데 함수에 대해서 만들때는 좋게 사용하지만 설명을 달아놓지 않으면 나중에는 전혀 사용하지 못합니다.
코드를 작성해 놓고 오랜만에 보면 어? 모르겠다 하는 경우가 한둘이 아니죠.
코드안에 주석으로 처리를 해두어도 되겠지만 엑셀 인터페이스에서 설명을 보는 방법을 알아보겠습니다.
기본적으로 사용자 함수는 작성할 수 있을 정도의 고수분들이 참고용으로 사용하는 기능이니 코드를 펼치겠습니다.
< 예시 코드 >
Function FilterOddEven(rng As Range, num AsInteger) As Variant
'이 Function 항목은 오늘 사용할 함수입니다.Dim cell As Range
Dim result() As Variant
Dim count AsIntegerDim i AsInteger' 입력 값 검사If num <> 1And num <> 2Then
FilterOddEven = CVErr(xlErrValue) ' 숫자가 1, 2가 아니면 #VALUE! 에러를 나타냄ExitFunctionEndIf'결과 배열 만들기ReDim result(1To rng.count)
count = 0' 홀수(1) 또는 짝수(2) 조건에 맞는 값만 필터링
i = 1ForEach cell In rng
IfNot IsEmpty(cell.Value) ThenIf (num = 1And i Mod2 <> 0) Or (num = 2And i Mod2 = 0) Then
count = count + 1
result(count) = cell.Value
EndIfEndIf
i = i + 1Next cell
' 결과 배열 크기조절If count > 0ThenReDimPreserve result(1To count)
Else
FilterOddEven = CVErr(xlErrNA) ' 결과가 없으면 #N/A 반환ExitFunctionEndIf' 배열 반환
FilterOddEven = result
EndFunction'---------------------------------------------'↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓' 오늘의 주제인 설명을 추가하는 코드입니다.Sub AddDescription()
Dim funcName AsStringDim funcDesc AsStringDim paramDesc1 AsStringDim paramDesc2 AsString' ① 함수 이름을 정확하게 입력합니다.
funcName = "FilterOddEven"' ② 함수의 전체 설명입니다.
funcDesc = "함수의 설명 - 주어진 범위에서 홀수/짝수 리스트를 필터합니다."' ③ 매개변수 설명 설정
paramDesc1 = "리스트를 필터할 범위"
paramDesc2 = "필터할 기준을 선택합니다. 1 = 홀수번째 값, 2 = 짝수번째 값"' ④ 함수 옵션 등록
Application.MacroOptions Macro:=funcName, _
Description:=funcDesc, _
Category:="사용자 정의 함수", _
ArgumentDescriptions:=Array(paramDesc1, paramDesc2)
EndSub
이번에 예시로 들기 위해 작성해둔 사용자 함수를 사용하겠습니다. 위에 있는
"Function FilterOddEven(rng As Range, num As Integer) As Variant"에서 "End Function"까지는 그냥 예시입니다.
함수의 이름은 FilterOddEven이고 범위 하나와 숫자 하나를 계수로 받아들입니다.
오늘 소개하고 싶은 것은 아래 있는 "Sub AddDescription()" 구문입니다.
위의 코드의 ①, ②, ③번 부분은 설명과 같습니다.
함수의 이름과 함수 자체의 설명, 매개변수의 설명을 입력합니다.
④ Application.MacroOptions
이 부분이 메크로(코드)의 옵션을 변경하는 적용 어플리케이션입니다.
funcName 변수의 함수를 찾아서 Description(설명)과 Categoty(분류)를 변경합니다.
그리고 ArgumentDescriptions(매개변수)를 배열 형식으로 입력합니다.
※ 주의하실 점은 "Sub AddDescription()" 는 그냥 둔다고 되는 것이 아니고 F5나 ▶ 버튼을 눌러서 실행시켜야 합니다.
엑셀이 함수를 찾을 수 있도록 모듈을 만들어서 작성하거나 함수 바로 아래 작성해두고 단독으로 실행하면 됩니다.
한번만 실행하면 해당 문서에서는 계속 작동합니다.
설명을 보는 방법도 알려드리겠습니다.
아래 움짤로 보면 이해 되실 것 같습니다.
설명 확인하는 방법
함수를 다 타이핑해서 입력한 후에 함수키를 누르면 "함수 인수" 매뉴가 나타나는데 여기서 볼 수 있습니다.
함수키
방큼 코드를 통해 입력 한 설명이 정상적으로 입력 되었음을 알 수 있습니다.
좀 더 복잡하게도 넣을 수 있으니 사용자 함수를 여러개 사용하시는 분은 이런식으로 설명을 추가해 보세요.
Sub SummarizeData()
Dim wsSource As Worksheet
Dim wsTarget As Worksheet
Dim criteriaCol AsLongDim valueCol AsLongDim startCell As Range
Dim lastRow AsLongDim dict AsObjectDim i AsLongDim category As Variant
Dim value As Variant
' ① 워크시 기본 정보 입력하기Set wsTarget = ThisWorkbook.Sheets("실행")
OnErrorResumeNextSet wsSource = ThisWorkbook.Sheets(wsTarget.Range("D3").value)
OnErrorGoTo0Set startCell = wsTarget.Range("F8")
' ② 먼저 입력 했던 값 선택하고 지우기
Worksheets("실행").Range(startCell.Address).CurrentRegion.Select
Selection.ClearContents
' 시트가 없으면 없다고 알려주고 끝내기If wsSource IsNothingThen
MsgBox "대상 시트가 존재하지 않습니다.", vbExclamation
ExitSubEndIf' ③ 입력한 열의 이름을 열 번호로 변경하기
criteriaCol = wsSource.Range(wsTarget.Range("D4").value & "1").Column
valueCol = wsSource.Range(wsTarget.Range("D5").value & "1").Column
' ④ "기준"이 되는 열에서 마지막 칸 입력하기
lastRow = wsSource.Cells(wsSource.Rows.Count, criteriaCol).End(xlUp).Row
' ⑤ 폴더를 초기화합니다. 참조에서 Microsoft Scripting Runtime를 활성화 시킵니다.Set dict = CreateObject("Scripting.Dictionary")
' ⑥ dict에 값이 없으면 폴더를 추가하고, 있으면 숫자의 값을 불러와서 더합니다.For i = 1To lastRow
category = Trim(wsSource.Cells(i, criteriaCol).value)
value = wsSource.Cells(i, valueCol).value
If category <> ""And IsNumeric(value) ThenIf dict.exists(category) Then
dict(category) = dict(category) + CDbl(value)
Else
dict.Add category, CDbl(value)
EndIfEndIfNext i
' ⑦ 결과 출력를 출력합니다. 참조가 추가되지 않으면 여기서 에러가 납니다.
i = 0ForEach category In dict.Keys
startCell.Offset(i, 0).value = category ' 분류
startCell.Offset(i, 1).value = dict(category) ' 합계
i = i + 1Next category
MsgBox "데이터를 정리하였습니다" & Chr(10) & "https://toast-story.tistory.com", vbInformation
EndSub
실행하는 방법
우선 실행하는 방법은 쉽습니다.
이 워크시트에 정리할 시트를 복사해서 붙여 넣고, 데이터만 있는 상태로 만듭니다.
그리고 시트이름 / 정리할 열 / 숫자가 들어있는 열을 각각 입력하고 옆에 회색의 실행버튼을 누릅니다.
※ 엑셀 인터페이스에서 쓰는 Find 함수와 VBA에서 사용하는 Find 매소드는 별개임을 알려드립니다.
① B 행에서 내용이 있는 마지막 셀 찾기
find를 사용할 껀데 먼저 코드를 보도록 하겠습니다.
Sub FindLastColumn()
Dim ws As Worksheet
Dim lastCell As Range
Set ws = ThisWorkbook.Sheets("Sheet5")
'find를 사용해서 마지막 값을 찾음Set lastCell = ws.Columns("B").Find(What:="*", _
After:=ws.Range("B1"), _
LookIn:=xlFormulas, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious)
IfNot lastCell IsNothingThen
MsgBox "B행의 마지막 데이터는 " & lastCell.Address & "에 있습니다."Else
MsgBox "B행에 데이터가 없습니다."EndIfEndSub
Find의 사용법은 위 코드를 보면 알 수 있고 각 매개변수에 대해서 설명하겠습니다.
What : 찾을 값으로 * 을 사용하였음으로 "모든 값"을 검색합니다.
After : 검색을 시작할 위치입니다. 여기서 부터라고 보면 됩니다.
LookIn : 검색할 기준입니다. 이 경우에는 수식으로 검색하는 것이 좋습니다. - xlFormulas : 수식을 기준으로 검색하는데 수식의 결과가 아닌, 수식 자체를 검색합니다. - xlValues : 값을 검색합니다. 이 경우에는 수식의 결과를 기준으로 검색합니다. - xlComments : 셀에 추가된 주석을 검색합니다. - xlCommentsThreaded : Threaded Comments라는 Office365 버전부터 추가된 새로운 주석을 검색합니다.
LookAt : (xlPart : 부분일치), (xlWhole : 전체일치)중 하나를 선택합니다.
SearchDirection : 검색하는 방향입니다. (xlNext : 앞에서 뒤로), (xlPrevious : 뒤에서 앞으로)
(MatchCase) : 검색할 때 대소문자를 구별할지 선택합니다. 디폴트는 False(구별 안함)입니다.
(MatchByte) : 더블 바이트 언어를 설치했을 때 사용합니다. - True : 더블 바이트 문자가 정확하게 더블 바이트와 일치할 경우만 검색 - False : 더블 바이트 문자가 싱글 바이트와 일치해도 검색함
(SearchFormat) : 검색 형식입니다.
즉 위의 코드는 ws.Columns("B") 로 범위를 제한해서,
B1부터 시작하여 해당 행(xlByRows)에서 뒤에서 앞으로(xlPrevious) 검색하여 처음 만나는 값의 위치를 찾습니다.
② 셀에서 마지막 범위 찾기
거의 같습니다. 똑같이 Find를 사용합니다.
Sub FindLastCell()
Dim ws As Worksheet
Dim lastCell As Range
Set ws = ThisWorkbook.Sheets("Sheet5")
' 마지막 데이터를 찾음Set lastCell = ws.Cells.Find(What:="*", _
After:=ws.Cells(1, 1), _
LookIn:=xlFormulas, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious)
IfNot lastCell IsNothingThen
MsgBox "워크시트의 마지막 데이터는 " & lastCell.Address & "에 있습니다."Else
MsgBox "워크시트에 데이터가 없습니다."EndIfEndSub
처음나온 코드에서 범위를 행으로 제한했던 ws.Columns("B")를 전체 대상의 ws.Cells로 변경한 것입니다.
SearchOrder는 "xlByRows"로 하면 가장 아래 값을 끝으로 "xlByColumns"를 하면 가장 오른쪽에 있는 셀을 선택합니다.
③ 처음부터 끝까지 선택하기
이제 응용편입니다.
끝의 셀을 선택한다면 처음셀로 찾을 수 있죠.
두 셀을 찾아서 전체 선택을 하는 코드입니다.
이 것 역시 간간히 쓰는데, 그때그때 작성하려니 실수가 많아 오늘 기회로 정리합니다.
Sub SelectallContentCell()
Dim ws As Worksheet
Dim firstCell As Range
Dim dataRange As Range
Set ws = ThisWorkbook.Sheets("Sheet5")
' 처음 셀 찾기Set firstCell = ws.Cells.Find(What:="*", _
After:=ws.Cells(1, 1), _
LookIn:=xlFormulas, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext)
' 마지막 셀 찾기Set lastCell = ws.Cells.Find(What:="*", _
After:=ws.Cells(1, 1), _
LookIn:=xlFormulas, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious)
Set dataRange = ws.Range(firstCell, lastCell)
dataRange.SelectIfNot firstCell IsNothingThen
MsgBox "선택된 범위는 " & dataRange.Address
Else
MsgBox "워크시트에 데이터가 없습니다."EndIfEndSub
엑셀에서는 그럴 때 사용하도록 Ctrl + 방향키(←,→,↑,↓)를 눌러서 끝에서 끝까지 이동할 수 있습니다.
무슨 게임하는 것 같아서 처음에는 익숙해지지 않았을 때는 마우스에 많이 의존하지만,
일단 적응되면 손에서 놓을 수가 없습니다.
1. 끝으로 이동하기
Ctrl + 방향키로 움직이기
VBA에서도 이 기능을 수행하는 명령어가 있습니다.
xlDown : 시작 위치에서 아래방향으로 데이터가 끝나는 셀로 바로 이동합니다.
xlUp : 시작 위치에서 위 방향으로 데이터가 끝나는 셀로 바로 이동합니다.
xltoRight : 시작 위치에서 오른쪽 방향으로 데이터가 끝나는 셀로 바로 이동합니다.
xltoLeft : 시작 위치에서 왼쪽 방향으로 데이터가 끝나는 셀로 바로 이동합니다.
시작 위치가 데이터가 없는 빈 셀일 경우에는 반대로 처음 데이터가 있는 셀로 이동합니다.
빈 셀인 경우 그 방향에 데이터가 하나도 없으면 끝까지 이동합니다.
사용하는 방법은 아래와 같습니다.
간단함으로 모두 묶어서 하나의 소스에 담아서 설명하겠습니다.
Sub MoveCell()
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("Sheet1")
ws.Range("B28").End(xlDown).Select'아래 방향으로
ws.Range("B28").End(xlUp).Select'위 방향으로
ws.Range("B28").End(xltoRight).Select'오른쪽 방향
ws.Range("B28").End(xltoLeft).Select'왼쪽 방향으로EndSub
보시면 이해될 것이라고 생각합니다.
셀 B28 에서 아래, 위, 오른쪽, 왼쪽으로 이동하는 소스입니다.
2. 끝까지 선택하기
위에 처럼 이동하는 것으로도 편리하지만 전체 선택하기라는 편리한 기능도 있습니다.
일반 엑셀 인터페이스에서는 Ctrl + Shift + 방향키(←,→,↑,↓) 입니다.
이 기능을 수행하는 코드도 설명 드리겠습니다.
범위 선택하기
소스로 따지면 약간 길어지는 합니다.
하지만 어렵지는 않으니 사용해 보면 바로 알 수 있을 것 같습니다.
Sub SelectRange()
Dim ws As Worksheet
Dim dataRange As Range
Set ws = ThisWorkbook.Sheets("Sheet1")
' A1부터 아래 방향으로 데이터가 있는 마지막 셀까지 범위 선택Set dataRange = ws.Range("A1", ws.Range("A1").End(xlDown))
dataRange.Select' A1부터 오른쪽 방향으로 데이터가 있는 마지막 셀까지 범위 선택Set dataRange = ws.Range("A1", ws.Range("A1").End(xlToRight))
dataRange.Select' A1에서 시작해 데이터가 있는 끝까지 범위를 설정Set dataRange = ws.Range("A1", ws.Range("A1").End(xlToRight).End(xlDown))
dataRange.SelectEndSub
굉장히 자주 사용하는 코드로 사용자가 입력해서 계속 길어지는 엑셀에 VBA를 적용할 때 사용하기도 합니다.