csvの予定をカレンダーにインポートできる iCal 形式に変換する csv2ical を JavaScript で作った

## やりたかったこと
　Excel 等で作成した予定を、一括でAppleのカレンダーアプリに登録したかった。
ググると、一度 Google カレンダーに CSV 形式のものを一括インポートして、それをエクスポートしたものをAppleカレンダーに読み込ませるとあった。
　そのためには１行目に項目識別のキーワードを入れた次のような表を作って CSV に書き出した。

■ 表データ（Excelなどで）
| Subject | Start Date | Start Time | End Date | End Time |
|:-:|:-:|:-:|:-:|:-:|
| 出勤 | 2023/2/10 | 9:00  |  2023/2/10 |  15:00 |
| 出勤 | 2023/2/11 | 9:00  |  2023/2/11 |  15:00 |
| 出勤 | 2023/2/12 | 9:00  |  2023/2/12 |  15:00 |
|   |   |   |   |   |

■ csvデータ
```csv:
Subject,Start Date,Start Time,End Date,End Time
出勤,2023/2/10,9:00,2023/2/10,15:00
出勤,2023/2/11,9:00,2023/2/1,15:00
出勤,2023/2/12,9:00,2023/2/12,15:00
```
## Google カレンダーへのインポートできず！
　ググった記事には CSV 形式でインポートできるとあったが、できなくなったみたい。
![GoogleCalImport.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16491/26615512-0e1e-0789-e007-550b416e51e4.png)

　iCal または　VCS形式ならインポートできると！　（それ以外は受け付けない）

## CSV を iCal に変換しよう！
　せっかく作った CSV データを iCal 形式に変換する方法を探してみたら、次のサイトがあった。
https://csv-to-ical.chimbori.com/
早速試すと、ちゃんと Appleカレンダー、Googleカレンダーのどちらにも一括登録できるデータが出来上がった。

## 自分でも作れるのでは？
　これまでの経緯で、当初の目的は果たせたのだが、プログラミングの血が騒いで、変換プログラムを作りたくなった。
　JavaScript に CSV 形式をパースするライブラリがあるようだが、データの配列順を変えない前提で、通常のテキストとして単純に処理するようにした。（１行目のデータは無視（笑））
ということで、HTMLで GUI を、 JavaScript で処理する形式て、単一ファイルの Webアプリとした。

```html:csv2iCal
<!doctype html>
<html>
<head>
<meta charset="utf-8"></meta>
<title>CSV to iCalコンバータ</title>
</head>

<body>
<h3>CSV to iCal コンバータ</h3>
<div>
	<h3>変換前</h3>
	<form name="inputForm">
		<input name="inFile" type="file" /><br />
		<textarea name="inData" cols="80" rows="10"></textarea>
	</form>
	<h3>変換後</h3>
	<form name="outForm">
		<textarea name="outData" cols="80" rows="20"></textarea>
		<a id="btn" download="iCal.ics">ダウンロード</a>
	
	</form>
</div>
<script type="module">
	var form = document.forms.inputForm;
	form.inFile.addEventListener( 'change', function(e) {
		const result = e.target.files[0];
		const reader = new FileReader();
		reader.readAsText( result );
		reader.addEventListener( 'load', function() {
			form.inData.textContent = reader.result;
			document.forms.outForm.outData.textContent = conv(reader.result.split("\r"));	// 改行コードに注意
		})
	})
	var conv = function(csv) {
		let iCal = "BEGIN:VCALENDAR\r";
		iCal += "VERSION:2.0\r";
		iCal += "CALSCALE:GREGORIAN\r";
		iCal += "X-WR-CALNAME;VALUE=TEXT:iCal\r";
        for (let i = 1; i < csv.length; ++i) {    // 1行目を無視
			let cells = csv[i].split(",");
			if (cells.length != 1) {
				let event = makeEvent(cells);
				iCal += event;
			}
		}
		
		iCal = iCal + "END:VCALENDAR\r";
		return iCal;
	}
	var makeEvent = function(cells) {
		let ev = "BEGIN:VEVENT\r";
		ev += "SUMMARY:" + cells[0] + "\r";
		ev += "DTSTAMP:" + dateConv(cells[1]) + "T" + timeConv(cells[2]) + "\r";
		ev += "DTSTART:" + dateConv(cells[1]) + "T" + timeConv(cells[2]) + "\r";
		ev += "DTEND:" + dateConv(cells[3]) + "T" + timeConv(cells[4]) + "\r";
		
		ev += "END:VEVENT\r";
		return ev;
	}
	var dateConv = function(dateIn) {
		const dw = dateIn.split("/");
		return dw[0] +  ("0" + dw[1]).substr(-2) +  ("0" + dw[2]).substr(-2)
	}
	var timeConv = function(timeIn) {
		const tw = timeIn.split(":");
		return ("0" + tw[0]).substr(-2) + ("0" + tw[1]).substr(-2) + "00";
	}

</script>

<script type="module">
	const btn = document.getElementById('btn');
	console.log("btn");
	btn.addEventListener('click', function() {
		const blob = new Blob([document.forms.outForm.outData.textContent], {"type": "text/plain"});
		btn.href = window.URL.createObjectURL(blob);
	})
</script>

</body>
</html>
```

## 使い方
　このHTMLファイルを Web ブラウザーで開いて、「ファイルを選択」で csv 形式のデータを開くと、すぐに iCal データに変換します。あとは「ダウンロード」すれば、テキストファイルとしてダウンロードされます。（下の画像）

![スクリーンショット 2023-02-09 13.35.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16491/2525a489-e51d-76a5-717c-c6019dc40478.png)

## 注意
　macOS で動作していますが、Windows だと、文字コード、改行コードが違って正常に動作しないかもしれません。その際は適当に JavaScript の68行目を修正してお使いください。
また、冒頭で書いているようにデータの並びに依存していますので、それに合わせてください。