VBAは言語なのか？VBAでアルゴリズムを書いてみた

[デフエンジニアの会アドベントカレンダー](https://qiita.com/advent-calendar/2022/deafengineers)15日目の記事です。

デフエンジニアの会はデフ（＝ろう・難聴）のエンジニア、また、聴者（＝耳が聴こえる人）エンジニアで構成されているグループです。
WEB分野はエンジニアだけでなくデザイナーも兼任している人もいることからデザイナーも一部います。

そして私は今はVBAで仕事をしています。
その中でVBAを通して色々と思うことがあるので今日はこれについて書いていこうと思います。

# VBAは言語なのか？
これはよく言われるのですが、「VBAはプログラミングとは言えない」「そもそも言語なのか」という・・・いわゆるプログラミング界でもVBAへの「見下し」みたいなことがあるようです。
そして実は私も、かつては「VBAなんて・・」という気持ちがありました。
C言語やPHPやPythonの方がかっこいい、VBAはダサい・・なんて思っていた時期もありました。

ですが、今はそうは思っていません。
その理由を書いていきます。

## VBAが見下されがちな理由

そもそもなぜ見下されがちなのか書いていきます。
まず、VBAは「Excelのめんどくさい作業をちょっと補うためだけにコードを書いている」と思われてしまいがち、またExcelでしか使えないためそこから「VBAはちょっと勉強すれば簡単に身に着く」「だからVBAはプログラミングとは言えない」という考え方に繋がるのではと思いました。（しつこいですが私も前はそう思っていました・・）

しかし、本当にそうでしょうか？

### VBAは意外と複雑である

そもそもVBAはExcelに特化した言語で、主にExcelを使った作業を自動化させるために使うものです。
そしてそこから実に様々なことができるのです。

例えば

- ExcelからPDF・Outlook・Word文書を出力可能
- ExcelからAccessに繋げてデータ出力、更にSQLを使ってデータ調整もVBA内で可能
- 複数ファイルを添付したOutlookメールを作成し送信も可能
- [VBAでDiff比較ツールみたいなものも作れる](https://qiita.com/mamineko/items/14e3eb424b8c5d82f1e7)

など、Microsoft系アプリケーションとも連携してあらゆることができます。
また他にも

- [VBAでスクレイピングも可能](https://qiita.com/aozora_blue/items/f9f9e54da9b9306871ac)
- 工学計算もVBAで実現可能
- WEBAPIと連携しあらゆるデータの取得も可能

などなど、実に色々なことができるようになっています。

また、コーディングも多岐にわたり本当にいろいろな知識も必要になってきます。
もちろん配列にしても多次元配列、二次元配列、などがありそれもVBAで書くことができます。

ここまでくれば、もう「VBAは言語ではない」「VBAはプログラミングではない」とは言えないのではと思います。

### VBAのメリット

そしてVBAのメリットは、何よりも「作業の効率化ができる」ということです。
また「データ分析」も勉強しておけば、VBAとデータ分析を連携させてあらゆるデータ分析も可能になってきますし、業務の幅も広がっていきます。

これを知ってから、私はもう他の言語をうらやましいと思うことなくVBAを究めてみようと思うようになりました！

折りしも今はRPAや業務自動化系の仕事も増えてきているので、これを機にVBAに挑戦するのも良いかと思います！
おすすめです。

### それでもVBAは言語ではないというのなら

基本的に、どんなプログラミング言語にも「アルゴリズム」は存在します。
言い換えれば、アルゴリズムが組み立てられないと「言語とは言えない」のではと思っています（私の勝手なこじつけです・・）

そこで、VBAでアルゴリズムが書けるかどうかに挑戦してみることにしました！
（強引な書き方ですみません）

## VBAでアルゴリズムを書いてみた

では前置きが長くなってしまいましたが、最後にVBAでアルゴリズムを書くことに挑戦してみます！

以前、デフエンジニアの会では「輪読会」という企画で「Pythonではじめるアルゴリズム入門」という本を使ってアルゴリズムの勉強をしたことがあります。

その本をもとにVBAでアルゴリズムを書いてみる、というのをやってみます。
ここではアルゴリズムの中でも有名な「探索アルゴリズム」を取りあげていきます。

### VBAで探索アルゴリズムを書いてみよう

**探索アルゴリズム**
データの中から条件に合った要素を取り出してくる操作のこと。
そしてこの探索アルゴリズムには2種類あり、１つが「線形探索」でもう一つが「2分探索」です。

**1. 線形探索**

例えば以下画像内で数字が色々と入っているとします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/772852/8d134d5b-2fcb-0b29-715e-8eb72e3de619.png)

その中で「５」がどこにあるか探したい、とします。

すると通常は上から順番にセル内の値を参照し、５であるかどうかを1つずつ探していきます。
これと同じ考えで作られたアルゴリズムが探索アルゴリズムの種類の１つ、「線形探索」です。
1つずつ順番に探していくということで単純なアルゴリズムとして知られています。

ではこれをコードで実現してみましょう。

```vb
Option Explicit

Sub test1()

Dim ws As Worksheet
Dim iLast As Integer
Dim icnt As Integer
Dim strValue As String

    Set ws = ThisWorkbook.Worksheets("Sheet1")
    strValue = 5
    
    '最終行チェック
    iLast = ws.Cells(Rows.Count, 1).End(xlUp).Row

    'Forループで上から１行ずつセル内の値を参照しながら「５」があるかチェック
    '「５」があればセルの場所をメッセージに出して終了
    For icnt = 1 To iLast
        If ws.Cells(icnt, 1).Value = strValue Then
            Debug.Print "（"; ws.Cells(icnt, 1).Address(False, False); "）にありました"
            Exit Sub
        End If
    Next
    
    Debug.Print "見つかりませんでした。"
    
End Sub

```

**解説**

このコードはこの順序で処理を指示しています。

①シート取得
②探索したい値をセット
③最終行取得
④Forループで上１行目から順番に１つずつ値を参照
⑤もし見つかれば、値が存在した場所をメッセージ出力
 もし見つからなければ、「見つかりませんでした」というメッセージ出力
⑥処理終了

という流れです。

この書き方だと線形探索が可能です。
では次に二分探索ではどう書くのかを書いてみます。

**2. 二分探索**

先ほどの線形探索では、上から１つずつ値を探して・・ということでしたが、二分探索はざっくりと２つに割って、まず１つ目で対象値を探します。
そしてそこになければ２つ目で対象値を探していくというものです。

**二分探索のメリット**

まず「データ量が多い時」に探す手間が省けるというものですが、
特に２つに分けて最初の１つ目ですぐデータが見つかればその分処理も早くなる、という大きなメリットがあります。

従ってこのやり方も覚えておいて損はないアルゴリズムだとも言えます。

では実際にコードを書いてみます。

```vb
Sub test2()

Dim ws As Worksheet

Dim icnt As Integer
Dim strValue As String
Dim istart As Integer
Dim imiddle As Integer
Dim iLast As Integer

    Set ws = ThisWorkbook.Worksheets("Sheet1")
    strValue = 5
    
    '最終行チェック
    iLast = ws.Cells(Rows.Count, 1).End(xlUp).Row
    
    istart = 1
    Do
        If imiddle = istart + ((iLast - istart) \ 2) Then
            Debug.Print "みつかりませんでした。"
            Exit Do
        End If
        
        imiddle = istart + ((iLast - istart) \ 2)
        If ws.Cells(imiddle, 1).Value > strValue Then
            iLast = imiddle
        ElseIf ws.Cells(imiddle, 1).Value < strValue Then
            istart = imiddle
        Else
            Debug.Print "（"; ws.Cells(imiddle, 1).Address(False, False); "）にありました"
            Exit Do
        End If
    Loop
End Sub
```

**解説**

①シート取得
②探索したい値をセット
③最終行取得
④まず真ん中で割って真ん中のセル行数を取得
⑤最初の行数から真ん中の行数までの値をチェックし、見つかればセルの場所をメッセージ出力し処理終了
 もし見つからなければ、真ん中の行数から最後の行数までの値をチェック
⑥見つかれば、セルの場所をメッセージ出力
⑥処理終了

という流れです。

この書き方だと二分探索が可能です。



## まとめ

VBAでもアルゴリズムが書けることが分かったので、VBAは言語である、と言えます（強引ですが・・）
ともかく、VBAを仕事としている身としては、VBAは甘く見てはいけないと思っていますし、実際私自身まだまだ勉強が必要だと思っています。

それでは長くなりましたが、これで終わります。

あとデフエンジニアの会応援してもらえると嬉しいです！！