[Excel] 10. 엑셀로 능력있는 직장인이 되는 법. 엑셀 그림판에 애니메이션 기능 추가하기!

in #kr-dev7 years ago (edited)

안녕하세요! @gbgg 입니다. 능력있는 직장인이 되는법!

엑셀 자동화 강의가 벌써 열번째입니다! 사실 어떻게 보면 많이 관심 없으실 만한 분야라서

어떤 컨텐츠로 강의를 진행해야할까 고민 많이했었는데 많이 좋아해주셔서 보람차고 기쁩니다 :)

지난 9번 강좌에서 진행했던 그림판 만들기에서 어떤 기능을 추가하면 좋을까 생각하다가

애니메이션 기능을 넣어보면 어떨까 하는 생각에 한번 만들어보게 되었습니다.

애니메이션이라고 해서 어렵게 느끼실 수 있으실 것 같은데, 지난 강의들에서 진행했던

데이터 불러오고 기록하는 단순한 방법으로 만들 수 있는 것이라 쉽게 이해하실 수 있으실

것이라고 생각합니다! :)

오늘 진행할 강의내용의 핵심은 두 가지 입니다!

  • 도트데이터 저장하고 불러오기
  • 엑셀 렉 줄이기 & 지연시간 활용

조금 난이도가 있으니 천천히 잘 따라와주세요! 지난번처럼 예제파일도 첨부하겠습니다!

강의가 끝나면 요런 애니메이션도 만드실 수 있을 겁니다!

에비츄.gif


기본 셋팅

가장 먼저 데이터의 양이 어느정도 될지 체크해보겠습니다.

52 * 52 = 2,704개의 픽셀로 이루어져 있습니다.

그렇다면 별도의 최적화를 하지 않는 이상 한 그림에 2,704개의 픽셀 데이터 값이 저장될 겁니다.

생각보다 데이터 양이 많아보입니다.

하지만 엑셀의 vba는 그 이상의 데이터도 빠르게 처리할 수 있기 때문에 걱정하지 않으셔도 됩니다.

이제 작업을 어떤식으로 진행할 지 기능별로 정리해보겠습니다.

그림 하나당 2,704개의 데이터를 저장해야합니다.

가장 좋은 방법은 시트 하나에 에니메이션 횟수만큼 데이터를 이어서 저장하는 것 이지만

이번 강의에서는 기본 개념을 위해 시트 3개를 만들어 각 시트에 저장해보겠습니다.

  • DATA1, 2, 3 시트를 만들어 이곳에 데이터 저장

데이터를 저장하려면 캔버스에 어떤 그림이 저장되어있는지 먼저 파악해야합니다.

픽셀 개념이기 때문에 FOR 반복문 두개를 사용해서 X축과 Y축의 값을 가져오려고 합니다.

  • X축과 Y축 픽셀의 색상 값 검사

저장된 데이터가 있으니 불러오기도 구현해야겠죠?

불러오기는 저장의 역순이라고 생각하시면 됩니다.

시트에 저장된 2,704개의 데이터들을 하나 씩 순차적으로 픽셀에 그려주면 됩니다.

픽셀에 그리기 앞서 기존에 있던 픽셀 그림들을 삭제해야합니다. 이 부분은 이전 시간에 배운 매크로를 활용해서 코드를 복사해 사용하겠습니다.

  • DATA1, 2, 3에 있는 데이터 값을 순차적으로 불러 캔버스에 표시
  • 캔버스에 있는 색상을 모두 빈 바탕색으로 변경 (매크로 활용)

불러오기 기능까지 구현되었다면 애니메이션은 간단합니다.

이번 포스팅에서는 총 3개의 픽셀데이터가 존재하는데 이 데이터들을 순차적으로 불러오면 됩니다.

화면클리어 -> 1번불러오기 -> 화면클리어 -> 2번불러오기....

방식으로 코드를 작성하면 되고 중간중간에 지연시간을 넣어 이모티콘처럼 작동하도록 구현해보겠습니다.

위 그림과 같이 버튼 3개를 배치하고 숫자를 써 넣을 셀 두개의 공간을 만듭니다.

픽셀 데이터를 넣을 시트 (DATA1, DATA2, DATA3)을 만듭니다.

