94本目 Excelの表をHTMLに変換

VBA100本ノック

VBA100本ノック 94本目を動画で解説しています。Excelの神髄さんの模範解答はコチラ


問題

#VBA100本ノック 94本目
表を、HTMLのに変換するFunctionを作成。
引数(セル範囲,見出行数)でHTMLで返す。
見出行数:>=1は指定行数をで出力。
セル結合:<td colspan=”2″ rowspan=”2″>等々。
空白セル:” “を出力。
※出力サンプルを参考に。
※文字位置は不要、インデントは任意

解答

Sub main()
    Open Replace(ThisWorkbook.FullName, ".xlsm", ".html") For Output As #1
    Print #1, VBA100_94_01(Range("B2").CurrentRegion, 2)
    Close #1
'    Debug.Print VBA100_94_01(Range("B2").CurrentRegion, 2)
End Sub

Function VBA100_94_01(範囲 As Range, 見出し行数 As Long) As String

    Dim str As String, 開始タグ As String, 終了タグ As String
    Dim i As Long, j As Long
    str = "<table border=""1"">" & vbLf 'テーブルタグ
    If 見出し行数 > 0 Then
        開始タグ = "<th>": 終了タグ = "</th>"
        str = str & "<thead>" & vbLf
    Else
        開始タグ = "<td>": 終了タグ = "</td>"
        str = str & "<tbody>" & vbLf
    End If
    Dim mRow, mCol
    For i = 1 To 範囲.Rows.Count
        str = str & "<tr>" & vbLf
        For j = 1 To 範囲.Columns.Count
            If 範囲.Cells(i, j).MergeCells Then  'もしセル結合されていた場合
                'もしCells(i,j)のアドレスと、Cells(i,j)のMergeAreaの1番目が同じだった場合のみ処理
                If 範囲.Cells(i, j).Address = 範囲.Cells(i, j).MergeArea(1).Address Then
                    mRow = 範囲.Cells(i, j).MergeArea.Rows.Count
                    mCol = 範囲.Cells(i, j).MergeArea.Columns.Count
                    str = str & Left(開始タグ, 3)
                    If mRow > 1 Then str = str & " rowspan=""" & mRow & """"
                    If mCol > 1 Then str = str & " colspan=""" & mCol & """"
                    str = str & ">" & 範囲.Cells(i, j).Value & 終了タグ & vbLf
                End If
            Else 'セル結合されていない場合
                If 範囲.Cells(i, j) <> "" Then
                    str = str & 開始タグ & 範囲.Cells(i, j).Value & 終了タグ & vbLf
                Else
                    str = str & 開始タグ & "&nbsp;" & 終了タグ & vbLf
                End If
            End If
        Next j
        str = str & "</tr>" & vbLf
        If i = 見出し行数 Then
            str = str & "</thead>" & vbLf
            str = str & "<tbody>" & vbLf
            開始タグ = "<td>": 終了タグ = "</td>"
        End If
    Next i
    str = str & "</body>" & vbLf
    str = str & "</table>"
    VBA100_94_01 = str
End Function

■考え方・流れ
0:00 冒頭・問題確認
3:08 範囲内をループして値を取得
5:12 取得した値をタグで挟む
6:50 tableタグの作成とtheadでの行数の分岐
9:04 thタグ、tdタグでの分岐
10:30 セル結合がされていない場合の分岐
11:44 セル結合がされていた場合の分岐
13:02 結合された行数列数をカウント

HTMLってなんぞや???って人でも分かるように一つずつゆっくり解説していったぞ?たぶんね!

先に作りたいファンクションのイメージだけ載せとくぞ!↓

新人君
新人君

全くの初心者さんには
難しい問題でしたね…

ブチョ
ブチョ

フィーリングでいけるぞ!

新人君
新人君

ふぃ、フィーリングで…?
無理やろ…

範囲内をループして値を取得

細かいことはまずはおいといて!
とりあえず、表範囲の中の、全ての行列の値を取得する方法から!
ここは今までの知識でなんとかなるぞ!

ということは引数受け取った範囲の、行列を全てループすればよいから…

ここからは、全ての文字を改行を挟んで結合してあげる!
str = str + その範囲 + vbLf(改行)だね!

最後はおなじみ!!ファンクション名 = strで、関数の結果を返してあげる!

Debug.Printでこのコードをイミディエイトウィンドウに出力してあげるとこんな感じ!!
空白は入ってるが、とりあえず表の中の値は全て出せてそうだね!

取得した値をタグで挟む

お次は取得した値をタグ<>で挟んでいくぞ!!
よーくみたらHTMLって、全ての文字が<></>で挟まれてるのが分かるかな?
そういうことなんすわ!

とりあえず全部、<td>と</td>でくくってみるぞ!
話はそこからじゃい!

こんな感じじゃい!↓

実行結果はこんな感じだ!!!
ちょっとだけそれっぽいよな!

tableタグの作成とtheadでの行数の分岐

よし!次はとりあえず…!
一番上のtableタグってやつと、theadタグの分岐をやっていくぞ!!

とりあえずtableタグを一番上と下に入れた結果がこちら!↓
<table border=”1″>ってのは、枠線をいれますよ~ってこと!
borderは枠線って意味なんざんすんご!!

お次はtheadの行数による分岐!!
見出しがない場合も考慮して、0の場合はいきなりtbody(本文)から入らにゃならんのだ!!
むずいー!!

ほんで…見出しがなかった場合は!
今度は最後に</thead>でくくる必要がないから…!!
最後も同じように条件分岐だ!!

thタグ、tdタグでの分岐

お次は、「見出し部分の分岐!!」
今は一旦ぜーんぶ、表の値をtdタグでくくったんだけど…
実は見出し部分はthタグってのでくくるのがルールなんスわ!

これに関してはそこまで難しくなく、
さっきまでtdってアホみたいに書いてたところを、
変数に置き換えればOK!!

セル結合がされているかどうかで分岐

よし!お次は…
表の中にセル結合がされているかされていないかの条件分岐だ!!

え?セル結合やめてって??
いやいや…HTMLにするための表でそれはむりっしょ…

まずは簡単な、セル結合されてる場合の方から書いてるぞ!
セル結合されていない場合で、「空白のセル」は
“&nbsp”で表せられるんスわ!そういうもんなんすわ!!

続いて、セル結合されていた場合!!↓
まーじせるのインデックスが1の時…そうでない時…てきな…

ここはイメージとしてはこんな感じ!↓
ただ、Cells(i,j).MergeAreaじゃなくてMergeCellsが正しいです。(後で訂正)

結合された行数列数をカウント

最後です!!
Cells(i,j)が結合されている場合で、かつそのセルが一番左上だった場合の処理です!!
書き方むずいけど…↓これを参考に文字を当てていくだけだ!!がんばれ!!

セルによって、何行何列結合されてるかはわからないから…
mRow,mColって変数を作って、何行何列結合されているかをこの中にぶち込むぞ!

ほんでここからがちょっとややこしい…!!!
<td rowspan”2″…的な感じにするには、一旦左から3文字だけ抜き出して…

その後に続く文字は、何行結合されてるか、何列結合されてるかで分岐しよう!!!
複数行結合されている場合、つまりmRowが2以上の場合、rowspanと、”と、mRow(何行)と、”を結合!!!!
複数列の場合はcolspanにすりゃ~~~OKなんご!

ここまでできたら、あとはbodyタグやら何やらをしめるだけだ!!!
その辺は多少割愛したが、ここまでの中身が理解出来てたらそこは余裕だと思う!!

模範解答はもっとスマートだから、是非見てみてくれよな!

ブチョ
ブチョ

ムズすぎて漏らしちゃいそうだったよ!

新人君
新人君

僕もッス!

あとがたり

おはこんばんちは。uぷ主です。
94本目!!Excelの表をHTMLに変換する問題でした!

・・・

え?もっかい言って?HTMLがなんて??

いんやぁ~、HTML勉強して自分で書いた方が早いんちゃうかと思うレベルの問題でしたね。
94本目でこれが来るとは…ビビりました。

僕が個人的にHTMLを知ったのは、VBA勉強してから…4年後ぐらい??だったと思うんで…
VBAは知ってるけどHTMLの知識全くない人も多そうwww

ま、そんな人にも向けて、一応HTMLってどんなもんや??てきな解説も入れてみたので…
良かったら褒めてください…きつかった…

今まででかなり難しい部類の問題でした。
てか、残り6本の中ではこれが一番難しかったかな??

こんだけ色々変数やら分岐やらロジック組み立てられたらもう充分っすよ。
ホント、オツカレサマデシタ。

また来年お会いしましょう~~~!!
あと6本!!

コメント

タイトルとURLをコピーしました