Copilotを使ったらExcelのマクロが簡単に作成できた話

## はじめに

仕事でExcelを使う方、非常に多いと思うのですが、ちょっとした作業を自動化したいことがよくあると思います。特定のデータを一斉に修正するとか、シート間でデータをコピーしたり結合したりとか。

そういった作業を自動化できるのがExcelのマクロなのですが、**なんとなく敷居が高そう**で使っていない方、多いと想像します。かく言う私自身もそうでした。<br>
（プログラミングの素養はあると自負していますが、新しい言語を覚えるのは壁があるし何よりコードを書く時間がもったいない、と思ってしまいます。）

これを解決するのが今や当たり前の技術になった生成AIです。とはいえ、以前は「生成AIってプロンプトの書き方とかちゃんとわかってないといけないんじゃないの？」とか考えてあまり使っていませんでした。ところが、仕事中にExcelの作業が面倒に感じたときに生成AIを使ってみたところ思いの外簡単だったので、その経験を共有したいと思いこの記事を書きました。

使った生成AIは**Microsoft Copilot**です。Copilotに何を入力して、どんな出力が得られて、それをどのように活用したかを簡単に解説していきたいと思います。<br>
マクロで自動化した作業は以下2点です。
* 自動化した作業①：箇条書きのフォーマット修正
* 自動化した作業②：シート間のテーブル結合


## 自動化した作業①：箇条書きのフォーマット修正
Excelに表形式で検討事項をまとめていて、とある列を以下の列２のように箇条書きチックにメモを書いていました。

| 列１ | 列２ | 列３ |
|-----------:|:------------|:------------:|
| … |・あああ<br>-いいい<br>␣-ううう| … |
| … |・かかか<br>-ききき<br>␣-くくく| … |
| … |・さささ<br>-ししし<br>␣-すすす| … |

このような書き方だと1段目と2段目でインデントが同じになってしまい階層がわかりにくくなります。最初からこの書き方を避けていれば何の問題もなかったのですが、気づいたときにはすでに数十行ほど書いてしまっていました。

そこで、これを以下のような形式に直すことにしました。

| 列１ | 列２ | 列３ |
|-----------:|:------------|:------------:|
| … |・あああ<br>␣-いいい<br>␣␣-ううう| … |
| … |・かかか<br>␣-ききき<br>␣␣-くくく| … |
| … |・さささ<br>␣-ししし<br>␣␣-すすす| … |

箇条書き2段目と3段目の文頭にスペースを入れて1段目とのインデントの違いがはっきりわかるようにしています。一斉置換で対応しようとすると、文中の'‐'にもスペースが入ってしまうのでマクロで対応することにしました。

Copilotにはまず以下のようにお願いをしてみました。

```
箇条書きを以下のように変換するExcelマクロを生成して

===変換前===
・あああ
-いいい
　-ううう
======

===変換後===
・あああ
　-いいい
　　-ううう
==========
```

結果、以下の回答が返ってきました。

```
もちろんです！以下のExcelマクロを使用して、箇条書きを指定の形式に変換できます。

vba
Sub ConvertBullets()
    Dim rng As Range
    Dim cell As Range
    Dim text As String
    Dim newText As String
    
    ' 選択範囲を設定
    Set rng = Selection
    
    ' 選択範囲内の各セルを処理
    For Each cell In rng
        text = cell.Value
        newText = Replace(text, "・", "・" & vbCrLf & "　-")
        cell.Value = newText
    Next cell
End Sub


このマクロは、選択したセルの内容を変換し、「・」の後に改行とインデントを追加します。使い方は以下の通りです：

1. Excelでマクロを追加するために、Alt + F11を押してVBAエディタを開きます。
2. 「挿入」メニューから「モジュール」を選択し、新しいモジュールを作成します。
3. 上記のコードをコピーして、新しいモジュールに貼り付けます。
4. VBAエディタを閉じて、Excelに戻ります。
5. マクロを実行したいセル範囲を選択し、Alt + F8を押して「ConvertBullets」マクロを実行します。

これで、箇条書きが指定の形式に変換されます。何か他にお手伝いできることがあれば教えてください！
```