DATA시트의 양식은 다음과 같이 NO와 RGB로 구성하겠습니다.


저장하기

저장 기능을 구현하기에 앞서 알고리즘을 말로 한번 풀어 써 보겠습니다.

픽셀 그림판은 이렇게 X, Y축으로 볼 수 있습니다.

이 데이터를 저장하려면 어떤 순서로 해야할까요?

저는 아래와 같은 순서대로 컬러 값을 뽑아보겠습니다.

(Y,X)라 가정할 때 위 그림같은 순서대로 좌표값을 찾아낼 수 있습니다.

일반적으로 이럴 때는 FOR 반복문을 두번 중첩시켜 읽어내는데 코드는 다음과 같습니다.

For i = 2 To 53
    For j = 2 To 53

    Next
Next

2부터 53까지 반복시킨 이유는 셀의 번호가 2부터 53까지이기 때문입니다.

1부터 52까지 두고 i + 1, j + 1 하는 방식도 있지만 여기서는 이렇게 코드를 짜 보겠습니다.

자 그렇다면 i값이 2고 j값이 2인 처음 부분에서 어떤 작업을 진행해줘야 할까요?

즉 저 RGB 부분에 (j , i)의 컬러 값을 넣어야 합니다. 이 작업을 2,704번 반복하면?

그림의 각각 픽셀 값을 모두 저장시킬 수 있습니다.

그렇다면 코드는 이런식으로 작성할 수 있을겁니다.

Sub 단추1_Click()
Sheets("DATA").Range("A2:B2706").ClearContents

For i = 2 To 53
    For j = 2 To 53
        cnt = Sheets("DATA").Range("A1").CurrentRegion.Rows.Count + 1
        Sheets("DATA").Cells(cnt, 1) = Val(Sheets("DATA").Cells(cnt - 1, 1)) + 1
        
        Sheets("DATA").Cells(cnt, 2) = Sheets("그림판").Cells(j, i).Interior.Color
    Next
Next
End Sub

.Interior.Color 부분만 제외하고 나머지는 지난 강의에서 진행했던 부분이니 살짝 넘어가보도록 하겠습니다.

.Interior.Color 코드는 해당 셀의 컬러값을 가져오는데 255,255,255 식으로 가져오는 게 아니고

색상마다 정해진 주소값을 가져오게 됩니다.

예를들어 하얀색은 16777215이 되고 검은색은 0이 됩니다.

하지만 이 값은 중요하지 않습니다. 어짜피 이 값을 그대로 적용시킬 것이기 때문에 모르셔도 됩니다.

Sheets("DATA").Range("A2:B2706").ClearContents 이 부분은 데이터를 저장시키기 전에

덮어씌우기 위해 기존에 있던 값을 모두 지웁니다.

코드를 작성하셨다면 버튼을 눌러보겠습니다.

잠깐의 렉? 이후에 DATA 시트로 가보면 이렇게 순서대로 값이 기록된 걸 확인하실 수 있을 겁니다.

DATA2와 DATA3도 추가해야겠죠?

이 BD30셀의 값이1이면 DATA, 2면 DATA2, 3이면 DATA3으로 저장되도록 해보겠습니다.

Sub 단추2_Click()

Dim cnt As Integer

If Sheets("그림판").Range("BD30").Value = "1" Then

Sheets("DATA").Range("A2:B2706").ClearContents

For i = 2 To 53

    For j = 2 To 53
        cnt = Sheets("DATA").Range("A1").CurrentRegion.Rows.Count + 1
        Sheets("DATA").Cells(cnt, 1) = Val(Sheets("DATA").Cells(cnt - 1, 1)) + 1
        
        Sheets("DATA").Cells(cnt, 2) = Sheets("그림판").Cells(j, i).Interior.Color
    Next
Next

ElseIf Sheets("그림판").Range("BD30").Value = "2" Then

Sheets("DATA2").Range("A2:B2706").ClearContents

For i = 2 To 53

    For j = 2 To 53
        cnt = Sheets("DATA2").Range("A1").CurrentRegion.Rows.Count + 1
        Sheets("DATA2").Cells(cnt, 1) = Val(Sheets("DATA2").Cells(cnt - 1, 1)) + 1
        
        Sheets("DATA2").Cells(cnt, 2) = Sheets("그림판").Cells(j, i).Interior.Color
    Next
