t-hom’s diary

主にVBAネタを扱っているブログ…とも言えなくなってきたこの頃。

VBA 環状矢印を複数個つなげてリング状にするマクロ

オートシェイプで矢印を綺麗な環状に並べたい場合がある。
f:id:t-hom:20190129212208p:plain

その名の通り「環状矢印」というシェイプを使うのだが、手でやるとなかなか綺麗にできない。
試しに手でやってみたのがこちら。。
f:id:t-hom:20190129212624p:plain

ひどい。

そこで今回は環状矢印を綺麗に並べるためのマクロを作成してみた。

コード

Enum CircularArrowAdjustmentItemValues
    eThickness = 1
    eStartDegree = 4
    eEndDegree = 3
    eArrowheadSize = 5
End Enum
Type Position
    x As Double
    y As Double
End Type

Sub Draw360DegreeCircularArrows()
    '固定値:さわるな危険
    Const START_DEGREE_OFFSET = -90
    Const END_DEGREE_OFFSET = -110
    
    '設定値:適宜変更よろしく
    Const RING_SIZE = 300 'ここで指定したリングサイズになる。
    Const ARROW_THICKNESS = 0.1 '矢印の太さ。0~0.2くらいまでを、少数で指定する。
    Const NUMBER_OF_ARROWS = 5 'ここで指定した数の矢印が書かれる。12くらいが限界。
    Dim pos As Position
        pos.x = 100
        pos.y = 100
    
    'メインコードここから
    Dim startDegree As Long
    Dim endDegree As Long
    Dim i As Long
    For i = 1 To NUMBER_OF_ARROWS
        Dim sh As Shape: Set sh _
            = ActiveSheet.Shapes.AddShape(msoShapeCircularArrow, pos.x, pos.y, RING_SIZE, RING_SIZE)
        With sh
            startDegree = endDegree
            endDegree = startDegree + 360 / NUMBER_OF_ARROWS
            .Fill.ForeColor.RGB = GetRandomColor
            .Line.Visible = msoFalse
            .Adjustments.Item(eThickness) = ARROW_THICKNESS
            .Adjustments.Item(eStartDegree) = startDegree + START_DEGREE_OFFSET
            .Adjustments.Item(eEndDegree) = endDegree + END_DEGREE_OFFSET
            .Adjustments.Item(eArrowheadSize) = .Adjustments.Item(eThickness)
        End With
    Next
End Sub

Function GetRandomColor()
    Dim r: r = WorksheetFunction.RandBetween(0, 255)
    Dim g: g = WorksheetFunction.RandBetween(0, 255)
    Dim b: b = WorksheetFunction.RandBetween(0, 255)
    GetRandomColor = RGB(r, g, b)
End Function

実行方法

Draw360DegreeCircularArrowsを実行すると冒頭の図のように矢印が綺麗に環状に並ぶ。
定数で指定されている設定値を変えることで違った結果になる。

実行結果サンプル

NUMBER_OF_ARROWSに12を指定したのがこちら。
f:id:t-hom:20190129214035p:plain

ARROW_THICKNESSを0.05に指定したのがこちら。
f:id:t-hom:20190129214255p:plain

NUMBER_OF_ARROWSとARROW_THICKNESSはバランスを取る必要があり、太い矢印で個数を増やしすぎるとバグる。
ARROW_THICKNESSが0.2、NUMBER_OF_ARROWSが12の結果がこちら。
f:id:t-hom:20190129214722p:plain
なぜか真ん中に円が。

ARROW_THICKNESSを0.5にしてみると。。。風車みたいになった。
f:id:t-hom:20190129214808p:plain

ARROW_THICKNESSが0.2でも、NUMBER_OF_ARROWSが少ないとサマになる。
f:id:t-hom:20190129215112p:plain

角度補正について

START_DEGREE_OFFSETがマイナス90度、END_DEGREE_OFFSETがマイナス110度となっている。
実は矢印の頭のサイズ分、.Adjustments.Item(eStartDegree)と.Adjustments.Item(eEndDegree)では角度の開始値がズレているためだ。
f:id:t-hom:20190129215847p:plain

このままではとても分かりにくいので、両方とも時計の12時を0度として時計回りの角度で指定できるようにするためにオフセット値を引いて角度を補正している。

以上。

当ブログは、amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイト宣伝プログラムである、 Amazonアソシエイト・プログラムの参加者です。