この回答を読むと、'・'の後に改行とインデントを追加しておりこちらの意図とは違うことがわかります。そこで次に以下のお願いをしてみました。

```
"・"ではなく"-"の前にインデントを追加して
```

```
了解しました！以下のExcelマクロを使用して、"-"の前にインデントを追加するように変更しました。

Sub ConvertBullets()
    Dim rng As Range
    Dim cell As Range
    Dim text As String
    Dim newText As String
    
    ' 選択範囲を設定
    Set rng = Selection
    
    ' 選択範囲内の各セルを処理
    For Each cell In rng
        text = cell.Value
        newText = Replace(text, "-", "　-")
        cell.Value = newText
    Next cell
End Sub
このマクロは、選択したセルの内容を変換し、"-"の前にインデントを追加します。使い方は以下の通りです：

Excelでマクロを追加するために、Alt + F11を押してVBAエディタを開きます。
「挿入」メニューから「モジュール」を選択し、新しいモジュールを作成します。
上記のコードをコピーして、新しいモジュールに貼り付けます。
VBAエディタを閉じて、Excelに戻ります。
マクロを実行したいセル範囲を選択し、Alt + F8を押して「ConvertBullets」マクロを実行します。
これで、"-"の前にインデントが追加されます。何か他にお手伝いできることがあれば教えてください！
```

これだと全ての'-'にインデントが追加されてしまうので、更に以下の通りにお願いをしてみました。

```
行頭の"-"だけインデントを追加して
```

このお願いをしてから、既にインデントが追加されている行にインデントが追加されないことに気づき、さらに以下のお願いをしました。

```
行頭が"　-"の場合もインデントを追加してほしい
```

この回答が以下です。

```
了解しました！以下のExcelマクロを使用して、行頭が"　-"の場合もインデントを追加するように変更しました。

Sub ConvertBullets()
    Dim rng As Range
    Dim cell As Range
    Dim text As String
    Dim newText As String
    Dim lines As Variant
    Dim i As Integer
    
    ' 選択範囲を設定
    Set rng = Selection
    
    ' 選択範囲内の各セルを処理
    For Each cell In rng
        text = cell.Value
        lines = Split(text, vbLf)
        newText = ""
        
        ' 各行を処理
        For i = LBound(lines) To UBound(lines)
            If Left(Trim(lines(i)), 1) = "-" Or Left(Trim(lines(i)), 2) = "　-" Then
                lines(i) = "　" & Trim(lines(i))
            End If
            newText = newText & lines(i) & vbLf
        Next i
        
        ' 最後の改行を削除
        newText = Left(newText, Len(newText) - 1)
        
        cell.Value = newText
    Next cell
End Sub
このマクロは、行頭が"-"または"　-"の場合にインデントを追加します。使い方は以下の通りです：

Excelでマクロを追加するために、Alt + F11を押してVBAエディタを開きます。
「挿入」メニューから「モジュール」を選択し、新しいモジュールを作成します。
上記のコードをコピーして、新しいモジュールに貼り付けます。
VBAエディタを閉じて、Excelに戻ります。
マクロを実行したいセル範囲を選択し、Alt + F8を押して「ConvertBullets」マクロを実行します。
これで、行頭が"-"または"　-"の場合にインデントが追加されます。何か他にお手伝いできることがあれば教えてください！

```

おそらくこれでいけるだろうと思ってCopilotの回答にある通りの手順でマクロを実行したところ、以下の通りになりました。

| 列１ | 列２ | 列３ |
|-----------:|:------------|:------------:|
| … |・あああ<br>␣-いいい<br>␣-ううう| … |
| … |・かかか<br>␣-ききき<br>␣-くくく| … |
| … |・さささ<br>␣-ししし<br>␣-すすす| … |

3行目にインデントが追加されていませんね…

そこで再度Copilotに以下のお願いをしました。

