概要
インプット情報(Google スプレッドシートか CSV)を HTML テーブルに変換し、Web ブラウザで視覚的に確認できる HTML ファイルを生成する方法を検討します。
- Python スクリプト
- VBA マクロ
- シェルスクリプト
- Google Apps Script
1. Python スクリプト
コード
import csv
def csv_to_html_with_colspan(input_file, output_file):
with open(input_file, 'r', encoding='utf-8') as csv_file:
reader = csv.reader(csv_file)
with open(output_file, 'w', encoding='utf-8') as html_file:
html_file.write("<!DOCTYPE html>\n")
html_file.write("<html><head><title>CSV to HTML Table</title></head><body>\n")
html_file.write("<table border='1'>\n")
for row_index, row in enumerate(reader):
html_file.write("<tr>\n")
empty_count = 0
for cell in row:
if cell == "":
empty_count += 1
else:
if empty_count > 0:
tag = "th" if row_index == 0 else "td"
html_file.write(f"<{tag} colspan='{empty_count}'></{tag}>\n")
empty_count = 0
tag = "th" if row_index == 0 else "td"
html_file.write(f"<{tag}>{cell}</{tag}>\n")
if empty_count > 0:
tag = "th" if row_index == 0 else "td"
html_file.write(f"<{tag} colspan='{empty_count}'></{tag}>\n")
html_file.write("</tr>\n")
html_file.write("</table>\n")
html_file.write("</body></html>\n")
print(f"HTML file has been created: {output_file}")
# 使用例
input_file_path = "path/to/test.csv" # 入力CSVファイルのパス
output_file_path = "path/to/output.html" # 出力HTMLファイルのパス
csv_to_html_with_colspan(input_file_path, output_file_path)
実行方法
-
input_file_path
とoutput_file_path
を自分の環境に合わせて指定します。 - スクリプトを実行すると、指定された HTML ファイルが生成されます。
2. VBA マクロ
コード
Sub CsvToHtmlWithColspan()
Dim csvFilePath As String
Dim htmlFilePath As String
Dim htmlFile As Object
Dim fs As Object
Dim line As String
Dim isFirstLine As Boolean
Dim columns() As String
Dim emptyCount As Integer
Dim i As Integer
csvFilePath = "C:\path\to\test.csv" ' 入力CSVファイルのパス
htmlFilePath = "C:\path\to\output.html" ' 出力HTMLファイルのパス
Set fs = CreateObject("Scripting.FileSystemObject")
Set htmlFile = fs.CreateTextFile(htmlFilePath, True)
htmlFile.WriteLine "<!DOCTYPE html>"
htmlFile.WriteLine "<html><head><title>CSV Table</title></head><body><table border='1'>"
Open csvFilePath For Input As #1
isFirstLine = True
Do Until EOF(1)
Line Input #1, line
columns = Split(line, ",")
htmlFile.WriteLine "<tr>"
emptyCount = 0
For i = LBound(columns) To UBound(columns)
If columns(i) = "" Then
emptyCount = emptyCount + 1
Else
If emptyCount > 0 Then
htmlFile.WriteLine "<" & IIf(isFirstLine, "th", "td") & " colspan='" & emptyCount & "'></" & IIf(isFirstLine, "th", "td") & ">"
emptyCount = 0
End If
htmlFile.WriteLine "<" & IIf(isFirstLine, "th", "td") & ">" & columns(i) & "</" & IIf(isFirstLine, "th", "td") & ">"
End If
Next i
If emptyCount > 0 Then
htmlFile.WriteLine "<" & IIf(isFirstLine, "th", "td") & " colspan='" & emptyCount & "'></" & IIf(isFirstLine, "th", "td") & ">"
End If
htmlFile.WriteLine "</tr>"
isFirstLine = False
Loop
Close #1
htmlFile.WriteLine "</table></body></html>"
htmlFile.Close
MsgBox "HTMLファイルが " & htmlFilePath & " に出力されました。"
End Sub
実行方法
- Excel で VBA エディターを開き(
Alt + F11
)、新しいモジュールにコードを貼り付けます。 -
csvFilePath
とhtmlFilePath
を自分の環境に合わせて変更し、マクロを実行します。
3. シェルスクリプト
コード
#!/bin/bash
INPUT_FILE="/path/to/your/test.csv" # CSVファイルのパス
OUTPUT_FILE="/path/to/your/output.html" # 出力HTMLファイルのパス
{
echo "<!DOCTYPE html>"
echo "<html><head><title>CSV to HTML Table</title></head><body>"
echo "<table border='1'>"
while IFS= read -r line; do
echo "<tr>"
IFS=',' read -ra cols <<< "$line"
empty_count=0
for col in "${cols[@]}" ""; do
if [[ -z "$col" ]]; then
((empty_count++))
else
if ((empty_count > 0)); then
echo "<td colspan='$empty_count'></td>"
empty_count=0
fi
echo "<td>$col</td>"
fi
done
echo "</tr>"
done < "$INPUT_FILE"
echo "</table>"
echo "</body></html>"
} > "$OUTPUT_FILE"
echo "HTMLファイルが $OUTPUT_FILE に出力されました。"
実行方法
- スクリプトをファイルに保存し、実行権限を付与します。
chmod +x csv_to_html.sh
- スクリプトを実行します。
./csv_to_html.sh
4. Google Apps Script のメモ
-
Google Apps Script
//CSVファイルを読んでHTMLを出力する function processCsvAndGenerateHtml() { const folderId = "フォルダID"; // ここにフォルダIDを指定 const folder = DriveApp.getFolderById(folderId); const files = folder.getFilesByName("data.csv"); if (!files.hasNext()) { Logger.log("data.csv ファイルが見つかりません"); return; } const file = files.next(); const content = file.getBlob().getDataAsString("UTF-8"); const rows = content.split("\n").map((row) => row.split("\t")); let htmlTop = ""; let htmlBottom = ""; let tableContent = ""; rows.forEach((row) => { const firstCell = row[0] ? row[0] : ""; if (firstCell.startsWith("#")) { if (firstCell.startsWith("#■固定出力部top")) { htmlTop += row.slice(1).join("").replace(/\t/g, "") + "\n"; // タブを除去 } else if (firstCell.startsWith("#■固定出力部bottom")) { htmlBottom += row.slice(1).join("").replace(/\t/g, "") + "\n"; // タブを除去 } else if (firstCell.startsWith("#行データ・機能")) { tableContent += ` <tr>\n`; tableContent += ` <td colspan=3>${row[1].trim()}</td>\n`; tableContent += ` </tr>\n`; } else if (firstCell.startsWith("#行データ・状態")) { tableContent += ` <tr>\n`; tableContent += ` <td>${row[1].trim()}</td>\n`; tableContent += ` <td>${row[2].trim()}</td>\n`; tableContent += ` <td class="toggle-col">${row[3].trim()}</td>\n`; tableContent += ` </tr>\n`; } else { return; // 上の処理指定行以外はスキップする。 } } }); const finalHtml = htmlTop + tableContent + htmlBottom; const outputFileName = "output.html"; const outputFile = folder.createFile( outputFileName, finalHtml, MimeType.HTML ); Logger.log(`HTMLファイルが生成されました: ${outputFile.getUrl()}`); }
//GWSドライブのスプレッドシートを読み込んでHTMLを出力する function processSpreadsheetAndGenerateHtml() { const spreadsheetId = "スプレッドシートID"; // ここにスプレッドシートIDを指定 const sheetName = "シート1"; // シート名を指定 const sheet = SpreadsheetApp.openById(spreadsheetId).getSheetByName(sheetName); const rows = sheet.getDataRange().getValues(); let htmlTop = ""; let htmlBottom = ""; let tableContent = ""; rows.forEach((row) => { const firstCell = row[0] ? row[0].toString() : ""; if (firstCell.startsWith("#")) { if (firstCell.startsWith("#■固定出力部top")) { htmlTop += row.slice(1).join("").replace(/\t/g, "") + "\n"; // タブを除去 } else if (firstCell.startsWith("#■固定出力部bottom")) { htmlBottom += row.slice(1).join("").replace(/\t/g, "") + "\n"; // タブを除去 } else if (firstCell.startsWith("#行データ・機能")) { tableContent += ` <tr>\n`; tableContent += ` <td colspan=3>${row[1].trim()}</td>\n`; tableContent += ` </tr>\n`; } else if (firstCell.startsWith("#行データ・状態")) { tableContent += ` <tr>\n`; tableContent += ` <td>${row[1].trim()}</td>\n`; tableContent += ` <td>${row[2].trim()}</td>\n`; tableContent += ` <td class="toggle-col">${row[3].trim()}</td>\n`; tableContent += ` </tr>\n`; } else { return; // 上の処理指定行以外はスキップする。 } } }); const finalHtml = htmlTop + tableContent + htmlBottom; const folderId = "出力用フォルダID"; // 出力用フォルダID const folder = DriveApp.getFolderById(folderId); const outputFileName = "output.html"; const outputFile = folder.createFile( outputFileName, finalHtml, MimeType.HTML ); Logger.log(`HTMLファイルが生成されました: ${outputFile.getUrl()}`); }
//ログファイルを指定階層に出力する function outputLog(folder_id, msg) { // 実行日付をフォーマットする var date = new Date(); var dateString = Utilities.formatDate( date, Session.getScriptTimeZone(), "yyyy-MM-dd" ); var dateTimeString = Utilities.formatDate( date, Session.getScriptTimeZone(), "yyyy-MM-dd HH:mm:ss" ); // ログの生成 var log_message = dateTimeString + " " + msg; Logger.log(log_message); // Apps Scriptのログに記録 var fileName = dateString + "_log.txt"; // フォルダーIDを指定して取得する var folderId = folder_id; // ここに指定するフォルダIDを記入 var folder = DriveApp.getFolderById(folderId); // 指定されたフォルダーを取得 var files = folder.getFilesByName(fileName); var file; // ファイルが存在する場合、内容を追記 if (files.hasNext()) { file = files.next(); var oldContent = file.getBlob().getDataAsString(); file.setContent(oldContent + "\n" + log_message); } else { // ファイルが存在しない場合、新しいファイルを作成 file = folder.createFile(fileName, log_message); } }
#メッセージ 現在の Service Status は異常です。 #読み込み対象外 #読み込み対象外 項目1 項目2 項目3 #行データ・機能 機能A #行データ・状態 データ1 データ2 データ3 #行データ・状態 データ4 データ5 データ6 #行データ・機能 機能B #行データ・状態 データ7 データ8 データ9 #行データ・状態 データ10 データ11 データ12 #読み込み対象外 #読み込み対象外 #読み込み対象外 #■固定出力部top <!DOCTYPE html> #■固定出力部top <html lang="ja"> #■固定出力部top <head> #■固定出力部top <meta charset="UTF-8"> #■固定出力部top <title>テーブル列の表示・非表示</title> #■固定出力部top <style> #■固定出力部top .hidden { #■固定出力部top display: none; #■固定出力部top } #■固定出力部top .header { #■固定出力部top background-color: #0078d4; #■固定出力部top color: white; #■固定出力部top padding: 1rem; #■固定出力部top text-align: center; #■固定出力部top } #■固定出力部top .message { #■固定出力部top color: black; #■固定出力部top padding: 1rem; #■固定出力部top text-align: center; #■固定出力部top } #■固定出力部top .container { #■固定出力部top max-width: 900px; #■固定出力部top margin: 2rem auto; #■固定出力部top background-color: white; #■固定出力部top border-radius: 8px; #■固定出力部top box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); #■固定出力部top padding: 1rem; #■固定出力部top } #■固定出力部top </style> #■固定出力部top <script> #■固定出力部top function toggleColumn() { #■固定出力部top var cols = document.querySelectorAll('.toggle-col'); #■固定出力部top cols.forEach(function(col) { #■固定出力部top col.classList.toggle('hidden'); #■固定出力部top }); #■固定出力部top } #■固定出力部top </script> #■固定出力部top </head> #■固定出力部top <body> #■固定出力部top <div class="header"> #■固定出力部top <h1>Service Status</h1> #■固定出力部top </div> #■固定出力部top <div class="message"> #■固定出力部top <h1> #■固定出力部top 現在の Service Status は異常です。 #■固定出力部top </h1> #■固定出力部top </div> #■固定出力部top <div class="container"> #■固定出力部top <button onclick="toggleColumn()">列の表示/非表示</button> #■固定出力部top <table border="1"> #■固定出力部top <tr> #■固定出力部top <th>項目1</th> #■固定出力部top <th>項目2</th> #■固定出力部top <th class="toggle-col">項目3</th> #■固定出力部top </tr> #■固定出力部bottom </table> #■固定出力部bottom <!-- 他のステータス項目を追加 --> #■固定出力部bottom </div> #■固定出力部bottom </body> #■固定出力部bottom </html>
5. Google Sheets でシートにボタンを配置して Google Apps Script を視覚的に実行する
ボタンを挿入する
-
Google Sheets を開く
- 「挿入」メニューをクリックし、「図形描画」を選択
- 図形描画ツールで適当な図形(四角形など)を描画
- 描画した図形を選択し、「保存して閉じる」をクリック
-
図形にスクリプトを割り当てる
- シート上に挿入された図形を右クリックし、「スクリプトを割り当て」を選択
- 表示されるダイアログボックスに実行したい関数名を入力(例えば、copyFiles など)。
- 「OK」をクリック
- これで、図形(ボタン)をクリックすると、指定した Google Apps Script が実行される