Excel & IT Info

아이엑셀러 닷컴, 엑셀러TV

VBA

Python과 Excel VBA의 배열 개념 비교

권현욱(엑셀러) 2024. 2. 15. 20:00
반응형

배열은 하나 또는 여러 개의 값을 가질 수 있는 특수한 형태의 변수입니다. 파이썬에서는 배열과 유사한 리스트(List)를 사용할 수 있지만 Excel의 배열과 같은 형태는 없습니다. 하지만 외부 라이브러리를 사용하여 배열을 만들 수 있습니다. 간단한 예를 통해 Python과 Excel VBA의 배열 개념을 소개합니다.

 

권현욱(엑셀러) | 아이엑셀러 닷컴 대표 · Microsoft Excel MVP · Excel 솔루션 프로바이더 · 작가

 

(이미지: 아이엑셀러 닷컴)

 

※ 이 글은 아래 기사 내용을 토대로 작성되었습니다만, 필자의 개인 의견이나 추가 자료들이 다수 포함되어 있습니다.


  • 원문: Arrays in Python and Excel VBA
  • URL: https://towardsdatascience.com/arrays-in-python-and-excel-vba-efd73b649d6d

대부분의 프로그래밍 언어에는 '배열' 개념이 있습니다. 파이썬과 엑셀 VBA의 배열 개념을 비교합니다. VBA를 처음부터 또는 다시 시작하실 분들은 다음 포스트로 시작해 보세요.
💎 VBA 입문 강의

파이썬의 배열

배열은 모든 데이터 유형의 하나 또는 여러 값을 보유할 수 있는 특수 변수입니다. Python에서는 목록(List)과 같은 유사한 데이터 유형과 달리 배열에 대한 기본 지원이 없습니다. 그러나 numpy 패키지의 배열 모듈을 사용하여 배열을 만들 수 있습니다. numpy 배열 객체의 인덱스는 항상 0으로 시작합니다. numpy 배열 내부의 마지막 항목은 -1을 참조하여 액세스할 수 있습니다. numpy 배열은 특정 데이터 유형 또는 여러 데이터 유형의 변수를 보유할 수 있습니다.

아래에 간단한 코드가 있습니다. 이 코드 조각은 numpy 배열에서 모양(치수, 즉 행, 열), 크기(요소 수) 및 길이(컨테이너에 있는 항목 수, 즉 행)에 액세스할 수 있는 방법을 보여줍니다.

import numpy as np

simple_array = np.array([1, 2, 3])
mixed_array = np.array([1, 2, 3, "a", "b", "c", 4.5])
print ("Simple array: ", simple_array)
print ("First element of simple_array: ", simple_array[0])
print ("Shape of simple_array: ", simple_array.shape)
print ("Size of simple_array; ", simple_array.size)
print ("\n")
print ("Mixed array: ", mixed_array)
print ("Last element of mixed_array: ", mixed_array[-1])
print ("Length of mixed_array: ", len(mixed_array))

 

대수 행렬 연산에 numpy 배열 사용하기

유연한 구조로 인해 numpy 배열은 다양한 차원의 행렬 객체를 생성하고 이에 대한 작업을 수행하는 데 편리합니다. 위의 예제는 1차원 배열 객체의 예입니다.

아래에서는 2차원 배열인 두 개의 배열 객체 a와 b를 만들었습니다(2*2 행렬). 두 행렬의 내적을 수행하는 것은 np.dot(a, b)를 수행하는 것만큼 간단합니다. 내적에서 a와 b는 벡터(크기와 방향을 모두 갖는 객체)로 간주됩니다. 행렬 곱셈에서 행렬 a의 각 요소는 행렬 b의 해당 요소와 곱해집니다. 예를 들어, a11(첫 번째 행, 첫 번째 열 항목)에 b11을 곱하는 식입니다.

a = np.array([[0, 1],[2,3]])
b = np.array([[3,4],[5,6]])
print ("Dot Product of a and b: \n", np.dot(a,b))
print ("Matrix multiplication of a and b \n",a*b)

 

또한 덧셈, 뺄셈, 전치 등의 다른 행렬 연산도 수행할 수 있습니다. 행렬의 행렬식을 얻으려면 np.linalg.det(a)를 사용할 수 있습니다. 행렬의 곱셈 역원을 얻으려면 np.linalg.inv(a)를 사용할 수 있습니다.

print (“Addition of a and b:\n”, np.add(a, b))
print ("Also addition of a and b:\n", a+b)
print ("Transpose of a:\n", a.T)
print ("Determinant of a:\n", np.linalg.det(a))
print ("Inverse of a:\n", np.linalg.inv(a))

 

목록 객체에서 m*n 모양의 numpy 배열 만들기

필자가 살았던 국가 목록과 해당 수도를 포함하는 country_lived와 capitals라는 두 개의 목록을 가지고 있습니다.