```
"　-"の場合にインデントが追加されません。何か間違っていませんか？
```

```
申し訳ありません。コードを修正して、行頭が"　-"の場合にもインデントが追加されるようにします。以下の修正されたマクロをお試しください。

Sub ConvertBullets()
    Dim rng As Range
    Dim cell As Range
    Dim text As String
    Dim newText As String
    Dim lines As Variant
    Dim i As Integer
    
    ' 選択範囲を設定
    Set rng = Selection
    
    ' 選択範囲内の各セルを処理
    For Each cell In rng
        text = cell.Value
        lines = Split(text, vbLf)
        newText = ""
        
        ' 各行を処理
        For i = LBound(lines) To UBound(lines)
            If Left(Trim(lines(i)), 1) = "-" Then
                lines(i) = "　" & Trim(lines(i))
            ElseIf Left(Trim(lines(i)), 2) = "　-" Then
                lines(i) = "　" & Trim(lines(i))
            End If
            newText = newText & lines(i) & vbLf
        Next i
        
        ' 最後の改行を削除
        newText = Left(newText, Len(newText) - 1)
        
        cell.Value = newText
    Next cell
End Sub
このマクロは、行頭が"-"または"　-"の場合にインデントを追加します。使い方は以下の通りです：

Excelでマクロを追加するために、Alt + F11を押してVBAエディタを開きます。
「挿入」メニューから「モジュール」を選択し、新しいモジュールを作成します。
上記のコードをコピーして、新しいモジュールに貼り付けます。
VBAエディタを閉じて、Excelに戻ります。
マクロを実行したいセル範囲を選択し、Alt + F8を押して「ConvertBullets」マクロを実行します。
これで、行頭が"-"または"　-"の場合にインデントが追加されるはずです。再度お試しいただけますか？何か他にお手伝いできることがあれば教えてください！
```

これを実行したところ、ついにこちらが意図したとおりの修正ができました！<br>
間違ってる原因を自分で探さなくても、「何か間違ってませんか？」と聞いただけで正しく修正してくれるのはありがたい限りです。<br>
今回はここまでで終わりにしましたが、3行目を"+"などの別の記号に変える等の処理も簡単にできそうですね。

### ①を終えての感想

何度もやり取りを重ねていて効率悪く見えるかもしれませんが、実際にやってみるととても効率的な感覚があります。ポイントとしては以下が挙げられます。

1. 会話のように、思ったことをそのままお願いしても通じる。
2. ゴールに確実に近づいている感覚がある。
3. 言語を全く知らなくてもコードが書ける。

1.については上記のやり取りをみてわかる通り、「こうしてほしいな」という考えをそのまま直感的に入力してもちゃんと理解してくれます。こちらの考えを整理したり、入力のフォーマットを整えたりといった事前準備が何もいらないのでCopilotを使う敷居が物凄く低いです。

2.についてはこの記事だけを見ると何度もやり取りをしていて手間に見えるかもしれません。しかし、ググって効率的なやり方を見つけたとしても、いざ試すと上手くいかずまた振り出しに戻るということは少なくありません。Copilotだとちょっと違う回答だとしても「それは違う」と伝えれば理解してゴールに近づいてくれる感覚があります。

3.はプログラミングの素養がある方なら共感頂けると思いますが、コードが「読めるけど書けない」ことがあると思います。書くには文法を理解していないといけないのですが、読むだけなら他の言語の知識を応用して読めるはずです。更に、読めればちょっと書き換えるぐらいのことはできます。

## 自動化した作業②：シート間のテーブル結合

複数のシートでテーブルデータを整理していて、それぞれのIDを紐づけてテーブルを結合したいときがありました。やりたいことのイメージは以下のテーブル１とテーブルAのデータを合わせてテーブル１Aを作りたいというものです。

**テーブル１**
| ID | データ１ | データ２ |
|-----------:|:------------|:------------|
| 001 |あああ| いいい |
| 002 |かかか| ききき |
| 003 |さささ| ししし |

