VBAで弧・扇形を描く

 以下の例ではページヘッダに描画するようにしていますので、ページヘッダのあるレポートを作っておくことが必要です(「レコードソースの値に基づく描画」を除く)。

弧と扇形の描画方法について

f:id:accs2014:20190228001241p:plain:right:w400

 弧も扇形も、円や楕円と同じくCircleメソッドを用います。
 円や楕円との違いは第4,第5のパラメータで始点と終点を指定することで、各点の指定は座標ではなく角度(単位はラジアン)で行います。
 中心点Oと半径r、角度θと点Pの位置関係は画像のようになります。
 角度θは-2πから2πまで(約-6.28から約6.28まで)の数値で指定できますので、1つの点を表すときに角度の指定方法が複数あります。画像からもわかるように1/2πと-3/2πは同じ点に対応します。
 
 そこで弧と扇形の描き方の違いですが、次のようになります。

  • 弧……角度をプラスの値で指定する(0を含む)
  • 扇型……角度をマイナスの値で指定する(0を含まない(要注意))
 詳しくは以下に示しますが、まずはこの点を押さえておいてください。

弧の描画例

f:id:accs2014:20190227233631p:plain:right:w600

 ページヘッダを持つレポートを作り、レポートモジュールに次のように記します。

Option Compare Database

Private Sub ページヘッダーセクション_Format(Cancel As Integer, FormatCount As Integer)

    Const pi As Single = 3.14

    Me.DrawWidth = 10

    '1個目                     点1の角度 < 点2の角度
    Me.Circle (1000, 1000), 450, , 0, 1 / 2 * pi

    '2個目                     点1の角度 > 点2の角度
    Me.Circle (1000, 2000), 450, , 1 / 2 * pi, 0

End Sub

 さて、このコードでは2つの弧を描きますが、点1(始点)の角度と点2(終点)の角度は順番が違うだけで組み合わせは同じです(0と1/2π)。
 ではどういう違いが出るかというと……

f:id:accs2014:20190227233628p:plain:right:w250

 こうなります。点1と点2の角度の値の大小関係により、2つの点を結ぶ描画の向き(側)が変わります。

 これを踏まえて次のようなコードを実行してみます。

Option Compare Database

Private Sub ページヘッダーセクション_Format(Cancel As Integer, FormatCount As Integer)

    Const pi As Single = 3.14

    Me.DrawWidth = 10

    '1段目                     点1の角度 < 点2の角度
    Me.Circle (1000, 1000), 450, , 0, 1 / 2 * pi
    Me.Circle (2000, 1000), 450, , 0, 2 / 2 * pi
    Me.Circle (3000, 1000), 450, , 0, 3 / 2 * pi
    Me.Circle (4000, 1000), 450, , 0, 4 / 2 * pi

    '2段目                     点1の角度 < 点2の角度
    Me.Circle (1000, 2000), 450, , 1 / 2 * pi, 0
    Me.Circle (2000, 2000), 450, , 2 / 2 * pi, 0
    Me.Circle (3000, 2000), 450, , 3 / 2 * pi, 0
    Me.Circle (4000, 2000), 450, , 4 / 2 * pi, 0

End Sub

 

f:id:accs2014:20190227233625p:plain:right:w400

 結果はこうなります。
 円周率が厳密でないので、下段右端の例では弧が小さい点になって残っています。上段右端も円ではないのですが、線幅(DrawWidth)が太いせいでつながって見えます。
 ちなみに線幅が太いとθ=0付近の点を指定したときに意図した描画にならないことがありますのでご注意ください;-o-)

 2つの点の角度、その大小関係による描画の違い理解をできれば自由に弧を描くことができます。
 ただし、指定できる角度の範囲が0から2πと決まっていますので注意が必要です。
 次のコードは、円の右端・上端・左端・下端がそれぞれ欠けたような弧を描くものです。

Option Compare Database

Private Sub ページヘッダーセクション_Format(Cancel As Integer, FormatCount As Integer)

    Const pi As Single = 3.14

    Me.DrawWidth = 10

    '1個目  0近辺が欠けている弧
    Me.Circle (1000, 1000), 450, , 1 / 8 * pi, 15 / 8 * pi
    '2個目  1/2π近辺が欠けている弧
    Me.Circle (2000, 1000), 450, , 5 / 8 * pi, 3 / 8 * pi
    '3個目  π近辺が欠けている弧
    Me.Circle (3000, 1000), 450, , 9 / 8 * pi, 7 / 8 * pi
    '4個目  3/2π近辺が欠けている弧
    Me.Circle (4000, 1000), 450, , 13 / 8 * pi, 11 / 8 * pi

End Sub

2番目の弧において「 Me.Circle (2000, 1000), 450, , 5 / 8 * pi, 19 / 8 * pi」とやってしまうと19/8π>2πのためエラーになります。そこを考慮して2つの点の角度を指定する必要があります。
 