countries_lived = [“Nepal”,”India”,”Germany”,”Netherlands”]
capitals = [“Kathmandu”,”New Delhi”,”Berlin”,”Amsterdam”]

 

이러한 목록 개체를 포함하는 배열을 만들려면 np.array([countries_lived, capitals])를 사용할 수 있습니다. 그러면 2*4 모양(즉, 2행과 4열)의 배열이 반환됩니다. 단일 국가와 해당 국가의 수도를 같은 행에 두려면 동일한 배열을 바꾸면 됩니다.

array1 = np.array([countries_lived, capitals])
print ("array1:\n", array1)
print ("Shape of array1:\n", array1.shape)
print ("Size of array1:\n", array1.size)

array2 = np.array([countries_lived, capitals]).T
print ("array2:\n", array2)
print ("Shape of array2:\n", array2.shape)
print ("Size of array2:\n", array2.size)

 

numpy 배열에 항목 추가 및 데이터프레임 생성

France 및 Paris 항목을 array2에 추가 행으로 추가하고 싶다고 가정해 보겠습니다. 이 작업은 np.append(arr, value, axis = None) 구문을 사용하여 수행할 수 있습니다. 값은 축을 제외하고 arr과 동일한 모양이어야 합니다. 축이 지정되지 않으면 사용하기 전에 arr과 값이 모두 평면화됩니다.

아래와 같이 새 항목을 배열에 새 행으로 추가했습니다. 마지막으로 모양 (5,2)의 array2는 Country 및 Capital 열이 있는 데이터 프레임 개체 df를 만드는 데 사용됩니다.

array2 = np.append(array2, [[“France”,”Paris”]], axis = 0)
print ("array2 after appening new row: \n", array2)

import pandas as pd

df = pd.DataFrame(array2,
                 columns = ["Country", "Capital"])

df

 

Excel VBA의 배열

Python과 유사하게 배열은 Excel VBA의 변수 모음이기도 합니다. 배열의 하한은 Excel VBA에서 0 또는 1부터 시작할 수 있습니다. 기본 하한은 0입니다. 그러나 모듈 상단에 Option Base 1을 명시하여 1부터 시작되도록 지정할 수 있습니다. 배열에 사용된 하한과 상한을 감지하려면 각각 Lbound(array_name)와 Ubound(array_name)를 사용합니다.

 

배열 선언

Public 키워드를 사용하여 배열을 공개적으로(즉, 전역변수) 선언할 수 있습니다. Excel VBA에서 배열이나 기타 변수를 공개적으로 선언하면 다시 선언하지 않고도 모든 모듈이나 서브루틴에서 사용할 수 있습니다.

Public countries(1 to 4) as String
Public capitals(4) as String
Public countries_visited() as String

 

또는 Dim 키워드를 사용하여 서브루틴 내에서 로컬로 배열을 선언할 수도 있습니다. 그런 다음 이러한 배열은 특정 서브루틴 내에서만 사용할 수 있습니다.

Dim countries(1 to 4) as String
Dim capitals(4) as String

 

위의 예에서는 배열의 크기도 지정됩니다. 1~4를 지정하거나 4만 지정하면 둘 다 크기가 4인 배열을 의미합니다.

1차원 배열

1차원 배열은 행 수(예: 1~5), 즉 배열에 포함될 요소 수를 선언하여 할당됩니다. 필자가 살았던 4개국의 1차원 배열을 만드는 예는 다음과 같습니다. Excel 파일 워크시트의 A열에 해당 국가의 이름이 인쇄됩니다.

Option Base 1

Sub array_1d()
    countries(1) = "Nepal"
    countries(2) = "India"
    countries(3) = "Germany"
    countries(4) = "Netherlands"

    Dim i As Integer
    Range("A1").Value = "Country"

    For i = 1 To 4
        Range("A" & i + 1).Value = countries(i)
    Next i
End Sub

 

2차원 배열

2차원 배열은 행과 열의 개수를 선언하여 정의됩니다. 다음 예에서는 country_capital이라는 2차원 배열을 선언합니다. 각 행의 첫 번째 요소는 이전 섹션에서 선언된 국가 배열의 요소에 해당합니다. 각 행의 두 번째 요소는 아래 코드에서 개별적으로 선언된 수도에 해당합니다.

Sub array_2d()

    Dim country_capital(4, 2) As String

    For i = 1 To 4
        country_capital(i, 1) = countries(i)
    Next i

    country_capital(1, 2) = "Kathmandu"
    country_capital(2, 2) = "New Delhi"
    country_capital(3, 2) = "Berlin"
    country_capital(4, 2) = "Amsterdam"

    Range("B1").Value = "Capital"

    For i = 1 To 4
        Range("A" & i + 1).Value = country_capital(i, 1)
        Range("B" & i + 1).Value = country_capital(i, 2)
    Next i
End Sub

 

동적 배열

