HTMLのtable要素を作るFunction

HTMLのtable要素を作る

HTMLで表を作るのはメンドクサイ

Excelでちゃちゃっと表を作って、それをHTMLタグで囲って構造化するマクロを作った。

リスト1 標準モジュール
Public Function createHTMLTable( _
                  ByVal targetRange As Range, _
                  Optional ByVal hasHeader As Boolean = True, _
                  Optional ByVal hasBorder As Boolean) As String    '……(1)'
  Dim rowCount As Long    '……(2)'
  rowCount = targetRange.Rows.Count
  Dim columnCount As Long
  columnCount = targetRange.Columns.Count
  Dim i As Long
  Dim j As Long
  Dim stringOfCell() As String    '……(3)'
  ReDim stringOfCell(0 To rowCount - 1, 0 To columnCount - 1)
  For i = 0 To rowCount - 1
    For j = 0 To columnCount - 1
      stringOfCell(i, j) = targetRange.Cells(i + 1, j + 1).Value
    Next
  Next
  Dim str As String
  If hasBorder Then    '……(4)'
    str = "<table border=""1"">"
  Else
    str = "<table border="""">"
  End If
  For i = 1 To rowCount    '……(5)'
    str = str & "<tr>"    '……(6)'
    For j = 1 To columnCount    '……(7)'
      If hasHeader And i = 1 Then    '……(8)'
        str = str & "<th>" & stringOfCell(i - 1, j - 1) & "</th>"
      Else
        str = str & "<td>" & stringOfCell(i - 1, j - 1) & "</td>"
      End If
    Next
    str = str & "</tr>"    '……(9)'
  Next
  str = str & "</table>"    '……(10)'
  str = Replace(str, vbLf, "<br>")    '……(11)'
  createHTMLTable = str
End Function

(1)の

Public Function createHTMLTable( _
                  ByVal targetRange As Range, _
                  Optional ByVal hasHeader As Boolean = True, _
                  Optional ByVal hasBorder As Boolean) As String

では、引数3つと返り値の型を設定。

第1引数では、対象のセル範囲を指定。

第2引数は、表が項目ラベルを持っているかどうか。持っているならTrue。

第3引数は、境界線をどうするか。Trueだったらborder属性に"1"をセットする。Falseなら""。

で、返り値はString型。

(2)からの4行

Dim rowCount As Long
rowCount = targetRange.Rows.Count
Dim columnCount As Long
columnCount = targetRange.Columns.Count

では、表の行数・列数を変数にぶち込んでおく。

(3)からの7行

Dim stringOfCell() As String
ReDim stringOfCell(0 To rowCount - 1, 0 To columnCount - 1)
For i = 0 To rowCount - 1
  For j = 0 To columnCount - 1
    stringOfCell(i, j) = targetRange.Cells(i + 1, j + 1).Value
  Next
Next

では、String型の2次元配列stringOfCell()に表の各セルの値をぶち込んでいる。

もっと簡単にできたと思うけれど、調べるのがめんどくさいんで(←コラ!)、とりあえずこういう原始的なやり方で。

(4)からの5行

If hasBorder Then
  str = "<table border=""1"">"
Else
  str = "<table border="""">"
End If

では、引数hasBorderの値に応じて、tableの開始タグを書き分けている。

で、(5)からの11行

For i = 1 To rowCount
  str = str & "<tr>"    '……(6)'
  For j = 1 To columnCount    '……(7)'
    If hasHeader And i = 1 Then    '……(8)'
      str = str & "<th>" & stringOfCell(i - 1, j - 1) & "</th>"
    Else
      str = str & "<td>" & stringOfCell(i - 1, j - 1) & "</td>"
    End If
  Next
  str = str & "</tr>"    '……(9)'
Next

二重のForループで一気にtableタグの中身を作っていく。

まず、外側のForループでは、表の各行を作っていくので、ループの最初に(6)の

str = str & "<tr>"

で<tr>タグを付け足し、次のループに移る直前に(9)の

str = str & "</tr>"

で</tr>タグを付け足すようにしている。

また、内側のForループ、すなわち(7)からの7行

For j = 1 To columnCount
  If hasHeader And i = 1 Then    '……(8)'
    str = str & "<th>" & stringOfCell(i - 1, j - 1) & "</th>"
  Else
    str = str & "<td>" & stringOfCell(i - 1, j - 1) & "</td>"
  End If
Next

では、引数hasHeaderの状態に応じて分岐。(8)の

If hasHeader And i = 1 Then

でhasHeaderがTrueで、かつ i = 1 のとき、つまり表の1行目が各列のラベルである場合は、セルの値を<th></th>で囲まないといけないので、このような条件分岐にしている。

hasHeader And i = 1

がTrueのときは、

str = str & "<th>" & stringOfCell(i - 1, j - 1) & "</th>"

によって、セルの値を<th></th>でくくった文字列をstrに追加し、

hasHeader And i = 1

がFalseのときは、

str = str & "<td>" & stringOfCell(i - 1, j - 1) & "</td>"

によって、セルの値を<td></td>でくくる、という仕掛け。

二重のForループから抜けると、表の中身は全てタグ打ちができているはずなので、(10)の

str = str & "</table>"

でtableタグを閉じる。

ついでに、(11)の

str = Replace(str, vbLf, "<br>")

では、Replace関数を用いて、セル内改行(vbLf)を<br>に置き換えておく。

使ってみる

f:id:akashi_keirin:20180108222554j:plain

シート(Sheet2です)にこんなふうに表を用意して、次のコードで実験してみる。

スト2 標準モジュール
Public Sub testHTMLTable()
  Dim Sh As Worksheet
  Set Sh = ThisWorkbook.Worksheets("Sheet2")
  Debug.Print createHTMLTable(Sh.Range("A1").CurrentRegion, True, True)
End Sub

f:id:akashi_keirin:20180108222603j:plain

イミディエイトに、タグ打ちした文字列が表示されるので、それをHTMLソースにコピペしてブラウザで開いてみた。

f:id:akashi_keirin:20180108222612j:plain

f:id:akashi_keirin:20180108222623j:plain

セル内改行した表でも実験してみたが、

f:id:akashi_keirin:20180108222636j:plain

こんなふうに、うまく表示された。

おわりに

Excelでちょこちょこっと表を作って、table要素にできたらいいなーと思っただけです。

「ちょwww もっと簡単にできるじゃねーかよwww」とか、笑われるかもしれませんが、HTMLなんてつい最近までろくに知らなかったし、Webページを触るようなこともしたことがなかったので、ホームページビルダー(っていうの?)なんかも触ったことのない素人の思いつきですから、笑って許してくだされ。

しっかし、これ、セルの結合とかに対応しようとしたら、途端に激ムズになるんじゃね???

@akashi_keirin on Twitter