ic


워크시트 출력에 대한 고민-배열의 출력 EXCEL/VBA

vba를 이용하여 워크시트에 출력하는 일은 거의 필수적인 작업이다. 그런데 출력하는 작업은 vba의 속도를 떨어 뜨리는 주범중 하나이다. 그래서 추천하는 방법이 하나의 루프에서 100번을 반복하면서 100번을 출력하는 것보다는 배열에 저장하고, 루프를 나오면 한번에 출력하는 것이다.

그런데 10,000개의 데이터를 워크시트에 한번에 출력하는 게 문제이다. Range("B2") = mat()는 B2셀에 배열의 (1,1)의 값을 출력한다.
Sub CopyMatrixToRange()
Dim mat(10, 10) As Double
Dim i As Long, j As Long

Randomize
For i = LBound(mat) To UBound(mat)
For j = LBound(mat, 2) To UBound(mat, 2)
mat(i, j) = Rnd
Next
Next
Sheet1.Range("B2") = mat()
End Sub
이런 오류를 해결하고 아래와 같이 출력하려면

아래와 같이 출력하려는 배열의 크기만큼 셀의 범위를 맞춰야 한다. 아래의 코드에서 10x10의 배열을 출력하기 위해 셀의 범위를 B2:K11 로 맞춰야 한다.
Sub CopyMatrixToRange()
Dim mat(10, 10) As Double
Dim i As Long, j As Long

Randomize
For i = LBound(mat) To UBound(mat)
For j = LBound(mat, 2) To UBound(mat, 2)
mat(i, j) = Rnd
Next
Next
Sheet1.Range("B2:K11") = mat()
End Sub
그런데 배열의 크기에 맞춰 셀 범위를 하드코딩해두는 건 그리 아름다운 모습은 아니다. 그래서 배열의 크기만큼 셀 범위를 자동으로 맞출 필요가 있고, 크기를 계산할 필요가 있다. 아래의 코드에서 Range개체의 Resize()메서드와 UBound()/LBound()함수를 이용하여 행과 열의 크기를 계산하였다.
Sub CopyMatrixToRange()
Dim mat(10, 10) As Double
Dim i As Long, j As Long

Randomize
For i = LBound(mat) To UBound(mat)
For j = LBound(mat, 2) To UBound(mat, 2)
mat(i, j) = Rnd
Next
Next

Dim cntRow As Long, cntCol As Long

cntRow = UBound(mat) - LBound(mat) + 1
cntCol = UBound(mat, 2) - LBound(mat, 2) + 1


Sheet1.Range("B2").Resize(cntRow, cntCol) = mat()
End Sub
하지만 1억개의 셀에 출력하는 것은 버거운지 약간 시간이 걸리지만 루프를 돌리는 것보단 훨씬 낫다.

덧글

  • 눌눌 2018/04/15 22:05 # 답글

    오옷 .Resize 라는 명령어가 있군요
    가르침 감사합니다!
  • 타임버드 2018/04/15 23:54 #

    ㅎㅎ 찾아주셔서 감사합니다
  • 2018/04/17 04:22 # 삭제 답글 비공개

    비공개 덧글입니다.
  • 2018/04/17 06:14 # 비공개

    비공개 답글입니다.
댓글 입력 영역