0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

CSVをテーブル表示してフィルタリングやソートできるHTMLファイル

Last updated at Posted at 2025-03-13

自宅の検証環境のWindowsでイベントログが結構出ているので、csv出力してログを軽く眺めたいなと思いまして、CSVファイルをテーブル表示してかつ、
フィルタリングやソートのような簡単な機能を持ったHTMLコードを作ってみました。
ちなみに、自宅の検証環境が一部インターネットにつながっていないので、
一応オフラインの環境でも動くようにコードが作られているはずです。
(Google Geminiを一部使用してコード作成していますので、使用は自己責任で。)

CSViewer.html
<!DOCTYPE html>
<html>
<head>
    <title>CSViewer</title>
    <style>
        table {
            border-collapse: collapse;
            width: 100%;
        }
        th, td {
            border: 1px solid black;
            padding: 8px;
            text-align: left;
        }
        th {
            background-color: #f2f2f2;
            cursor: pointer;
        }
        .filter {
            width: 100%;
            padding: 8px;
            margin-bottom: 8px;
        }
    </style>
</head>
<body>
    <input type="file" id="csvFileInput">
    <p>使い方<br>①CSVファイルを選択して読み込むとテーブルが表示されます
        <br>②検索条件をフィルター欄に入力すると検索されます
        <br>③テーブルの並び替えはカラム(先頭行)をダブルクリックします</p>
    <div id="filters"></div>
    <br>
    <table id="csvTable">
        <thead>
            <tr></tr>
        </thead>
        <tbody></tbody>
    </table>

    <script>
        const csvFileInput = document.getElementById('csvFileInput');
        const filtersDiv = document.getElementById('filters');
        const csvTable = document.getElementById('csvTable');

        csvFileInput.addEventListener('change', function(event) {
            const file = event.target.files[0];
            const reader = new FileReader();

            reader.onload = function(e) {
                const csv = e.target.result;
                const data = parseCSV(csv);
                renderTable(data);
                renderFilters(data[0]);
            };

            reader.readAsText(file);
        });

        function parseCSV(csv) {
            const lines = csv.split('\n');
            return lines.map(line => line.split(','));
        }

        function renderTable(data) {
            const theadRow = csvTable.querySelector('thead tr');
            theadRow.innerHTML = '';
            const tbody = csvTable.querySelector('tbody');
            tbody.innerHTML = '';

            if (data.length === 0) return;

            data[0].forEach(header => {
                const th = document.createElement('th');
                th.textContent = header;
                th.addEventListener('click', () => sortTable(data, header));
                theadRow.appendChild(th);
            });

            for (let i = 1; i < data.length; i++) {
                const row = document.createElement('tr');
                data[i].forEach(cell => {
                    const td = document.createElement('td');
                    td.textContent = cell;
                    row.appendChild(td);
                });
                // 特定列の値に応じて背景色を変更(重大度を視覚的にわかりやすくするため)
                const targetColumnIndex = 2; // 例)3列目を指定(1列目は0から数える)
                if (data[i][targetColumnIndex] === 'エラー') {
                    row.style.backgroundColor = 'red';
                } else if (data[i][targetColumnIndex] === '警告') {
                    row.style.backgroundColor = 'orange';
                }
                tbody.appendChild(row);
            }
        }

        function renderFilters(headers) {
            filtersDiv.innerHTML = '';
            headers.forEach(header => {
                const input = document.createElement('input');
                input.type = 'text';
                input.placeholder = `Filter ${header}`;
                input.className = 'filter';
                input.addEventListener('input', () => filterTable());
                filtersDiv.appendChild(input);
            });
        }

        function filterTable() {
            const filters = Array.from(filtersDiv.querySelectorAll('.filter'));
            const tbodyRows = Array.from(csvTable.querySelector('tbody').rows);

            tbodyRows.forEach(row => {
                let display = true;
                filters.forEach((filter, index) => {
                    if (filter.value && !row.cells[index].textContent.includes(filter.value)) {
                        display = false;
                    }
                });
                row.style.display = display ? '' : 'none';
            });
        }

        function sortTable(data, header) {
            const index = data[0].indexOf(header);
            const body = csvTable.querySelector("tbody");
            const new_data = data.slice(1)

            new_data.sort((a, b) => {
                if (a[index] < b[index]) {
                    return -1;
                } else if (a[index] > b[index]) {
                    return 1;
                } else {
                    return 0;
                }
            });

            const newData = [data[0], ...new_data];
            renderTable(newData)

        }
    </script>
</body>
</html>

ついでに、csvファイルを結合するbatコードも追記。

@echo off
setlocal

set "outputFile=結合結果.csv"
del "%outputFile%" 2>nul

powershell.exe -NoProfile -Command ^
    "Get-ChildItem *.csv | Where-Object {$_.Name -ne '%outputFile%'} | ForEach-Object {(Get-Content $_.FullName | Select-Object -Skip 1) | Add-Content '%outputFile%'}"

if %errorlevel% == 0 (
    echo 結合が完了しました。
) else (
    echo エラーが発生しました。
)

endlocal
pause
0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?