[엑셀 VBA #12] (배열응용) 특정 셀 영역 그대로 복사/ 


동하기




이번 엑셀 VBA 강의에서는 특정 셀을 기준으로 원하는 영역을 그대로 복사 및 이동하는 법에 대해서 배워보겠습니다.


예제를 받고 따라와 주세요.









이번 예제에는 두 가지 내용이 들어가 있습니다.


먼저 2차원 배열으로 구성된 셀 영역을 복사/이동하는 엑셀 VBA 코드를 알아보겠습니다.



좌측 상단 모서리에 있는 셀을 기준으로 값이 있는 모든 영역을 파란색 셀을 기준으로 이동하는 코드입니다.


예제 상에는 4x3의 배열으로 정해져 있지만, 사용자가 임의로 배열의 크기를 조정해도 문제 없도록 동적배열을 선언합니다.


Option Explicit            '변수가 선언 없이 사용되는걸 방지


Sub example_7()


Dim varArray                'varArray 배열 선언

Const n = 1                '기준으로할 셀의 행값 n 설정

Const m = 1                '기준으로할 셀의 열값 m 설정


Dim i As Integer

Dim p As Integer


i = Cells(n, m).End(2).Column - m + 1        '배열의 가로 크기 구하기

p = Cells(n, m).End(4).Row - n + 1            '배열의 세로 크기 구하기


ReDim varArray(1 To p, 1 To i)                '위에서 구한 배열의 크기로 배열 재선언


varArray = Cells(n, m).Resize(p, i)                '배열의 크기대로 셀(n,m)을 기준으로 배열 저장

Cells(5, 5).Resize(p, i) = varArray                '셀(5,5)에 저장된 배열 불러오기



End Sub



※Resize문과 End속성이 이해가 되지 않으면 관련 내용이 이전 엑셀 강의에 수록되어 있으니 확인하시고 진행하기 바랍니다.


위 코드를 실행시키면 아래와 같이 출력됩니다.





배열의 크기를 바꾸면 어떻게 출력될까요?





변화한 배열의 크기에 맞춰서 배열이 재선언되고, 크기에 맞춰서 정상적으로 복사됩니다.






이제 방금 배운 배열 응용법으로 간단한 회원관리 시스템을 만들어 보겠습니다.





위와 같은 회원관리 시스템에서 회원이 탈퇴했을 경우, 회원의 이름을 선택하고 매크로를 실행하면 아래 과거회원 시트로 해당된 회원 정보를 이동시키는 엑셀 VBA 매크로입니다.


option explicit

Sub example_7_2()


Dim varArray()                    '배열 varArray 선언

Dim n As Long                    '회원 이름이 포함된 셀의 행 n 선언

Dim m As Long                     '회원 이름이 포함된 셀의 열 m 선언

Dim i As Long                        '행의 길이(이동해야 할 셀의 양) 변수 선언



n = Selection.Row                '선택한 셀의 행을 n에 입력

m = Selection.Column                '선택한 셀의 열을 m에 입력


    If m <> 1 Then                    'm의 값이 1이 아닐 경우, 즉 선택한 셀이 이름이 포함된 열이 아닐경우

    MsgBox "회원 이름을 선택해야 합니다."           

    Exit Sub                            '종료

    Else

    End If

    

i = Sheet9.Cells(n, m).End(2).Column                    '이동해야 할 셀의 양 설정


ReDim varArray(1 To i)                            '이동해야 할 셀의 양에 맞춰서 배열 크기 조절




varArray = Sheet9.Cells(n, m).Resize(, i).Value                    '배열에 복사해야 할 값 지정

Sheet10.Cells(Rows.Count, 1).End(3)(2).Resize(, i) = varArray          '데이터가 들어가야 하는 위치를 찾고 배열을 입력 


Selection.EntireRow.Delete                    '과거로 이동한 인원 자료 현재회원에서 제거


End Sub



※만약 Resize 부분과 End(3)(2) 부분이 이해가 되지 않는다면 제가 이전에 올린 Resize와 End속성의 강의를 찾아보세요!





눈치가 빠르신 분은 눈치채셨을 수도 있습니다.


사실 위의 두 예제는 배열 선언이 필요 없습니다!


회원관리시스템 예제의 보라색 부분을 배열을 사용하지 않고 아래와 같이 바꿔도 똑같은 결과가 출력됩니다.


Sheet10.Cells(Rows.Count, 1).End(3)(2).Resize(, i) = Sheet9.Cells(n, m).Resize(, i).Value


그렇다면 굳이 배열을 사용하는 이유는 뭘까요?


먼저, 출력되는 값은 같지만, 두 가지 코드는 분명히 다릅니다.


첫 번째 코드는 배열을 선언 후, 복사해야 할 값을 배열(메모리)에 저장한 후 뿌려주었습니다.

두 번째 코드는 단순히 같은 값을 다른 셀에 똑같이 넣었습니다.


배열을 선언해서 메모리에 저장하게 되면, 셀의 값은 이제 배열의 값으로 복제가 되고, 복사하려는 셀이 사라지거나 수정이 되어도 그 값은 그대로 남아있게 됩니다.


반면에, 두 번째 코드처럼 메모리에 값을 저장하는 과정을 건너뛰게 되면 복사하고자 하는 셀의 값이 사라지거나 수정되는 경우 출력에 오류가 생기게 됩니다.


간단하게 예를 들어보겠습니다.


회원관리 예제의 초록색으로 표시된 부분을 보라색 코드 사이에 넣어보겠습니다.


varArray = Sheet9.Cells(n, m).Resize(, i).Value                

Selection.EntireRow.Delete 

Sheet10.Cells(Rows.Count, 1).End(3)(2).Resize(, i) = varArray  


과거 학생 시트로 값이 입력되기 전에 복사하고자 하는 값들을 엑셀 시트에서 삭제했음에도 불구하고, 출력되는 결과는 이전과 동일합니다. 이미 메모리에 배열이 저장되었기 때문에, 엑셀 시트상의 값이 사라진다고 해도 메모리에 저장된 값에는 변동이 없기 때문입니다.


또한 메모리를 사용하는 작업이기 때문에 대량 작업의 경우 작업의 속도가 현저하게 빨라집니다.


따라서 배열을 선언하는 습관을 갖고 있는 것은 정말 중요합니다.









Posted by Simon K
:

[엑셀 VBA #11] (배열#1) 배열 이해하기. 배열의 차원과 

정적, 동적배열




이번 시간부터는 엑셀 VBA를 배울 때 가장 까다로운 개념 중 하나인 배열에 대해 알아보겠습니다.


한 포스팅에 담기에는 벅찰 것 같아서 나눠서 진행하도록 하겠습니다.




배열은 확실히 까다로운 개념이 맞습니다.


하지만 정말 중요한 개념이고 많이 쓰이기 때문에 꼭 이해해야 하는 개념이기도 합니다.


엑셀 VBA의 배열은 수학적 개념의 배열과 동일합니다.


변수 i에 한 가지의 수, 문자를 저장할 수 있다면, 배열 i에는 한꺼번에 여러 개의 수와 문자를 저장할 수 있습니다.


하지만 안타깝게도 배열이 이렇게 단순하지만은 않습니다...


엑셀 VBA는 배열을 1차원부터 60차원까지 허용하고 있습니다.


이는 무엇을 의미하고 있는 것일까요?





N차 배열의 의미


1. 1차 배열


1차 배열은 직선형의 단순한 배열을 의미합니다.



배열 속에 있는 각각 개체들이 앞, 뒤 순서로만 배치되어 있습니다.


엑셀의 한 에 위치한 값들의 배열이라고 생각할 수 있습니다.





2. 2차 배열


2차 배열은 직사각형(정사각형) 의 배열을 의미합니다.



배열 속의 개체들이 상하좌우로 나뉘어서 배치되어 있습니다.


엑셀의 한 시트 안에 있는 값들의 배열이라고 생각할 수 있습니다. 배열이 (i, p)와 같은 좌표로 구성이 됩니다.




3. 3차 배열


3차 배열은 직육면체(정육면체) 의 배열을 의미합니다.




배열 속의 개체들이 상하좌우 및 위 아래로 배치되어 있습니다.


여러 시트(sheet1, sheet2, sheet3.....)로 구성된 엑셀 파일에 있는 값들의 배열이라고 생각할 수 있습니다. 배열이 (i, p, o)와 같은 좌표로 구성됩니다.





4. 4차 이상 배열


사실 4차 이상 배열은 잘 사용되지 않습니다. 엑셀의 범위를 넘어가기 때문이지요..


4차 배열의 경우 여러 엑셀 파일을 담고있는 폴더, 5차 배열의 경우 여러 폴더를 담고있는 하드드라이브, 6차 배열의 경우 여러 하드드라이브를 담고있는 컴퓨터, 7차 배열의 경우 여러 컴퓨터들을 담고있는 PC방에 비유할 수 있겠네요.


계속 차원을 넓혀가면 우주까지 다다를 수 있습니다. 


억지스런 비유이긴 하지만, 엑셀 VBA에 이런 고차원적인 요소는 필요 없기에,일반적으로 3차 배열까지만 사용되고 있습니다.


물론 4, 5, 6차 배열도 분명 사용할 수 있고 사용되고 있습니다. 하지만 일반적인 엑셀에는 그 만큼 넓은 배열이 필요하지 않습니다. 







자, 이해가 되시나요? 아직 좀 아리송할겁니다.


더 간단하게 비유해보겠습니다.


배열을 엑셀에 비유했을 때, 엑셀이라는 것이 점점 진화를 한다고 생각해 보겠습니다.


엑셀의 가장 작은 기본 단위는 "셀"입니다.


그렇다면 태초의 엑셀은 아래와 같다고 가정할 수 있습니다.


이 때의 엑셀에는 배열의 개념이 필요 없습니다.


셀이 하나밖에 없기 때문이죠.


하지만 엑셀이 한단계 진화한다면 말은 달라집니다.



엑셀이 한 단계 진화해서 한 개의 행을 이루었습니다.


이 때부터 배열의 개념이 필요하게 됩니다.


배열(0), 배열(1), 배열(2), ... , 배열(n)으로 구성된 1차 배열이 등장하게 됩니다.




엑셀이 한 단계 더 진화해서 시트를 구성했습니다.


배열(0, 0) 배열(0, 1) 배열(0, 2)..... 배열(n, m)으로 구성된 2차 배열이 등장하게 됩니다.




엑셀이 한 단계 더 발전해서 엑셀 파일을 구성했습니다.


배열(0, 0, sheet1) 배열(0, 0, sheet2) ..... 배열(n, m, sheetx)로 구성된 3차 배열이 등장하게 됩니다.






정적배열과 동적배열


정적배열과 동적배열의 개념은 간단합니다.


정적배열은 이미 배열의 용량을 정해준 배열이고, 동적배열은 배열의 용량을 정해주지 않은 배열입니다.


동적배열은 배열이 차지하는 크기가 확실하지 않을 때 사용합니다.


굳이 동적배열을 선언하지 않고 정적배열로 배열을 최대한 크게 만들어도 이론상으로는 상관 없습니다.


하지만 배열은 상당히 많은 메모리를 차지합니다.


배열을 불필요하게 크게 선언한다면 메모리 부족 현상이 나타나기 쉽습니다.


따라서 배열을 동적으로 선언하여 불필요한 메모리 차지를 방지해야 합니다.




정적배열의 선언


1차 정적배열


Dim varArray(1 to 10)


2차 정적배열


Dim varArray(1 to 10, 1 to 20)    '행은 10, 열은 20인 직사각형 배열


동적배열의 선언



1차 동적배열


Dim varArray()

...

...                '배열에 필요한 크기 n을 구함

Redim varArray(n)            'varArray() 배열을 크기 n의 정적배열으로 다시 선언



2차 동적배열


Dim varArray()

...

...                '배열에 필요한 행 크기 n, 열 크기 m을 구함

Redim varArray(1 to n, 1 to m)                'varArray() 배열을 행 크기 n, 열 크기 m의 정적배열으로 다시 선언






이번 포스팅에선 배열의 기본 개념과 배열의 차원, 그리고 정적, 동적 배열에 대해 알아봤습니다.


다음 포스팅은 배열에 대한 좀 더 심화된 내용으로 찾아오겠습니다.



Posted by Simon K
: