私はプログラマーとして働いているのですが、現在働いている職場では
- プログラムの設計書はExcel
- プログラムのソース管理はGit
という管理をしています。似たような境遇の方は多いのではないでしょうか。
現代だとソース管理ソフトを使わないというのは生産性の面でもリスクの面でも欠点しかありません。SVNかGITを使うことになるかと思いますが、最近ではGITのほうが主流になってきていると思います。
プログラムの設計書については脱Excelをしている現場も多いのですが、まだまだExcelを使用している現場も多いです。
やはりExcelですと表の作成が簡単だし、オブジェクトを使用したりして視覚的にわかりやすい資料を作れるので重宝しますよね。
そんなわけで、個人的にExcelとGITの両方を使うことが増えています。
そんな状況下でExcel資料にある表をMarkDown記述にして記載したいということが何度かありました。同じような需要は多いのではないかと思ったので記事にしてみたいと思います。
選択した範囲をMarkDown形式に変換するVBA
MarkDownに変換するのはExcel式だけでは相当面倒なので、変換するVBAマクロを作成してみました。
仕様としては
- MarkDownに変換したい範囲を選択する
- VBAマクロを実行する
- 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に変換したい範囲を指定するだけです。
コメントを残す