Next

ElseIf Sheets("그림판").Range("BD30").Value = "3" Then

Sheets("DATA3").Range("A2 : B2706").ClearContents

For i = 2 To 53

    For j = 2 To 53
        cnt = Sheets("DATA3").Range("A1").CurrentRegion.Rows.Count + 1
        Sheets("DATA3").Cells(cnt, 1) = Val(Sheets("DATA3").Cells(cnt - 1, 1)) + 1
        
        Sheets("DATA3").Cells(cnt, 2) = Sheets("그림판").Cells(j, i).Interior.Color
    Next
Next
        
End If
        
End Sub

함수로 반복되는 부분을 만들어서 쓰면 길이를 줄일 수 있지만 3개밖에 안되기 때문에 간단하게 이렇게 코드를 작성해 보겠습니다. 위 코드를 복사하셔서 쓰시면 됩니다.


불러오기

불러오기기능은 생각보다 간단합니다. 그림으로 설명드릴게요!

아까 저장했던 데이터들을 가지고 그 위치의 픽셀 컬러값을 바꿔주기만 하면 됩니다.

저장하기랑 정확하게 반대죠? 그렇다면 어느 부분을 반대로 해야할까요?

왼쪽이 저장, 오른쪽이 불러오기 입니다. 빨간 부분은 바뀐 부분입니다.

cnt = 0 이기 때문에 임의로 +1을 해서 픽셀 위치값과 맞춰주었습니다.

  • 여기서 잠깐
    여기서 잠깐 버그가 발생하는데 분명

색이 없는 부분은 투명한 상태임에도 데이터에는 아까 하얀값 -> 16777215이 들어가게 됩니다. 이렇게 되면 사진을 불러왔을 때 배경이 흰색으로 덮이게 되는데요.

아직 테두리색을 설정하지 않았기 때문에 이 부분은 조건문으로 처리되지 않게 해줘야겠죠?

현재는 하얀색이 투명을 의미하기 때문에 조건문으로 걸러내주어야 합니다.

Sub 단추3_Click()

Dim cnt As Integer

Range("B2:BA53").Select
    With Selection.Interior
        .Pattern = xlNone
        .TintAndShade = 0
        .PatternTintAndShade = 0
End With

If Sheets("그림판").Range("BD36").Value = "1" Then

For i = 2 To 53

    For j = 2 To 53
               
        cnt = cnt + 1
        
        If Sheets("DATA").Cells(cnt + 1, 2).Value = 16777215 Then
         
        Else
        Sheets("그림판").Cells(j, i).Interior.Color = Sheets("DATA").Cells(cnt + 1, 2)
         
        End If
         
    Next
Next

ElseIf Sheets("그림판").Range("BD36").Value = "2" Then

For i = 2 To 53

    For j = 2 To 53
               
        cnt = cnt + 1
        
        If Sheets("DATA2").Cells(cnt + 1, 2).Value = 16777215 Then
         
        Else
        Sheets("그림판").Cells(j, i).Interior.Color = Sheets("DATA2").Cells(cnt + 1, 2)
         
        End If
         
    Next
Next

ElseIf Sheets("그림판").Range("BD36").Value = "3" Then

For i = 2 To 53

    For j = 2 To 53
               
        cnt = cnt + 1
        
        If Sheets("DATA3").Cells(cnt + 1, 2).Value = 16777215 Then
         
        Else
        Sheets("그림판").Cells(j, i).Interior.Color = Sheets("DATA3").Cells(cnt + 1, 2)
         
        End If
         
    Next
Next

End If

End Sub

위 코드를 붙여넣으시면 됩니다.

Range("B2:BA53").Select
    With Selection.Interior
        .Pattern = xlNone
        .TintAndShade = 0
        .PatternTintAndShade = 0
End With

위 코드 부분은 지난 9강에서 배운 매크로를 사용하여 B2열부터 BA53열을 선택 후 색상값을 투명하게 만드는 작업을 수행한 후 얻은 코드입니다.

그림을 불러오기 전에 기존에 그려져 있던 그림은 지우고 그려야겠죠?

