Excel表をMarkdownへ変換
Markdownを知ってから、使いやすさからMarkdownでものを書くことが多くなり、勉強やアイディアのメモ、議事録などで使っていますが、表だけは書きづらく感じています。
そこで、Excelで表を作ってからMarkdownへ変換するプログラムが無いかと思って調べてみると、Javaなどの言語で書かれた変換のプログラムやWeb上で変換するサービスが見つかりましたが、自分の思うものが見つからなかったので、Excel VBAで自作することにしました。
作るにあたり下記の点に気をつけました。
簡単に使える
Excelで作成したあと、少ない手順で実行・変換できて、使いたい場所へのコピーが容易であるということです。ネットワークを必要としない
ノートパソコンを外で使っているとネットワークが無い環境が意外と多くあります。 Free Wi-Fiはセキュリティ面が心配です。 Excel VBAであれば基本的に問題ありません。簡単に移植できる
プログラムのコードをコピー&ペーストするだけで使えるようになるのが理想です。 UserFormは使わないようにします。
変換結果をクリップボードに保存するということを考えたのですが、その部分が一番大変でした。
検索するとDataobjectを使う方法が多く出てきますが、環境によりうまく動かないことがあるようです。
また、Microsoft Forms 2.0 Object Libraryを参照設定する必要がありますが、参照リストに通常では表示されず、パスでDLLを指定しなくてはならないということで、移植性が悪いと感じました。
そこで、msdnのページを参考に、Windows APIを使うことにしました。
Send Information to the Clipboard
下記コードをモジュールに貼り付けExportMarkdownを実行すると、アクティブシートにある表がMarkdownに変換されてクリップボードに保存されます。
使用の流れとしては下記3手順で変換することができます。
(プログラムが標準Moduleに書かれているExcelを使用している前提です)
- Excelで表を作る
- ExportMarkdownを実行する
- マークダウンを使いたい場所に貼り付けする
使用する際にいくつか条件があります。
- alignは一番上の行で決まる(標準の場合は中央揃え)
- 表は罫線が無くても使用できる
- 表の位置はどこにあっても認識する。
- シート内に存在する表は一つまで
- 余分な文字や罫線があると誤認識する
- 結合されたセルには非対応
usedRangeでうまく範囲が取得できる表であれば問題ありません。
Worksheet.UsedRange プロパティ (Excel)
細かい説明は省略しますが、大まかには下記4つを行っています。
また、クリップボードにセットする部分は参考ページのプログラムをそのまま使っています。
Option Explicit 'information-to-the-clipboard Private Declare Function OpenClipboard Lib "user32.dll" (ByVal hWnd As Long) As Long Private Declare Function EmptyClipboard Lib "user32.dll" () As Long Private Declare Function CloseClipboard Lib "user32.dll" () As Long Private Declare Function SetClipboardData Lib "user32.dll" (ByVal wFormat As Long, ByVal hMem As Long) As Long Private Declare Function GlobalAlloc Lib "kernel32.dll" (ByVal wFlags As Long, ByVal dwBytes As Long) As Long Private Declare Function GlobalLock Lib "kernel32.dll" (ByVal hMem As Long) As Long Private Declare Function GlobalUnlock Lib "kernel32.dll" (ByVal hMem As Long) As Long Private Declare Function lstrcpy Lib "kernel32.dll" Alias "lstrcpyW" (ByVal lpString1 As Long, ByVal lpString2 As Long) As Long Sub ExportMarkdown() Dim usedRange As Range Set usedRange = ActiveSheet.usedRange Dim columnMin As Long Dim columnMax As Long columnMin = usedRange.Column columnMax = columnMin + usedRange.Columns.Count - 1 Dim rowMin As Long Dim rowMax As Long rowMin = usedRange.Row rowMax = rowMin + usedRange.Rows.Count - 1 Dim i As Long, j As Long Dim exportStr As String 'Check header alignment For i = rowMin To rowMax If i = rowMin + 1 Then For j = columnMin To columnMax Select Case Cells(i, j).HorizontalAlignment Case xlRight exportStr = exportStr & "|---:" Case xlLeft exportStr = exportStr & "|:---" Case xlCenter exportStr = exportStr & "|:---:" Case Else exportStr = exportStr & "|:---:" End Select Next exportStr = exportStr & "|" & vbCrLf End If exportStr = exportStr & "|" For j = columnMin To columnMax exportStr = exportStr & Cells(i, j).Value & "|" Next exportStr = exportStr & vbCrLf Next Call SetClipboard(exportStr) End Sub Public Sub SetClipboard(sUniText As String) Dim iStrPtr As Long Dim iLen As Long Dim iLock As Long Const GMEM_MOVEABLE As Long = &H2 Const GMEM_ZEROINIT As Long = &H40 Const CF_UNICODETEXT As Long = &HD OpenClipboard 0& EmptyClipboard iLen = LenB(sUniText) + 2& iStrPtr = GlobalAlloc(GMEM_MOVEABLE Or GMEM_ZEROINIT, iLen) iLock = GlobalLock(iStrPtr) lstrcpy iLock, StrPtr(sUniText) GlobalUnlock iStrPtr SetClipboardData CF_UNICODETEXT, iStrPtr CloseClipboard End Sub
名前 | 直径 (km) | 表面重力(m/s2) | 公転周期(年) | 自転周期(日) |
---|---|---|---|---|
太陽 | 1392038 | 274 | - | 27.275 |
水星 | 4879.4 | 3.7 | 0.241 | 58.65 |
金星 | 12103.6 | 8.87 | 0.615 | 243.0187 |
地球 | 12756.3 | 9.78 | 1 | 0.997271 |
火星 | 6794.4 | 3.71 | 1.881 | 1.02595 |
木星 | 142984 | 24.79 | 11.86 | 0.4135 |
土星 | 120536 | 8.96 | 29.46 | 0.4264 |
天王星 | 51118 | 7.77 | 84.01 | 0.7181 |
海王星 | 49572 | 11 | 164.79 | 0.6712 |
これでMarkdownで表を書くのが少し楽になりそうです。
使っていく上で使いにくい部分があれば、改善していこうと思います。