セルの枠線に合わせて図形(矢印)を描画する

# 概要

セルの枠線に合わせて図形(矢印)を描画します.

Shapes.AddConnectorに渡す位置を「セルの幅と高さを基準にした値」を使ってセルの枠線に合わせています.

![draw_lines.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34777/635d1d7d-1a25-ceda-3cc6-fe522c042d52.gif)

ただ, 個数が少ないなら手で「[ALT＋マウスドラッグ][2]」するのがいいです.

# コード

```vb:コード
Option Explicit

' セルの枠線に合わせて図形(矢印)を描画する
Sub DrawHorizontalLinesOnCells()

    '矢印の個数
    Const LinesCount = 100

    ' 矢印の位置を計算する基本単位(BasicUnit).
    Dim BasicUnitX
    BasicUnitX = Cells(1, 1).Width
    
    Dim BasicUnitY
    BasicUnitY = Cells(1, 1).RowHeight

    ' 矢印を描画する初期位置(Offset)
    Dim OffsetX
    OffsetX = BasicUnitX * 1
    
    Dim OffsetY
    OffsetY = BasicUnitY * 3
    
    ' 矢印の長さ
    Dim LineLength
    LineLength = BasicUnitX * 3
    
    '''''
    ' 矢印をループで描画する
    Dim i, BeginX, BeginY, EndX, EndY
    Dim Arrow As Shape
    For i = 1 To LinesCount
    
        ' 描画する位置を計算
        BeginX = OffsetX
        BeginY = OffsetY + i * BasicUnitY
        
        EndX = OffsetX + LineLength
        EndY = BeginY
        
        '　直線を描画 → 形状を矢印に変更
        Set Arrow = ActiveSheet.Shapes.AddConnector( _
                            msoConnectorStraight, _
                            BeginX, BeginY, _
                            EndX, EndY _
                        )
        Arrow.Line.EndArrowheadStyle = msoArrowheadTriangle
    Next
End Sub
```

# 解説
## 図形(矢印)描画について

[Shapes.AddConnector メソッド][1]は(BeginX, BeginY) と (EndX, EndY) の二点を結ぶ線を描画します.

```
Addconnector(Type, BeginX, BeginY, EndX, EndY)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34777/442b784a-5cc5-6e44-a296-287548c51e3e.png)


| | |
|:--|:--|
|原点 (0, 0)|A1セルの左上の角(頂点)|
|X軸の方向|→ (右に行くほど増える)|
|Y軸の方向|↓ (下に行くほど増える)|
|単位|ポイント(pt)|

なので, BeginY = EndY となる値を設定すれば水平な線を引けます.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34777/b44029d3-5240-7f3f-a9b9-8df33e046525.png)

当初, 右クリックして出てくる「行の高さ」と「列の幅」を使おうとしましたが, どうやら[単位が違う](https://vbabeginner.net/%E3%83%9D%E3%82%A4%E3%83%B3%E3%83%88%E3%80%81%E3%83%94%E3%82%AF%E3%82%BB%E3%83%AB%E3%80%81%E3%82%A4%E3%83%B3%E3%83%81%E3%80%81%E3%82%BB%E3%83%B3%E3%83%81%E3%80%81%E3%83%9F%E3%83%AA%E3%81%AE%E7%9B%B8/#keni-toc1)(ポイントではない)ようです

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34777/1782a8bc-5d75-6c0e-3aa7-9ba78ee56192.png)

## セルの枠線の位置計算

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34777/5a2f2b41-e809-1718-62f8-6c1215610826.png)

| | |
|:--|:--|
|セルの幅|Cells(1, 1).Width|
|セルの高さ|Cells(1, 1).Height|

・・・という感じでセルから取得します.
セルから取得できる幅と高さ基本単位として, その整数倍で計算していけばちょうど枠線の位置になります.
コードは, すべて同じセルの高さ・幅だとしてCells(1, 1)の値を使いまわしていますが, そうでない場合はもう少し工夫が必要です.

```vb:コード抜粋
    ' 矢印の位置を計算する基準単位(BasicUnit).
    Dim BasicUnitX
    BasicUnitX = Cells(1, 1).Width
    
    Dim BasicUnitY
    BasicUnitY = Cells(1, 1).RowHeight

```

OffsetX, OffsetY, LineLength は, わかりやすく整数倍になっており, 

```vb:コード抜粋
    ' 矢印を描画する初期位置(Offset)
    Dim OffsetX
    OffsetX = BasicUnitX * 1
    
    Dim OffsetY
    OffsetY = BasicUnitY * 3
    
    ' 矢印の長さ
    Dim LineLength
    LineLength = BasicUnitX * 3
```

BeginX, BeginY, EndX, EndY も式変形すると整数倍になっていることがわかる.

```vb:コード抜粋
       ' 描画する位置を計算
        BeginX = OffsetX
        BeginY = OffsetY + i * BasicUnitY
        
        EndX = OffsetX + LineLength
        EndY = BeginY
```

BeginX = OffsetX = **1 * BasicUnitX**
BeginY = OffsetY + i * BasicUnitY = BasicUnitY * 3 + i * BasicUnitY = **(i + 3) * BasicUnitY**
EndX = OffsetX + LineLength = BasicUnitX * 1 + BasicUnitX * 3 = **4 * BasicUnitX**
EndY = BeginY = **(i + 3) * BasicUnitY**


# 拡張すればできそうなこと

- 矩形をセルの枠線に合わせて描画する
    - [できました](https://qiita.com/int_main_void/items/94e669e9de4dfaec6243)
- セルの幅や高さが一定でない場合でもセルの枠線に合わせて描画する

# 参考

[Shapes. AddConnector メソッド (Excel) - Microsoft Docs][1]
[図形などのオブジェクトをマウスだけで枠線に合わせて配置する方法 - Excelを制する者は人生を制す～No Excel No Life～][2]
[ポイント、ピクセル、インチ、センチ、ミリの相互変換 - Excel作業をVBAで効率化][3]

[3]:https://vbabeginner.net/%E3%83%9D%E3%82%A4%E3%83%B3%E3%83%88%E3%80%81%E3%83%94%E3%82%AF%E3%82%BB%E3%83%AB%E3%80%81%E3%82%A4%E3%83%B3%E3%83%81%E3%80%81%E3%82%BB%E3%83%B3%E3%83%81%E3%80%81%E3%83%9F%E3%83%AA%E3%81%AE%E7%9B%B8/
[2]:https://excel-master.net/graphics/object-match-frame-border/
[1]:https://docs.microsoft.com/ja-jp/office/vba/api/excel.shapes.addconnector