Excelの表を markdownの表に変換するマクロ

# はじめに

時どき、Excelの表をmarkdownに変換することがあります。これまでは、手作業でExcelやテキストエディタで加工していましたが、一発で変換できるExcelマクロを作りました。

# 使い方

前提とするExcelシートは、左上（A1セル）から始まる一連のデータです。

![before.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/145b6585-04c8-a29e-304e-2e81948ce59f.png)

このシートに、後述するマクロを実行すると、↓このように加工します。

![after.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/879e889c-7cdc-6181-15fc-f5666e5672e1.png)

マクロの最後で加工後のデータをクリップボードにコピーします。
これを貼り付けると、以下のようなテキストになります。
（一緒にイメージもコピーされることがあります）

```markdown
|	Col A	|	Col B	|	Col C	|	Col D	|
|	:-:	|	:-:	|	:-:	|	:-:	|
|	Row 2	|	Cell B2	|	Cell C2	|	Cell D2	|
|	Row 3	|	Cell B3	|	Cell C3	|	Cell D3	|
```

<b>中央揃え</b>になっているので、必要により、右寄せ・左寄せに変更します。

|	Col A	|	Col B	|	Col C	|	Col D	|
|	:-:	|	:-:	|	:-:	|	:-:	|
|	Row 2	|	Cell B2	|	Cell C2	|	Cell D2	|
|	Row 3	|	Cell B3	|	Cell C3	|	Cell D3	|


:::note alert
`テーブル`になっていると、正しく動作しません。
その場合は「`値のコピー`」で別シートにデータのみコピーして使ってください。

![table.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/5122747e-e652-ee21-e42f-66264575cd62.png)
:::

# Excelマクロ

Windows でも Mac でも動きます。
ActiveWorkbook - ActiveSheet が加工対象。

```vb
Sub TableToMarkdown()
    Dim r As Long, c As Long
    Dim lastRow As Long, lastCol As Long
    
    'テーブルならExit
    Dim lst As ListObject
    Set lst = Cells(1, 1).ListObject
    If Not (lst Is Nothing) Then Exit Sub
    
    Rows(2).Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove

    lastRow = Cells(Rows.Count, 1).End(xlUp).Row
    lastCol = Cells(1, Columns.Count).End(xlToLeft).Column
    
    For c = 1 To lastCol
        Cells(2, c) = ":-:"
    Next
    
    For r = 1 To lastRow
        Cells(r, lastCol + 1) = "|"
    Next
    
    For c = lastCol + 1 To 2 Step -1
        Columns(c).Copy
        Columns(c - 1).Insert Shift:=xlToRight
    Next

    'クリップボードへコピー
    lastRow = Cells(Rows.Count, 1).End(xlUp).Row
    lastCol = Cells(1, Columns.Count).End(xlToLeft).Column
    Range(Cells(1, 1), Cells(lastRow, lastCol)).Copy
End Sub
```

# Excel for Web スクリプト

ローカルのクリップボードはアクセスできないため、Ctrl＋C（⌘C）を手動でタイプしてください。

```javascript:TableToMarkdown.osts
function main(workbook: ExcelScript.Workbook) {
  let sheet = workbook.getActiveWorksheet();

  sheet.getRange("2:2").insert(ExcelScript.InsertShiftDirection.down);
  let usedRange = sheet.getUsedRange();
  let lastCol = usedRange.getColumnCount();

  for (let c = 0; c < lastCol; c++) sheet.getCell(1, c).setValue(":-:");
  let lastRow = usedRange.getRowCount();
  for (let r = 0; r < lastRow; r++) sheet.getCell(r, lastCol).setValue("|");

  for(let c = lastCol; c > 0; c--) {
    usedRange.getColumn(c - 1).insert(ExcelScript.InsertShiftDirection.right);
    sheet.getCell(0, c - 1).setValue("|");
    usedRange = sheet.getUsedRange();
    usedRange.getColumn(c - 1).copyFrom(usedRange.getColumn(c + 1));
  }

  sheet.getUsedRange().select();
  // manually press ⌘C for active range’s copy to clipboard 
}
```


# Google Spreadsheet スクリプト

ローカルのクリップボードはアクセスできないため、Ctrl＋Cを手動でタイプしてください。

```javascript
function TableToMarkdown() {
  const spreadsheet = SpreadsheetApp.getActive();
  const sheet = spreadsheet.getActiveSheet();

  sheet.insertRowsBefore(sheet.getRange('2:2').getRow(), 1);
  const lastCol = sheet.getRange(1, 1).getDataRegion().getNumColumns() + 1;

  for (let c = 1; c < lastCol; c++) sheet.getRange(2, c).setValue(":-:");
  const lastRow = sheet.getRange(1, 1).getDataRegion().getNumRows() + 1;
  for (let r = 1; r < lastRow; r++) sheet.getRange(r, lastCol).setValue("|");

  for (let c = lastCol; c > 1; c--) {
    sheet.insertColumnsBefore(sheet.getRange(1, c - 1, lastCol).getColumn(), 1);
    sheet.getRange(1, c + 1, lastCol).copyTo(sheet.getRange(1, c - 1, lastCol), SpreadsheetApp.CopyPasteType.PASTE_NORMAL, false);
  }

  sheet.getRange(1, 1).getDataRegion().activate();
  // manually press CTRL+C for active range’s copy to clipboard 
};
```

# おわりに

使う頻度はそれほど多くはありませんが、一発で変換できるのは便利です。

~~後日、`Google Spreadsheet`と`Excel for Web`向けのスクリプトも追加しておきます。~~

`Google Spreadsheet`と`Excel for Web`向けのスクリプトを追加しました。似て非なるスクリプトで、頭がこんがります。


#### 以上