위 코드까지 붙여넣으셨다면 다음과 같은 결과를 확인하실 수 있으실 겁니다.

gif1.gif


애니메이션

불러오기까지 이해가 가셨다면 애니메이션은 아주! 간단합니다.

불러오기 코드를 복붙하기만 하면 됩니다. 그림으로 한번 정리해 보겠습니다.

이렇게 해주면 되겠죠? 원리는 정말 간단합니다.

하지만 이렇게 하면 두 가지 문제가 발생합니다.

  • 엑셀이 과부하걸리면서 강제종료된다. (저장하지 않았다면 다 날라갑니다..ㅜㅜ)
  • 중간에 지연시간을 넣지 않았기 때문에 순식간에 프레임이 지나가버린다.

이 포스팅 초반에 제가 언급한 말이 있습니다.

'하지만 엑셀의 vba는 그 이상의 데이터도 빠르게 처리할 수 있기 때문에 걱정하지 않으셔도 됩니다.' 라고 말씀드렸었는데요.

아니 그런데 왜 과부하걸리는거죠?

엑셀은 정보 하나가 변경될 때 마다 시각적으로 모두 그 과정을 보여주도록 기본 셋팅되어있습니다.

우리는 2,704번의 그 변화를 계속해서 반복했는데 그 과정을 모두 보고 있었기 때문에

과부하가 걸려 이런 문제가 발생했던것입니다.

고맙게도 엑셀vba에서는 이 시각적으로 보는 기능을 켜고 끌수 있도록 만들어두었습니다.

Application.ScreenUpdating = False

Application.ScreenUpdating가 True 상태일때는 모두 시각적으로 표시됩니다.
Application.ScreenUpdating 가 False 상태일때는 작업이 완료된 후 표시됩니다.

그렇다면 이 코드를 껐다 켰다 하면 과부하를 막을 수 있을겁니다.

사이에 넣어보겠습니다.

이렇게 켜고 끄고를 반복하면 For문이 2704여번 반복하는 동안 시각효과가 꺼지게 되고

반복이 끝나면 시각적으로 보여줍니다.

이런식으로 사이에 넣어줌으로써 과부하를 방지할 수 있습니다.

이제 이 사이에 시간만 넣어주면 되겠죠?

start = Timer
    Do While Timer < start + 0.15
        DoEvents
    Loop

시간 함수는 간단합니다. Do while문을 사용하여 시간이 지나기전에 지나가지 못하도록 하는 방식인데요.

0.15라고 써져있는 부분만 수정해주시면 시간을 조절하실 수 있습니다.

단위는 1(초) 입니다. 저 부분에 10을 넣으면 10초가 되겠죠? 저는 0.15초로 셋팅하였습니다.

다음코드를 붙여넣어봅시다.

Sub 단추4_Click()

Dim cnt As Integer

Application.ScreenUpdating = False

For k = 1 To 5

    Range("B2:BA53").Select
    With Selection.Interior
        .Pattern = xlNone
        .TintAndShade = 0
        .PatternTintAndShade = 0
    End With
Range("BL59").Select
    
      For i = 2 To 53
        For j = 2 To 53
               
        cnt = cnt + 1
        
        If Sheets("DATA").Cells(cnt + 1, 2).Value = 16777215 Then
         
        Else
        Sheets("그림판").Cells(j, i).Interior.Color = Sheets("DATA").Cells(cnt + 1, 2)
         
        End If
         
        Next
    Next
    
Application.ScreenUpdating = True

    start = Timer
    Do While Timer < start + 0.15
        DoEvents
    Loop
    
Application.ScreenUpdating = False
    cnt = 0
    
Range("B2:BA53").Select
    With Selection.Interior
        .Pattern = xlNone
        .TintAndShade = 0
        .PatternTintAndShade = 0
    End With
Range("BL59").Select

    For i = 2 To 53
        For j = 2 To 53
               
        cnt = cnt + 1
        
        If Sheets("DATA2").Cells(cnt + 1, 2).Value = 16777215 Then
         
        Else
        Sheets("그림판").Cells(j, i).Interior.Color = Sheets("DATA2").Cells(cnt + 1, 2)
         
        End If
         
        Next
    Next
    