**テーブルA**
| ID | データA | データB |
|-----------:|:------------|:------------|
| 001 |A| B |
| 002 |AA| BB |
| 003 |AAA| BBB |

**テーブル１A**
| ID | データ１ | データ２ | データA | データB |
|-----------:|:------------|:------------|:------------|:------------|
| 001 |あああ| いいい |A| B |
| 002 |かかか| ききき |AA| BB |
| 003 |さささ| ししし |AAA| BBB |


この作業はマクロを作らなくてもVLOOKUP関数で実現可能です。今回はマクロ作成の実験を兼ねてマクロでやりましたが、VLOOKUP関数を使う場合は最初の問いを「ExcelのSheet1に対してSheet2の同じIDのデータを結合する関数を教えて」にすると良さそうです。

Copilotにはまず以下の通りに聞いてみました。Sheet1にテーブル１、Sheet2にテーブルAが記載されている想定です。

```
ExcelのSheet1に対してSheet2の同じIDのデータを結合するマクロを生成して
```

```
もちろんです！ExcelのVBAを使って、Sheet1とSheet2の同じIDのデータを結合するマクロを作成します。以下のコードをExcelのVBAエディタに貼り付けてください。

Excelを開き、Alt + F11キーを押してVBAエディタを開きます。
「挿入」メニューから「モジュール」を選択して、新しいモジュールを追加します。
以下のコードを新しいモジュールに貼り付けます。

Sub MergeSheetsByID()
    Dim ws1 As Worksheet
    Dim ws2 As Worksheet
    Dim wsResult As Worksheet
    Dim idRange1 As Range
    Dim idRange2 As Range
    Dim cell As Range
    Dim foundCell As Range
    Dim lastRow1 As Long
    Dim lastRow2 As Long
    Dim resultRow As Long

    ' シートの設定
    Set ws1 = ThisWorkbook.Sheets("Sheet1")
    Set ws2 = ThisWorkbook.Sheets("Sheet2")
    Set wsResult = ThisWorkbook.Sheets.Add(After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
    wsResult.Name = "MergedData"

    ' ID列の範囲を設定（ここではA列をID列と仮定）
    lastRow1 = ws1.Cells(ws1.Rows.Count, "A").End(xlUp).Row
    lastRow2 = ws2.Cells(ws2.Rows.Count, "A").End(xlUp).Row
    Set idRange1 = ws1.Range("A2:A" & lastRow1)
    Set idRange2 = ws2.Range("A2:A" & lastRow2)

    ' ヘッダーをコピー
    ws1.Rows(1).Copy Destination:=wsResult.Rows(1)
    ws2.Rows(1).Copy Destination:=wsResult.Rows(1).Offset(0, ws1.Columns.Count)

    resultRow = 2

    ' Sheet1のデータをSheet2のデータと結合
    For Each cell In idRange1
        Set foundCell = idRange2.Find(What:=cell.Value, LookIn:=xlValues, LookAt:=xlWhole)
        If Not foundCell Is Nothing Then
            ' IDが一致する行を結合
            ws1.Rows(cell.Row).Copy Destination:=wsResult.Rows(resultRow)
            ws2.Rows(foundCell.Row).Copy Destination:=wsResult.Rows(resultRow).Offset(0, ws1.Columns.Count)
            resultRow = resultRow + 1
        End If
    Next cell

    MsgBox "データの結合が完了しました！", vbInformation
End Sub

このマクロは、Sheet1とSheet2のID列（A列）を基にデータを結合し、新しいシート「MergedData」に結果を出力します。必要に応じて、ID列やデータ範囲を変更してください。

何か他にお手伝いできることがあれば教えてくださいね！
```

出力の最後にあるように、このマクロはシート名がSheet1とSheet2、ID列をA列と仮定して作られています。なのでシート名やID列の部分については自分で修正する必要があります。

このマクロを実行してみたのですが、結果はエラーになりました。原因はわからなかったですが「結合」の意図するところがずれているかもと思い、お願いをより具体的にしてみました。