f:id:accs2014:20190227233622p:plain:right:w400

 印刷プレビューはこうなります。

扇形の描画例

 角度の指定にマイナスの値を用いるという以外は弧の例と同じです。
 ただし、角度として0を指定できないため注意が必要です。
 次のコードでは12個の扇形を描きます(弧の例の2番目、3番目の画像で示した12個の弧に対応しています)。0の代わりに、0に近いマイナスの値を定数minus_zeroとして宣言しています。

Option Compare Database

Private Sub ページヘッダーセクション_Format(Cancel As Integer, FormatCount As Integer)

    Const pi As Single = 3.14
    '0点を含むと扇形にならないため小さい負の値を用いる
    Const minus_zero As Single = -0.01

    Me.DrawWidth = 10
    Me.FillStyle = 4

    '1段目                          点1の角度 > 点2の角度
    Me.Circle (1000, 1000), 450, , minus_zero, -1 / 2 * pi
    Me.Circle (2000, 1000), 450, , minus_zero, -2 / 2 * pi
    Me.Circle (3000, 1000), 450, , minus_zero, -3 / 2 * pi
    Me.Circle (4000, 1000), 450, , minus_zero, -4 / 2 * pi

    '2段目                          点1の角度 < 点2の角度
    Me.Circle (1000, 2000), 450, , -1 / 2 * pi, minus_zero
    Me.Circle (2000, 2000), 450, , -2 / 2 * pi, minus_zero
    Me.Circle (3000, 2000), 450, , -3 / 2 * pi, minus_zero
    Me.Circle (4000, 2000), 450, , -4 / 2 * pi, minus_zero

    '3段目  順に0,1/2π,π,3/2π付近が欠けている扇形
    Me.Circle (1000, 3000), 450, , -1 / 8 * pi, -15 / 8 * pi
    Me.Circle (2000, 3000), 450, , -5 / 8 * pi, -3 / 8 * pi
    Me.Circle (3000, 3000), 450, , -9 / 8 * pi, -7 / 8 * pi
    Me.Circle (4000, 3000), 450, , -13 / 8 * pi, -11 / 8 * pi

End Sub

 

f:id:accs2014:20190227233712p:plain:right:w400

 印刷プレビューです。

レコードソースの値に基づく描画

f:id:accs2014:20190228150559p:plain:right:w550

 レコードソースになっているテーブルやクエリの値を参照し、その値に応じた図形を描画する例です。
 このようなクエリをレコードソースとするレポートを作成し、達成率の大きさに応じた扇形(円グラフ)を表示するものとします。

 レポートモジュールの内容は次のようになります。
 指定できる角度の制約(-2π<Φ<0)があるため値に応じて場合分けする必要があります。

Option Compare Database

Private Sub 詳細_Format(Cancel As Integer, FormatCount As Integer)

    Const pi As Single = 3.14
    '0点を含むと扇形にならないため小さい負の値を用いる
    Const minus_zero As Single = -0.01

    Me.FillColor = RGB(255, 0, 0)
    Me.FillStyle = 0
    
    If Me.達成率 >= 100 Then
        Me.Circle (7000, 850), 550, RGB(255, 0, 0)
    ElseIf Me.達成率 >= 25 And Me.達成率 < 100 Then
        Me.Circle (7000, 850), 550, RGB(255, 0, 0), -5 / 2 * pi + (0.01 * Me.達成率 * 2 * pi), -1 / 2 * pi
    ElseIf Me.達成率 < 25 And Me.達成率 > 0 Then
        Me.Circle (7000, 850), 550, RGB(255, 0, 0), -1 / 2 * pi + (0.01 * Me.達成率 * 2 * pi), -1 / 2 * pi
    End If

End Sub

 

f:id:accs2014:20190228150556p:plain:right:w450

 印刷プレビューです。
 
 ただし、テキストボックスに対する条件付き書式でデータバー(横棒グラフ)を表示する方がはるかに簡単ですのでそちらをおすすめします。

プラスの角度とマイナスの角度が混在する場合

 おまけですが、角度を指定するときに点1の角度と点2の角度の符号が違う場合の例です。

Option Compare Database

Private Sub ページヘッダーセクション_Format(Cancel As Integer, FormatCount As Integer)

    Const pi As Single = 3.14

    Me.DrawWidth = 10
    Me.FillStyle = 4

    '                         一方の角度が正、一方の角度が負
    Me.Circle (1000, 1000), 450, , -1 / 4 * pi, 1 / 4 * pi
    Me.Circle (2000, 1000), 450, , 1 / 4 * pi, -1 / 4 * pi

End Sub

 

f:id:accs2014:20190227233708p:plain:right:w300

 こうなります。角度によってはアルファベットのGのような弧と扇形が混在するような結果になることもあります。