동적 배열은 배열 크기가 확실하지 않고 나중에 배열 크기가 변경될 수 있는 경우에 유용합니다. 아래 코드에서는 배열의 크기를 지정하지 않고 country_visited와 인구라는 두 개의 배열을 지정합니다. Dynamic_array 서브루틴 내에서 ReDim 문을 사용하여 두 배열의 크기를 4로 지정합니다. 다음으로, 내가 방문한 4개 국가와 그 인구를 기반으로 배열의 각 요소를 개별적으로 지정합니다.

Option Base 1

Public countries_visited() As String
Public population() As Long

Sub dynamic_array()
    Dim wb As Workbook
    Dim ws2 As Worksheet
    Set wb = ThisWorkbook
    Set ws2 = wb.Worksheets("Sheet2")

    ReDim countries_visisted(4)
    ReDim population(4)

    countries_visited(1) = "France"
    population(1) = 68

    countries_visited(2) = "Spain"
    population(2) = 48

    countries_visited(3) = "Iran"
    population(3) = 88

    countries_visited(4) = "Indonesia"
    population(4) = 274
End Sub

 

이렇게 작성했는데 얼마 후 또 한 나라(포르투갈)를 더 방문했다는 사실을 깨달았습니다. 이러한 배열의 원래 내용/요소를 유지하면서 배열의 크기를 다시 정의합니다. 이 배열의 크기를 1씩 늘립니다. 이를 위해 아래와 같이 ReDim Preserve 문을 사용합니다.

ReDim Preserve countries_visited(1 to 5)
ReDim Preserve population(1 to 5)

 

이 내용을 반영한 전체 코드는 아래와 같습니다.

Option Base 1

Public countries_visited() As String
Public population() As Long

Sub dynamic_array()
    Dim wb As Workbook
    Dim ws2 As Worksheet
    Set wb = ThisWorkbook
    Set ws2 = wb.Worksheets("Sheet2")

    ReDim countries_visisted(4)
    ReDim population(4)

    countries_visited(1) = "France"
    population(1) = 68

    countries_visited(2) = "Spain"
    population(2) = 48

    countries_visited(3) = "Iran"
    population(3) = 88

    countries_visited(4) = "Indonesia"
    population(4) = 274

    ws2.Range("A1").Value = "Countries visited"
    ws2.Range("B1").Value = "Population (million)"

    ReDim Preserve countries_visited(5)
    ReDim Preserve population(5)

    countries_visited(5) = "Portugal"
    population(5) = 10

    Dim i As Integer
    For i = 2 To 6
        Range("A" & i).Value = countries_visited(i - 1)
        Range("B" & i).Value = population(i - 1)
    Next i
End Sub

 

다양한 데이터 유형의 변수를 저장하는 배열 선언

위 섹션에서는 String 데이터 유형의 변수를 저장하기 위해 country_visited 배열을 선언하고 Long 데이터 유형의 변수를 저장하기 위해 인구 배열을 선언했습니다. Python numpy 배열과 유사하게 Excel VBA의 배열에 다양한 데이터 유형의 변수를 저장할 수도 있습니다. 이 경우 배열은 Variant 유형으로 선언되어야 합니다.

아래 예에서는 배열 테스트가 Variant로 선언되었습니다. 크기는 ReDim 문을 사용하여 3으로 지정됩니다. String, Integer 및 Date 유형의 세 가지 요소가 테스트 내에 지정됩니다. TypeName() 함수 내부에 변수를 전달하여 데이터 유형을 식별할 수 있습니다.

ption Base 0

Sub variant_test()
    Dim test() As Variant
    ReDim test(3)

    test = Array("Germany population in million: ", 83, Date)

    Dim i As Integer
    For i = 0 To 2 
        Debug.Print "Element " & i & " of test array is: " & test(i) & " of type " & TypeName(test(i))
    Next i
End Sub

 

정리

배열은 하나 이상의 데이터 유형의 값/변수의 모음입니다. 각 변수는 배열의 특정 인덱스 번호와 연관됩니다. 배열은 1차원, 2차원 또는 다중 차원일 수 있습니다. Python에는 배열에 대한 기본 지원이 없지만 numpy 패키지를 사용하여 배열을 만들 수 있습니다. 값을 저장하는 것 외에도 numpy 배열은 행렬 작업을 수행하는 데 매우 유용합니다.

 

Excel VBA에서 배열은 대규모 요소 데이터베이스 작업에 매우 유용합니다. Excel VBA에서는 배열 크기가 미리 정의되어 있는 경우 배열이 정적일 수 있습니다. 또는 배열의 크기가 미리 정의되지 않은 경우 배열은 동적일 수 있지만 이동하면서 지정할 수 있으며 배열에 이미 저장된 요소를 유지하면서 크기를 조정할 수도 있습니다.

Excel과 VBA의 모든 것 아이엑셀러 닷컴 · 강사들이 숨겨 놓고 보는 엑셀러TV