Excel 셀을 배열로 캡처하는 VBA

14486 단어 VBAExcel배열

VBA에서 배열을 사용하는 이유



모처럼, Excel VBA로 처리를 자동화해도, 1셀씩 입출력하고 있으면, 처리에 걸리는 시간이 길어져 버린다. 특히 Excel VBA의 경우 셀로의 출력에 시간이 걸리므로 대량의 데이터를 처리하는 경우는 1셀씩 처리를 하여 출력하는 것보다 배열로 처리를 하여 일괄적으로 출력하는 것 따라서 처리 시간을 줄일 수 있습니다.

구체적인 예



A열의 숫자와 B열의 숫자를 곱하여 100007로 나눈 나머지를 출력한다

처리하기Excel Data



A열과 B열에 0~10000의 난수를 입력(1행~50000행까지)


예 1: 한 줄씩 처리하는 경우



simple_code
Public Sub test_case_1()
    Const DIV As Long = 100007
    Dim i As Long
    For i = 1 To 50000
        Range("C" & i).Value = Range("A" & i).Value * Range("B" & i).Value Mod DIV
    Next
End Sub

계산 시간은 2.9921875초
1행씩 입출력하고 있으므로, 처리가 느린.

예 2: Range 객체로 처리하는 경우



using_object
Public Sub test_case_2()
    Const DIV As Long = 100007
    Dim i As Long 
    Dim r_in As Range, r_out As Range
    Set r_in = Range("A1:B50000")
    Set r_out = Range("C1:C50000") 
    For i = 1 To 50000
        r_out(i, 1) = r_in(i, 1) * r_in(i, 2) Mod DIV
    Next 
End Sub

계산 시간은 2.3984375초.
Range 오브젝트를 사용해, 일괄로 정보를 입력할 수 있기 때문에, 조금 계산이 빨라진다.
그러나, 1행씩 셀에 출력시키고 있기 때문에, 아직 처리가 느린. 일괄로 출력할 수 있으면, 더 빨라질 것.

예 3: 배열을 사용하여 처리하는 경우



using_array
Public Sub test_case_3()
    Const DIV As Long = 100007
    Dim i As Long
    Dim v_in As Variant, v_out As Variant

    v_in = Range("A1:B50000") ' Setをつけずに、Variant型変数にRangeオブジェクトを代入すると配列になる
    v_out = Range("C1:C50000") ' C1:C50000が空白なら空の配列になる

    For i = 1 To 50000
        v_out(i, 1) = v_in(i, 1) * v_in(i, 2) Mod DIV
    Next
    Range("C1:C50000") = v_out '一括でExcelシートに出力
End Sub

계산 시간은 0.140625초.
입력도 출력도, 일괄해서 실시하고 있으므로, 처리 시간이 짧다.
입력보다 Excel 워크 시트로의 출력을 일괄하여 수행하는 것이 처리 시간을 크게 단축 할 수 있습니다.

계산 시간 비교(10회분)




test_case 1
test_case_2
test_case_3


2.9921875
2.3984375
0.140625

2.9375
1.9765625
0.109375

2.9921875
1.9765625
0.140625

2.9375
1.9453125
0.140625

2.84375
2.328125
0.1328125

2.9296875
2.046875
0.1484375

3.0078125
1.984375
0.1328125

2.953125
1.921875
0.1953125

3.3359375
1.984375
0.1484375

2.8828125
2.015625
0.15625


배열 사용법



셀 범위를 배열로 변환



예를 들면, 이하와 같은 3행 4열의 범위의 Range 오브젝트를 배열에 건네주면, 3 x 4의 배열이 생긴다.


array_intro
Public Sub get_array()
    Dim r As Range
    Dim v As Variant
    Set r = Range("A1:D3")
    v = r 'Rangeオブジェクトの中身が配列に格納される
End Sub

로컬 윈도우에서 배열의 내용을 살펴보면 다음과 같다.
v(i, j) 는 i행 j열째의 요소에 대응하고 있는 것을 알 수 있다.
Variant형이므로, String형, Double형, Boolean형도 하나의 배열에 넣을 수 있다.


배열의 각 요소에 대한 데이터 처리 (Lbound, Ubound 함수)



얻어진 2차원 배열 v(i, j)의 행수, 열수는, Lbound, Ubound 함수로 취득할 수 있다.
Lbound, Ubound 함수의 두 번째 인수는 요소 범위를 얻는 차원을 지정합니다.

array_check
Public Sub check_array()
    Dim r As Range
    Dim v As Variant
    Set r = Range("A1:D3")
    v = r
    Debug.Print LBound(v, 1), UBound(v, 1) '配列vは、1行~3行まである → 1, 3が出力
    Debug.Print LBound(v, 2), UBound(v, 2) '配列vは、1列~4列まである → 1, 4が出力
End Sub

얻어진 배열에, 이하의 처리를 하고, Range("A5:D7")에 출력해 본다
첫 번째 줄은 대문자로 변환
두 번째 줄은 5를 더한다.
세 번째 줄은 논리 부정

array_proc
Public Sub proc_array()
    Dim r_in As Range, r_out As Range
    Dim v As Variant
    Dim i As Long, j As Long

    Set r_in = Range("A1:D3")
    Set r_out = Range("A5:D7")
    v = r_in
    For i = LBound(v, 1) To UBound(v, 1)
        For j = LBound(v, 2) To UBound(v, 2)
            If i = 1 Then v(i, j) = UCase(v(i, j)) '1行目の処理
            If i = 2 Then v(i, j) = v(i, j) + 5    '2行目の処理
            If i = 3 Then v(i, j) = Not v(i, j)    '3行目の処理
        Next
    Next
    r_out = v

End Sub

출력 결과는 다음과 같습니다.


요약



Excel 셀의 범위를 배열에 입출력하는 것은, 간단하게 할 수 있는 비교적 별로 활용되고 있지 않다.
처리의 고속화도 이어지므로 활용할 수 있게 되고 싶다.

좋은 웹페이지 즐겨찾기