【VBA】Excelの表をMarkDownに変換する

私はプログラマーとして働いているのですが、現在働いている職場では

  • プログラムの設計書はExcel
  • プログラムのソース管理はGit

という管理をしています。似たような境遇の方は多いのではないでしょうか。

現代だとソース管理ソフトを使わないというのは生産性の面でもリスクの面でも欠点しかありません。SVNかGITを使うことになるかと思いますが、最近ではGITのほうが主流になってきていると思います。

プログラムの設計書については脱Excelをしている現場も多いのですが、まだまだExcelを使用している現場も多いです。

やはりExcelですと表の作成が簡単だし、オブジェクトを使用したりして視覚的にわかりやすい資料を作れるので重宝しますよね。

そんなわけで、個人的にExcelとGITの両方を使うことが増えています。

そんな状況下でExcel資料にある表をMarkDown記述にして記載したいということが何度かありました。同じような需要は多いのではないかと思ったので記事にしてみたいと思います。

選択した範囲をMarkDown形式に変換するVBA

MarkDownに変換するのはExcel式だけでは相当面倒なので、変換するVBAマクロを作成してみました。

仕様としては

  1. MarkDownに変換したい範囲を選択する
  2. VBAマクロを実行する
  3. A1セルに変換結果が出力される(1行目はヘッダーとして出力する)

としました。実行結果は以下のような形です。

コードは以下の通りです。

Public Sub toMarkDown()
    'A1に出力する
    Const OUTPUT_COLUMN = 1
    Const OUTPUT_ROW = 1
    
    '範囲が選択されてなかったら終了する
    If Selection.Count < 2 Then
        MsgBox "変換する範囲を選択してから実行してください"
        Exit Sub
    End If

    Dim first_row As Long
    Dim last_row As Long
    Dim first_column As Integer
    Dim last_column As Integer

    With Selection
        first_row = .row
        last_row = .Rows(.Rows.Count).row
        first_column = .Column
        last_column = .Columns(.Columns.Count).Column
    End With

    Dim row As Long
    Dim col As Integer
    Dim ret As String
    Dim header As String
    
    For row = first_row To last_row
        For col = first_column To last_column
            If col = first_column Then
                '最初のカラムはスペースを入れない
                ret = ret & "|  "
                header = "| "
            Else
                ret = ret & "  |  "
                header = header & "  |  "
            End If
            ret = ret & Cells(row, col).Value
            header = header & "----"
        Next col
        ret = ret & "  |" & vbLf
        '最初の列はヘッダーにする
        If row = first_row Then
            ret = ret & header & "  |" & vbLf
        End If
    Next row

    '結果を出力する
    Cells(OUTPUT_ROW, OUTPUT_COLUMN).Value = ret
End Sub

この形式はシンプルで使いやすいのが魅力ですね。

後から紹介する引数を使用するパターンだと引数が何であるか把握する必要があるため、自分以外は使いにくいかと思います。(他人に渡すときは不向き)

クリップボードに値を出力するパターン

上記で紹介したA1セルに値を出力するパターンだと少し不便なことがあります。それは以下2点です。

  • A1セルに値が出力されるので、A1セルは使用していないことを前提としなければいけない
  • セルの値をコピペしたときにExcelの仕様で「”」で文字列が囲まれる

特に2つ目が厄介で、そのままGITに張ろうとするとNGなので「”」を削除する操作が必要となります。(とはいえ10秒で終わる作業ですが…)

↓こんな感じでコピペされるが先頭と末尾の「”」が不要

それを改善するためにクリップボードに値を出力するパターンを作ってみました。

(ただ、個人的にはクリップボードの操作は謎のエラーも起きやすいので、あまりいい思い出がなく、使いたくはないのが本音です。)

まず使用にあたっては、「Microsoft Forms 2.0 Object Library」の参照が必要になります。参照追加が面倒なら1度ユーザフォームを挿入すれば自動で参照追加されます。

Public Sub toMarkDown()
    '範囲が選択されてなかったら終了する
    If Selection.Count < 2 Then
        MsgBox "変換する範囲を選択してから実行してください"
        Exit Sub
    End If

    Dim first_row As Long
    Dim last_row As Long
    Dim first_column As Integer
    Dim last_column As Integer

    With Selection
        first_row = .row
        last_row = .Rows(.Rows.Count).row
        first_column = .Column
        last_column = .Columns(.Columns.Count).Column
    End With

    Dim row As Long
    Dim col As Integer
    Dim ret As String
    Dim header As String
    
    For row = first_row To last_row
        For col = first_column To last_column
            If col = first_column Then
                '最初のカラムはスペースを入れない
                ret = ret & "|  "
                header = "| "
            Else
                ret = ret & "  |  "
                header = header & "  |  "
            End If
            ret = ret & Cells(row, col).Value
            header = header & "----"
        Next col
        ret = ret & "  |" & vbLf
        '最初の列はヘッダーにする
        If row = first_row Then
            ret = ret & header & "  |" & vbLf
        End If
    Next row

    'クリップボードに結果をを出力する
    With New MSForms.DataObject
        .SetText ret
        .PutInClipboard
    End With
End Sub


引数で選択範囲を指定するパターン

個人的に一番好きなのが、この引数を指定するパターンですね。やはり出力するセルを指定できるようになるのが汎用的でよいです。

欠点としては前述もしていますが、他人が使おうとしたときに使い方がわかりにくいということです。メッセージボックスなども使いにくいので、何故エラーなのかもわかりにくいです。

Public Function toMarkDown(targetRange As Range)
    '範囲が選択されてなかったら終了する
    If targetRange.Count < 2 Then
        toMarkDown = CVErr(xlErrValue)
        Exit Function
    End If

    Dim first_row As Long
    Dim last_row As Long
    Dim first_column As Integer
    Dim last_column As Integer

    With targetRange
        first_row = .row
        last_row = .Rows(.Rows.Count).row
        first_column = .Column
        last_column = .Columns(.Columns.Count).Column
    End With

    Dim row As Long
    Dim col As Integer
    Dim ret As String
    Dim header As String
    
    For row = first_row To last_row
        For col = first_column To last_column
            If col = first_column Then
                '最初のカラムはスペースを入れない
                ret = ret & "|  "
                header = "| "
            Else
                ret = ret & "  |  "
                header = header & "  |  "
            End If
            ret = ret & Cells(row, col).Value
            header = header &  "----"
        Next col
        ret = ret & "  |" & vbLf
        '最初の列はヘッダーにする
        If row = first_row Then
            ret = ret & header & "  |" & vbLf
        End If
    Next row

    toMarkDown = ret
End Function

使い方はExcelの式として「toMarkDown」呼び出して引数にMarkDownに変換したい範囲を指定するだけです。


コメントを残す

メールアドレスが公開されることはありません。

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)