```
エラーが出ます。Sheet1とSheet2で同じIDのデータについて、Sheet2のID以外の列をSheet1に追加してほしいです。
```

```
了解しました。Sheet1とSheet2で同じIDのデータを見つけ、Sheet2のID以外の列をSheet1に追加するマクロを作成します。以下のコードを試してみてください。

Sub MergeSheetsByID()
    Dim ws1 As Worksheet
    Dim ws2 As Worksheet
    Dim idRange1 As Range
    Dim idRange2 As Range
    Dim cell As Range
    Dim foundCell As Range
    Dim lastRow1 As Long
    Dim lastRow2 As Long
    Dim lastCol1 As Long
    Dim lastCol2 As Long
    Dim resultRow As Long

    ' シートの設定
    Set ws1 = ThisWorkbook.Sheets("Sheet1")
    Set ws2 = ThisWorkbook.Sheets("Sheet2")

    ' ID列の範囲を設定（ここではA列をID列と仮定）
    lastRow1 = ws1.Cells(ws1.Rows.Count, "A").End(xlUp).Row
    lastRow2 = ws2.Cells(ws2.Rows.Count, "A").End(xlUp).Row
    lastCol1 = ws1.Cells(1, ws1.Columns.Count).End(xlToLeft).Column
    lastCol2 = ws2.Cells(1, ws2.Columns.Count).End(xlToLeft).Column
    Set idRange1 = ws1.Range("A2:A" & lastRow1)
    Set idRange2 = ws2.Range("A2:A" & lastRow2)

    ' Sheet2のID以外の列をSheet1に追加
    For Each cell In idRange1
        Set foundCell = idRange2.Find(What:=cell.Value, LookIn:=xlValues, LookAt:=xlWhole)
        If Not foundCell Is Nothing Then
            ' IDが一致する行のデータを結合
            ws2.Range(ws2.Cells(foundCell.Row, 2), ws2.Cells(foundCell.Row, lastCol2)).Copy
            ws1.Cells(cell.Row, lastCol1 + 1).PasteSpecial Paste:=xlPasteValues
        End If
    Next cell

    Application.CutCopyMode = False
    MsgBox "データの結合が完了しました！", vbInformation
End Sub

このマクロは、Sheet1とSheet2のID列（A列）を基にデータを結合し、Sheet2のID以外の列をSheet1に追加します。必要に応じて、ID列やデータ範囲を変更してください。

エラーが出た場合や他に質問があれば教えてくださいね。
```

こちらのマクロでシート名とID列を変えたところ、データの結合に成功しました！

マクロで書き換えた部分は以下の2行です。一つ目のシートでID列をC列にしていたので、ID列指定部分を書き換えています。
```
lastRow1 = ws1.Cells(ws1.Rows.Count, "C").End(xlUp).Row

Set idRange1 = ws1.Range("C2:C" & lastRow1)
```

シート名についてはマクロはそのままでExcelのシート名をSheet1とSheet2に変更しました。

### ②を終えての感想

2回のやり取りでこちらのほしいマクロが手に入ったので一つ目と比べるととても楽でした。ただし、シート名やID列についてマクロのどの部分を変更すればよいのかわかる程度のプログラミングスキルは必要かと思います。基礎知識が全くないと流石に難しそうです。

## おわりに

CopilotでExcelマクロを簡単に生成できた、という私の経験をご紹介しました。Excelに詳しい方にとってはCopilotに聞くほどのことではないかもしれません。しかし、私にとってはこれまで避けていたExcelマクロへの抵抗がさっぱり無くなったという意味で物凄く大きな収穫でした。一つ目の感想にも書いたのですが、やり取りを繰り返す中で少しづつゴールに近づいている感覚があるのが良いところだと感じました。<br>
今回はCopilotを使いましたが、Copilot以外の生成AIでも似たようなことは簡単にできると思います。Excelマクロに限らず、ちょっとわからないこと、ちょっと困っていることがあったら「生成AIを使ってみよう」という発想を持つことが大事なのではと思いました。