見出し画像

【ツール】Outlookイベント用ICSファイル生成ツール:PowerShellからHTMLへ

以前、PowerShellスクリプトを使用してOutlookのイベント用ICSファイルを生成するツールについて記事を書きました。

今回は、そのツールをさらに使いやすくするためにHTMLベースに移行した経緯と、新しいツールの紹介をしたいと思います。

なぜHTMLに移行したのか?

PowerShellスクリプトは非常に便利でしたが、いくつかの制限がありました

  1. ユーザーがPowerShellを実行できる環境が必要

  2. セキュリティ設定によってはスクリプトの実行が制限される可能性がある

  3. GUIの作成と管理が少し複雑

これらの課題を解決し、より多くの人が簡単に利用できるようにするため、HTMLとJavaScriptを使用したブラウザベースのツールに移行することにしました。

HTMLベースのツールの特徴

  1. ブラウザさえあれば利用可能です。

  2.  ブラウザで直接開けるため、特別なソフトウェアのインストールが不要です。ローカルで動作するため、データがサーバーに送信されることはありません。

使い方

  1. HTMLファイルをブラウザで開きます。

  2. フォームに必要な情報(イベントのタイトル、日時、場所など)を入力します。

  3. 「ICSファイル生成」ボタンをクリックします。

  4. 生成されたICSファイルをダウンロードし、Outlookで送信またはインポートします。

コード


以下のテキストをメモ帳などに張り付けて.htmで保存すればOK


<!DOCTYPE html>
<html>

<head>
    <title>Outlook イベントICSファイル作成</title>
    <meta charset="UTF-8">
    <style>
        body {
            font-family: 'Segoe UI', Arial, sans-serif;
            margin: 0;
            padding: 20px;
            background-color: #f3f3f3;
        }

        h1 {
            color: #0078d4;
        }

        label {
            display: block;
            margin-top: 15px;
            color: #333;
        }

        input[type="text"],
        input[type="datetime-local"],
        textarea {
            width: 300px;
            margin-top: 5px;
            padding: 5px;
            border: 1px solid #ccc;
            border-radius: 4px;
        }

        button {
            margin-top: 20px;
            padding: 10px 20px;
            background-color: #0078d4;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        }

        button:hover {
            background-color: #005a9e;
        }
    </style>
</head>

<body>
    <h1>Outlook イベントICSファイル作成</h1>
    <label for="eventName">イベント名:</label>
    <input type="text" id="eventName">

    <label for="startDateTime">開始日時:</label>
    <input type="datetime-local" id="startDateTime">

    <label for="endDateTime">終了日時:</label>
    <input type="datetime-local" id="endDateTime">

    <label for="location">場所:</label>
    <input type="text" id="location">

    <label for="description">説明:</label>
    <input type="text" id="description">

    <label for="privateEvent">非公開:</label>
    <input type="checkbox" id="privateEvent">
    <br>
    <button onclick="generateICSFile()">ICSファイル作成</button>

    <script>
        // Event handler for startDateTime change
        document.getElementById('startDateTime').addEventListener('change', function () {
            const startDateTime = new Date(this.value);
            const endDateTime = new Date(startDateTime.getTime() + 60 * 60 * 1000); // Add 1 hour
            document.getElementById('endDateTime').value = formatDateTimeLocal(endDateTime);
        });

        function generateICSFile() {
            const eventName = document.getElementById('eventName').value;
            const startDateTime = new Date(document.getElementById('startDateTime').value);
            const endDateTime = new Date(document.getElementById('endDateTime').value);
            const location = document.getElementById('location').value;
            const description = document.getElementById('description').value;
            const isPrivate = document.getElementById('privateEvent').checked;

            // Correcting file name for Japanese characters
            let eventNameForFile = eventName.replace(/[\\/:*?"<>|]/g, '');
            if (eventNameForFile === '') {
                eventNameForFile = 'Event';
            }

            // Create the ICS file content
            const icsClass = isPrivate ? 'PRIVATE' : 'PUBLIC';
            const icsContent = `BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//hacksw/handcal//NONSGML v1.0//EN
BEGIN:VEVENT
UID:${generateGUID()}
DTSTAMP:${formatDate(new Date())}
DTSTART:${formatDate(startDateTime)}
DTEND:${formatDate(endDateTime)}
SUMMARY:${eventName}
DESCRIPTION:${description}
LOCATION:${location}
CLASS:${icsClass}
END:VEVENT
END:VCALENDAR`;

            // Create a Blob with the ICS content
            const blob = new Blob([icsContent], { type: 'text/calendar;charset=utf-8' });

            // Create a download link and trigger the download
            const link = document.createElement('a');
            link.href = URL.createObjectURL(blob);
            link.download = `${eventNameForFile}.ics`;
            link.click();

            alert('ICSファイルが作成されました。');
        }

        function generateGUID() {
            return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
                const r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
                return v.toString(16);
            });
        }

        function formatDate(date) {
            return date.toISOString().replace(/[-:.]/g, '').slice(0, 15) + 'Z';
        }

        function formatDateTimeLocal(date) {
            const yyyy = date.getFullYear();
            const mm = String(date.getMonth() + 1).padStart(2, '0');
            const dd = String(date.getDate()).padStart(2, '0');
            const hh = String(date.getHours()).padStart(2, '0');
            const min = String(date.getMinutes()).padStart(2, '0');
            return `${yyyy}-${mm}-${dd}T${hh}:${min}`;
        }
    </script>
</body>

</html>

この記事が気に入ったらサポートをしてみませんか?