Application.ScreenUpdating = True
    
    start = Timer
    Do While Timer < start + 0.15
        DoEvents
    Loop
    
Application.ScreenUpdating = False
    cnt = 0

Range("B2:BA53").Select
    With Selection.Interior
        .Pattern = xlNone
        .TintAndShade = 0
        .PatternTintAndShade = 0
    End With
Range("BL59").Select

    For i = 2 To 53
        For j = 2 To 53
               
        cnt = cnt + 1
        
        If Sheets("DATA3").Cells(cnt + 1, 2).Value = 16777215 Then
         
        Else
        Sheets("그림판").Cells(j, i).Interior.Color = Sheets("DATA3").Cells(cnt + 1, 2)
         
        End If
         
        Next
    Next
    
Application.ScreenUpdating = True
    
    start = Timer
    Do While Timer < start + 0.15
        DoEvents
    Loop
    
Application.ScreenUpdating = False
    cnt = 0

Range("B2:BA53").Select
    With Selection.Interior
        .Pattern = xlNone
        .TintAndShade = 0
        .PatternTintAndShade = 0
    End With
Range("BL59").Select

    For i = 2 To 53
        For j = 2 To 53
               
        cnt = cnt + 1
        
        If Sheets("DATA2").Cells(cnt + 1, 2).Value = 16777215 Then
         
        Else
        Sheets("그림판").Cells(j, i).Interior.Color = Sheets("DATA2").Cells(cnt + 1, 2)
         
        End If
         
        Next
    Next
    
Application.ScreenUpdating = True

    start = Timer
    Do While Timer < start + 0.15
        DoEvents
    Loop
    
Application.ScreenUpdating = False
    cnt = 0

Next

Range("B2:BA53").Select
    With Selection.Interior
        .Pattern = xlNone
        .TintAndShade = 0
        .PatternTintAndShade = 0
    End With
Range("BL59").Select

    For i = 2 To 53
        For j = 2 To 53
               
        cnt = cnt + 1
        
        If Sheets("DATA").Cells(cnt + 1, 2).Value = 16777215 Then
         
        Else
        Sheets("그림판").Cells(j, i).Interior.Color = Sheets("DATA").Cells(cnt + 1, 2)
         
        End If
         
        Next
    Next
    
Application.ScreenUpdating = True

End Sub

코드가 정말 긴데 불러오기 동작을 복사해서 여러번 붙여넣은 것 밖에는 없습니다.

원래는 이렇게 쓸데없이 길게 코딩하면 안됩니다 ;;

단순히 3번 반복하는 것이기 때문에 이렇게 작성하였고

다음 버전에서는 함수로 만들어서 짧게 코딩하겠습니다. (굽신굽신)

여기까지 잘 따라오셨나요? 한번 구동시켜보겠습니다.

gif2.gif

(죄송합니다.. 에비츄의 귀여움을 제대로 표현하지 못한 것 같습니다 ㅠ_ㅠ)

이렇게 그림을 그려 저장한 후 다양한 이모티콘?을 만들어낼 수 있습니다.

gif2.gif

지난 포스팅에 잠깐 등장한 라이언입니다.


엑셀 자동화

지난 시간에 진행했던 엑셀 그림판에 애니메이션 기능을 추가해보았습니다.

어느정도 코딩에 지식이 있으신 분들을 위한 강의가 된 것 같아서 다음 기초편에 부족했던

코드에 대한 설명을 마무리해볼까 합니다.

벌써 엑셀 자동화강의가 10강까지 진행되었는데요, 아직 알려드릴것들이 많습니다 ㅎㅎ;

포스팅을 작성하고 한번 쭉 훑어보는데 괜찮게 쓴 것 같아서 올리고나면

다음에 다시 볼 때 무언가 덜 쓴내용이나 이런것들이 눈에 보이더라구요 ㅠㅠ

앞으로 더 알찬 포스팅이 되도록 노력하겠습니다. 감사합니다!

필요하실 분이나 한번 해보고 싶으신 분들을 위해

안쓰는 네이버 블로그에 자료 올려놓았습니다.

다운로드 링크로 이동

필요하신 분 있으시면 받아가세용!

혹시 강의에 추가되었으면 하는 기능이 있다거나

