ExcelのセルデータをHTMLファイルに差し込んで大量のウェブページを作成したい時、いちいちセルからコピペするのは大変です!
今回、VBAを使ってHTMLファイルを大量生産する方法を調べました。
いろいろなサイトのコードを参考にさせてもらい、何とか動作しました。感謝!
VBAで作成するHTMLファイルの確認
ページの構造は単純で、こんな感じのプロフィールページが大量にある感じです。
言葉だと説明が難しいので、まずはこちらのサンプルをご確認ください。
HTMLファイルに差し込むExcelデータはこんな感じ
Excelデータはこんな感じで、左からID、名前、アバターの画像URL、性別、職業、文章が並んでいます。
これらのデータを書き出すHTMLファイルに差し込んでいきます。
ダミーデータはこちらのサイトで生成しました。
VBAのコード全体はこんな感じ
コード全体ですが、大変長くなりました。。
Sub generateProductSpecDescription()
'くり返し用変数
Dim i As Integer
Dim j As Integer
'生成するファイル名に関する変数
Dim htmlName As String
Dim siteName As String
Dim lastNum As Integer
Dim Target As String
Dim formatZero As String
'データ取得に関する変数
Dim first_name As String
Dim last_name As String
Dim avatar As String
Dim gender As String
Dim job As String
Dim sentences As String
'Streamオブジェクトを生成
Dim adoSt As Object
Set adoSt = CreateObject("ADODB.Stream")
'生成するファイル数
lastNum = Cells(Rows.Count, 1).End(xlUp).Row
siteName = "えむ家のメモ帳"
'プロフィールが存在する限りループ
For i = 2 To lastNum
htmlName = "profile_"
formatZero = returnZero(i - 1)
Target = ActiveWorkbook.Path & "\" & htmlName & formatZero & ".html"
first_name = Cells(i, 2).Value
last_name = Cells(i, 3).Value
avatar = Cells(i, 4).Value
gender = Cells(i, 5).Value
job = Cells(i, 6).Value
sentences = Cells(i, 7).Value
With adoSt
'テキストデータ
.Type = 2
'文字コードをUTF-8に設定
.Charset = "UTF-8"
'改行コードを指定
.LineSeparator = 10
.Open
'HTML開始
.WriteText addHTML("", 0, "<!DOCTYPE html>"), 1
.WriteText addHTML("", 0, "<html lang=""ja"">"), 1
.WriteText addHTML("", 0, "<head>"), 1
.WriteText addHTML("", 1, "<link rel="" stylesheet"" type="" text/css"" href=""../css/normalize.css"">"), 1
.WriteText addHTML("", 1, "<link rel="" stylesheet"" type=""text/css"" href=""../css/common.css"">"), 1
.WriteText addHTML("", 1, "<link rel="" stylesheet"" type=""text/css"" href=""../css/adjustment.css"">"), 1
.WriteText addHTML("", 1, "<link rel="" stylesheet"" type=""text/css"" href=""./css/style.css"">"), 1
.WriteText addHTML("", 1, "<meta id=""viewport""name=""viewport""content=""width=device-width,minimum-scale=1,maximum-scale=1""/>"), 1
.WriteText addHTML("", 1, "<meta charset=""UTF-8"">"), 1
.WriteText addHTML("", 1, "<title>VBAでExcelのデータを差し込んだHTMLを大量生産する-" & "プロフィール_" & formatZero & "|えむ家のメモ帳</title>"), 1
.WriteText addHTML("", 0, "</head>"), 1
.WriteText addHTML("", 0, "<body>"), 1
.WriteText addHTML("", 1, "<header id=""header"">"), 1
.WriteText addHTML("", 2, "<divclass=""logo""><a href=""//m-kenomemo.com"">えむ家のメモ帳</a></div>"), 1
.WriteText addHTML("", 1, "</header>"), 1
.WriteText addHTML("", 1, "<main class=""main"">"), 1
.WriteText addHTML("", 2, "<h1>ExcelでHTMLを量産するサンプル</h1>"), 1
.WriteText addHTML("", 2, "<p class=""mb40"">ExcelのVBAで同じテンプレートのHTMLファイルを大量生産しました。<br><a href=""https://m-kenomemo.com/excel-mass-item/"">解説記事を読む</a></p>"), 1
.WriteText addHTML("", 2, "<p class=""center"">Profile_" & formatZero & "(" & i - 1 & "/" & lastNum - 1 & ")</p>"), 1
.WriteText addHTML("", 2, "<section class=""profile_wrap"">"), 1
.WriteText addHTML("", 3, "<h2>profile_main</h2>"), 1
.WriteText addHTML("", 3, "<div class=""img_area"">"), 1
.WriteText addHTML("", 4, "<img src=" & avatar & ">"), 1
.WriteText addHTML("", 3, "</div>"), 1
.WriteText addHTML("", 3, "<div class=""info_area"">"), 1
.WriteText addHTML("", 4, "<table>"), 1
.WriteText addHTML("", 5, "<tr>"), 1
.WriteText addHTML("", 6, "<th>name</th>"), 1
.WriteText addHTML("", 6, "<td>" & first_name & " " & last_name & "</td>"), 1
.WriteText addHTML("", 5, "</tr>"), 1
.WriteText addHTML("", 5, "<tr>"), 1
.WriteText addHTML("", 6, "<th>job</th>"), 1
.WriteText addHTML("", 6, "<td>" & job & "</td>"), 1
.WriteText addHTML("", 5, "</tr>"), 1
.WriteText addHTML("", 5, "<tr>"), 1
.WriteText addHTML("", 6, "<th>gender</th>"), 1
.WriteText addHTML("", 6, "<td>" & gender & "</td>"), 1
.WriteText addHTML("", 5, "</tr>"), 1
.WriteText addHTML("", 4, "</table>"), 1
.WriteText addHTML("", 3, "</div>"), 1
.WriteText addHTML("", 3, "<div class=""intro_area"">"), 1
.WriteText addHTML("", 4, "<p>" & sentences & "</p>"), 1
.WriteText addHTML("", 3, "</div>"), 1
.WriteText addHTML("", 2, "</section><!--/profile_wrap-->"), 1
.WriteText addHTML("", 2, "<div class=""nav"">"), 1
.WriteText addHTML("", 3, "<span class=""nav_btn show-prev"">"), 1
'最初のページの場合、ナビのPREVを表示しない
If formatZero = 1 Then
.WriteText addHTML("", 3, ""), 1
Else
.WriteText addHTML("", 4, "<a href=""./profile_" & returnZero(i - 2) & ".html""><img src=""./images/arrow_left.png""alt=""PREV"">PREV</a>"), 1
End If
.WriteText addHTML("", 3, "</span>"), 1
.WriteText addHTML("", 3, "<span class=""nav_btn show-next"">"), 1
'最後のページの場合、ナビのNEXTを表示しない
If i = lastNum Then
.WriteText addHTML("", 3, ""), 1
Else
.WriteText addHTML("", 4, "<a href=""./profile_" & returnZero(i) & ".html""><img src=""./images/arrow_right.png""alt=""NEXT"">NEXT</a>"), 1
End If
.WriteText addHTML("", 3, "</span>"), 1
.WriteText addHTML("", 2, "</div>"), 1
'プロフィール一覧
.WriteText addHTML("", 2, "<section class=""list_wrap"">"), 1
.WriteText addHTML("", 3, "<h2>profile_list</h2>"), 1
.WriteText addHTML("", 3, "<ul class=""list"">"), 1
'カレントユーザーの場合、リンクを無効にする
For j = 2 To lastNum
If formatZero = returnZero(j - 1) Then
.WriteText addHTML("", 4, "<li>NO." & returnZero(j - 1) & "(" & Cells(j, 2).Value & " " & Cells(j, 3).Value & ")</li>"), 1
Else
.WriteText addHTML("", 4, "<li><a href=""./profile_" & returnZero(j - 1) & ".html"">NO." & returnZero(j - 1) & "(" & Cells(j, 2).Value & " " & Cells(j, 3).Value & ")</a></li>"), 1
End If
Next j
.WriteText addHTML("", 3, "</ul>"), 1
.WriteText addHTML("", 2, "</section><!-- /list_wrap -->"), 1
.WriteText addHTML("", 1, "</main>"), 1
.WriteText addHTML("", 1, "<footer id=""footer"">"), 1
.WriteText addHTML("", 2, "<div class=""copyright"">Copyright 2020 © m-kenomemo.com</div>"), 1
.WriteText addHTML("", 1, "</footer>"), 1
.WriteText addHTML("", 1, "</body>"), 1
.WriteText addHTML("", 0, "</html>"), 1
'HTMLここまで
'BOMなしのUTF-8で出力する
.Position = 0
.Type = 1
.Position = 3
Dim byteData() As Byte
byteData = .Read
.Close
.Open 'ストリームを開く
.Write byteData 'ストリームに一時格納したデータを流し込む
.SaveToFile Target, 2
.Close
End With
Next i
End Sub
'0埋めする関数
Function returnZero(ByVal num As Integer) As String
If num < 10 ThenPolacode
returnZero = "0" + CStr(num)
Else
returnZero = CStr(num)
End If
End Function
'HTMLにタブを追加する関数
Function addHTML(ByVal strBase As String, ByVal cntIndent As Long, ByVal strAdd As String) As String
If cntIndent > 0 Then
Dim i As Long
For i = 1 To cntIndent
strBase = strBase & vbTab
Next i
End If
strBase = strBase & strAdd & vbCr
addHTML = strBase
End Function
生成するファイルの数を指定する
思ったより長いコードになったので、ポイントだけメモしておきます。
まずは、生成するHTMLファイルの数は、データを入力しているセルの最終行までとします。
セルA1の最終行の数を「lastNum」変数に格納します。
'生成するファイル数
lastNum = Cells(Rows.Count, 1).End(xlUp).Row
ADODB.Streamオブジェクトを設定する
VBAで生成されるファイルの文字コードは通常「Shift-JIS」になります。
HTMLファイルは「UTF-8」で作成することが多いので、今回は「UTF-8」でファイルを書き出します。
ADODB.Streamオブジェクト使用すると、ファイルの文字コードを指定できるようです。
オブジェクトを格納する変数を設定します。
'Streamオブジェクトを生成 Dim adoSt As Object Set adoSt = CreateObject("ADODB.Stream")
参考サイト
プロフィールの数だけ処理を繰り返す
Forループでデータが入力されているセルの数だけ同じ処理を繰り返します。
変数iはセルデータの行を取得するのに使用します。
差し込むデータは2行目から開始となるので、Forループの処理も2から開始します。
ループの最初でHTMLファイルに差し込むデータを変数に格納します。
'プロフィールが存在する限りループ
For i = 2 To lastNum
'変数セット
htmlName = "profile_"
formatZero = returnZero(i - 1)
Target = ActiveWorkbook.Path & "\" & htmlName & formatZero & ".html"
first_name = Cells(i, 2).Value
last_name = Cells(i, 3).Value
avatar = Cells(i, 4).Value
gender = Cells(i, 5).Value
job = Cells(i, 6).Value
sentences = Cells(i, 7).Value
'ここから繰り返す処理~
Next i
HTMLファイルをBOMなしのUTF-8で出力する
先ほど作成したADODB.Streamオブジェクトを使って、HTMLファイルをUTF-8で書き出します。
HTMLファイルはBOMなしのUTF-8が標準なので、その設定に関するコードも追加します。
With adoSt
'テキストデータ
.Type = 2
'文字コードをUTF-8に設定
.Charset = "UTF-8"
'改行コードを指定
.LineSeparator = 10
.Open
'HTML開始~終了
'BOMなしのUTF-8で出力する
.Position = 0
.Type = 1
.Position = 3
Dim byteData() As Byte
byteData = .Read
.Close
.Open 'ストリームを開く
.Write byteData 'ストリームに一時格納したデータを流し込む
.SaveToFile Target, 2
.Close
End With
参考サイト
HTMLのコードを追加していく
ここまで実装できたら、記述したいHTMLコードをどしどし追加していくだけです。
変数iを使えば、ページによっていろいろな条件分岐ができますね!
注意点はHTMLの「”」をエスケープする必要があることです。
あと、コードの見栄えをよくするために行の先頭にタブを追加しました。
これについては次のような関数を作成します。
'HTMLにタブを追加する関数
Function addHTML(ByVal strBase As String, ByVal cntIndent As Long, ByVal strAdd As String) As String
If cntIndent > 0 Then
Dim i As Long
For i = 1 To cntIndent
strBase = strBase & vbTab
Next i
End If
strBase = strBase & strAdd & vbCr
addHTML = strBase
End Function
参考サイト
まとめ
なんとか動作するVBAが作成できましたが、まだまだ内容を理解していないところが多いです。。
エクセルデータを差し込んでファイルを作成することは時々あるので、他にも応用できたらと思います!
コメント