글목록

2021년 6월 6일

Module 7. 여러 차트를 일괄 변경하기 - (1)선택된 차트를 배열에 할당하기

이제까지 주기적인 데이터를 선택하거나 fitting한 후, 차트를 작성하였습니다. 데이터를 일괄적으로 작업을 하고 차트를 작성하다보면, 차트 역시 데이터 갯수만큼 생성될 수 있습니다.

기본 형식으로 작성된 차트는 데이터의 분포를 파악하는 데에는 유용하지만, 별도의 자료를 작성하기 위해서는 일일이 차트들의 속성을 변경하는 작업이 필요하게 됩니다. 예를 들면, X, Y축의 범위라든지, 범례 위치라든지, 색상이나 크기를 맞추는 등...

만약 주기적인 데이터를 가진 자료로부터 차트를 만들었다면, 차트 종류나 데이터수와 같은 기본적인 차트 형식은 거의 동일할 것입니다. 따라서, 1개의 대표 차트에 기본적인 서식을 만들어 둔 후, 다른 차트에 서식을 복사할 수 있다면 필요한 수작업 양이 크게 줄어들 수 있을 것을 것입니다. 특히 수십개의 차트를 동시에 처리해야할 때 유용하겠지요.

이러한 작업을 위해, 우선 사용자가 선택한 차트를 배열에 할당할 필요가 있습니다.

그런데, 엑셀에서 차트는 복잡한 구조를 갖는 object입니다. 만약 사용자가 여러개의 object를 선택했다면, 이 중 차트만 배열에 할당해주면 됩니다만, 만약 1개의 차트의 구성 요소를 선택한 상태였다면 구성 요소의 Parent를 선택차트로 지정해주어야 합니다. 따라서, 차트를 선택했을 때에만 매크로가 작동할 수 있도록 사용자가 어떠한 개체를 선택했는지 확인하고, 차트를 선택했다면 선택된 차트를 배열로 지정해서 이후 차트와 관련된 일괄 작업을 할 수 있습니다.

'-----------------------------------

Function SelectionToChartArray(oChart() As Chart, Optional iCheckFirst As Boolean = False) As Boolean
  '차트가 포함된 개체를 선택했다면, oChart()에 선택된 차트 목록을 출력하고, 함수의 반환값은 True가 되고, 차트가 포함된 개체를 하나도 선택하지 않았다면, 함수의 반환값을 False로 반환해줍니다. Type을 지정해서 차트 선택 여부와 차트 목록을 동시에 반환할 수도 있지만, Type 선언을 최소화하기 위해서 이런 방식을 사용했습니다.
  On Error GoTo ErrorHandler
  Dim tChart() As Chart, tChart2() As Chart, tSel, i As Long, n As Long

  '현재 선택된 것이 어떤 개체인지 확인합니다.
  Select Case TypeName(Selection)
  '여러 개의 그림과 도형 등을 선택했을 때에는 TypeName이 DrawingObjects가 됩니다.
  'Selection.ShapeRange에 목록이 있으며 ShapeRange는 여러 개의 Shape으로 구성되고, Shape 아래 Chart가 포함됩니다. 차트를 포함한 Shape에서 차트만 배열에 할당해줍니다.
    Case "DrawingObjects"
      n = -1
      Set tSel = Selection.ShapeRange
      For i = 1 To tSel.Count
        If tSel(i).HasChart Then
          n = n + 1
          ReDim Preserve tChart(n)
          Set tChart(n) = tSel(i).Chart
        End If
      Next
  '여러 개의 차트를 일괄적으로 작업하기 위해, 1개의 차트에 서식이나, X, Y값의 범위, 크기 등을 지정해두고, 나머지 차트는 그 서식을 복사하는 방식으로 일괄 작업을 할 예정입니다. 따라서, 기준 차트를 첫번째로 선택한 차트로 설정할지 마지막에 선택한 차트로 설정할지를 확인한 후, 기준차트를 배열의 0번에 할당해줍니다. 시트에서 차트를 여러개 선택할 때, ZOrder를 바로 알 수 없기 때문에 기준차트를 마지막에 선택하는 것이 작업이 편할 수 있습니다.
      If n > 0 And iCheckFirst Then
        If MsgBox("첫번째 선택된 차트를 기준차트로 설정하시겠습니까?" & vbCrLf & " -Yes : 첫번째 차트를 기준차트로 설정" & vbCrLf & " -No : 마지막 차트를 기준차트로 설정", vbYesNo, "기준차트 설정") = vbNo Then
          tChart2 = tChart
          Set tChart(0) = tChart2(n)
          For i = 0 To n - 1
            Set tChart(i + 1) = tChart2(i)
          Next
        End If
      End If
  '1개 차트만 선택되었을 때에는 TypeName이 Chart로 주어집니다.
    Case "Chart"
      ReDim tChart(0)
      Set tChart(0) = Selection
  '차트가 선택되지 않은 상태에서 시트의 일부 구간을 선택했다면, Range를 선택한 것이며, 이때에는 차트와 과련된 작업을 할 필요가 없습니다.
    Case "Range"
      GoTo ErrorHandler
  '1개 차트 중 일부 요소를 선택했을 때에는 3번 정도 Parent 개체를 확인해보면, Chart를 선택했는지 확인할 수 있습니다. 그러나, 어떠한 요소는 이렇게 해도 현재 대상차트가 선택되지 않는 경우도 있습니다. 모든 구성요소를 다 확인해보진 않았으나, 차트 요소의 대부분은 Parent 개체를 확인하면 차트가 나오더군요.
    Case Else
      n = -1
      ReDim tChart(0)
      Set tSel = Selection
      For i = 1 To 3
        Set tSel = tSel.Parent
        If TypeName(tSel) = "Chart" Then
          Set tChart(0) = tSel
          n = n + 1
          Exit For
        End If
      Next
      If n < 0 Then GoTo ErrorHandler
  End Select

  '만약, 정상적으로 이 단계까지 왔다면, 1개 이상을 포함하는 차트 목록이 만들어졌음을 의미하며, 결과값을 True로 반환하고 함수를 종료합니다. 반면, 어떠한 이유에서든 에러가 발생했다면, 함수 결과를 False로 반환하고, 함수 목록은 반환해줄 필요가 없습니다.
  oChart = tChart
  SelectionToChartArray = True
  Erase tChart, tChart2
  Exit Function
ErrorHandler:
  SelectionToChartArray = False
  Erase tChart, tChart2
End Function

'-----------------------------------

댓글 없음:

댓글 쓰기

의견이나 질문이 있으신 분은 언제든지 댓글을 달아주세요~

많이 본 글 :