조언해주실 부분이 있으시다면 댓글로 거침없이 피드백 주세요! 쓴소리 좋아합니다!

능력있는 직장인이 되기 위해 엑셀로 전산프로그램을 만들 때 까지 한번 열심히 달려봅시다!

다음 포스팅에서 뵙겠습니다!


지난 포스팅

[Excel] 1. 능력있는 직장인이 되는 법. 엑셀 자동화란?

[Excel] 2. 능력있는 직장인이 되는 법. 다른 파일 불러오기!

[Excel] 3. 능력있는 직장인이 되는 법. 물품 입고시키기!

[Excel] 4. 엑셀로 능력있는 직장인이 되는 법. 간편한 UI 만들기!

[Excel] 5. 엑셀로 능력있는 직장인이 되는 법. 로그인 + 접속기록 만들기!

[Excel] 6. 엑셀로 능력있는 직장인이 되는 법. 재고(자산) 관리용 현황판 만들기!

[Excel] 7. 엑셀로 능력있는 직장인이 되는 법. 초급편 (기초함수 소개)

[Excel] 8. 엑셀로 능력있는 직장인이 되는 법. 초급편 (VLOOKUP, INDEX, MATCH 등)

[Excel] 9. 엑셀로 능력있는 직장인이 되는 법. 그림판 만들기 ! (매크로 기록 활용)

Sort:  

말도안돼..... 저런게 엑셀로 가능하다니...

더 신기한것도 많이 보여드릴 계획입니다ㅎㅎㅎ

컴퓨터를 잘못다루는 저로썬 어렵지만...
햄토리 너무 귀엽습니다!!!

네ㅠㅠ 이번꺼는 조금 어려우셨을것 같아요..
햄토리들 너무 귀엽죠 ㅋㅋㅋ

정말 대단하십니다.
무슨 프로그램을 만드는 것 같습니다.

감사합니다 ㅎㅎ 이왕 강의진행하면서 만드는거 프로그램처럼 만들어보려고 합니다!

엑셀의 한계가 있나 싶네요 대단하셔요 ..

할수있는건 다 해보려고 막 이것저것 해보고있습니다!ㅎㅎ

와 정녕 이것이 엑셀이란 말인가.....

아마 왠만한건 다 구현할수 있지 않을까 싶습니다!ㅋㅋ

와... 근데 직장에서 이거 만들고 있으면 혼날듯요 ㅎㅎ

ㅋㅋㅋ네 그림판은 약간 번외편 느낌으로 준비해봤어요!

항.. 이건 컴퓨터없이 읽을수없는글입니다ㅠㅠ 컴퓨터가필요해요!! 따라하고싶은데ㅠ

아이고 모바일이신가요 ㅠㅠ 아쉽네요 ㅠㅠㅠ 그래도 찾아주셔서 감사합니다 :)

헐 애니메이션까지!
정말 게시물 따라가면서 직접 해봐야겠습니다.

2018년 소망 릴레이에 지목되셨어요~
https://steemit.com/kr/@nand/2018-three-wishes

아이고 ㅠㅠ 이거 이미 진행했었습니다 ㅠㅠ 다른분 하셔야 할것같아요
지목해주셔서 감사합니다 낸드님! ^_^

앗 오래 전에 하셨군요 ㅎㅎ
그럼 슬쩍 다른분으로 바꾸겠습니다. ㅎㅎ

감사하고 죄송합니당 ㅠㅠㅋㅋㅋ

이정도 수준 엑셀실력이면 마스터 수준 아닌가요?ㅎㅎ
호기심에 포스팅 따라서 해보고 싶기도 합니다.
열심히 포스팅했을꺼 생각해서 ~
응원의 댓글 남겨요 화이팅~이요!

항상 들러주셔서 고맙습니다! ^_^ ㅎㅎㅎ
happyvirus님도 화이팅! :)

와~~ 대단하세요!!! 엑셀로 이렇게 귀여운 햄토리가!!!

살찐 햄토리가 되어버렸는데 귀엽게봐주셔서 감사합니다 ㅋㅋㅋㅋ

Coin Marketplace

STEEM 0.15
TRX 0.12
JST 0.025
BTC 54799.23
ETH 2353.99
USDT 1.00
SBD 2.36