僕のSheetJSお試し　～VBAマクロ撲滅計画Phase#1 ～

# 導入

今年から**武装派VBAマクロ撲滅組織**を独りでに立ち上げました。 
僕がVBAマクロを撲滅したい理由は

- VBAくらい使用場面が少ない（オフィスのソフトを操作するときぐらいしか使えない）言語をわざわざ覚えるのが面倒。ググるのすら面倒。
- エクセルのバージョンが変わったときに野良VBAどもをかき集めて修正するのが面倒。
- あの無機質なエディタを使うのが嫌。
- VBAはVBAでしかなく汎用性がない。（業務効率化のツールならもっとRPAばりにマウスカーソルの操縦とか画像認識とかさせて色々やらせたい。）

世の中に3000億人くらいいるVBAプロフェッショナルアドバイザーの方々からすると「いやいや、それは君のレベルが低いだけでVBAは偉大な存在だ」って感じかもしれないけども、とにかく僕はVBAが嫌だ。

個人的にはシステム開発でバックエンドでメインで使っている**java**、フロントエンド開発で使う**JS**、あとプラスでなんでも屋さんな言語（候補は**Python**）で業務の効率化を図りたいと考えています。

Phase#1と言っているがPhase#2があるのかは謎。

# Phase#1では
Phase#1ではエクセルをJSで操作するための**SheetJS**とかいうAPIをみつけたので、こいつを試しで使ってみようと思います。
あと意外とSheetJSで調べても見つからなかった処理を実装してみました。（レベルが低すぎて逆になかったのかな。。。

# 今回作るもの
今回は日本で7000億人のエンジニアが苦しめられている
**「アクティブセルA1、シート倍率100%」問題**
に立ち向かうツールを作りたいと思います。
僕自身官公庁案件にいたときに、この問題が原因で激づめされた記憶があるのでこれは良い題材かなと。
（あと、シンプルに簡単だろうなと）

# 成果物
結論以下のようなソースとなりました
<details><summary>ソース</summary>

```HTML
<!DOCTYPE html>
<html lang="ja">

<head>
	<title>設計書汎用整形ツール</title>
	<meta charset="UTF-8">
	<link rel="preconnect" href="https://fonts.googleapis.com">
	<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
	<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP&family=Roboto:ital,wght@1,300;1,700&display=swap"
		rel="stylesheet">
	<style>
		* {
			font-family: 'Noto Sans JP', 'Roboto', sans-serif sans-serif;
		}

		body {
			text-align: center;
		}

		h1.tool-title {
			background-color: darkblue;
			color: white;
			padding-left: 1em;
		}

		h2 {
			background-color: lightblue;
			color: darkblue;
			padding-left: 1em;
		}

		button {
			margin-top: 1em;
			background-color: blue;
			border-radius: 50px;
			color: #fff;
			padding: 15px 50px;
			font-size: medium;
		}
	</style>
</head>

<body>
	<div id="app">
		<h1 class="tool-title">設計書汎用整形ツール</h1>
		<h2>INPUT</h2>
		<input type="file" id="excelFile" /><br>
		<button v-on:click="doFormat">整形</button>
	</div>
</body>
<script src="https://unpkg.com/vue@2.5.17"></script>
<script src="https://unpkg.com/xlsx/dist/xlsx.full.min.js"></script>
<script src="./document_check_logics/checkExtension.js"></script>
<script>
	// ロードされ、Vueがグローバル変数として定義されているか確認
	console.assert(typeof Vue !== 'undefined');
	// ファイル不正メッセージ
	const FILE_FORMAT_ERROR_MSG = "ファイルの拡張子が不正です。";

	new Vue({
		el: '#app',

		methods: {
			/**
			 * 「チェック開始」ボタン押下時のイベント
			*/
			doFormat: function () {
				const vm = this;
				vm.errorList = [];

				// 拡張子チェック
				const fileName = document.getElementById("excelFile").files[0].name;
				if (checkExtension(fileName) === false) {
					alert(FILE_FORMAT_ERROR_MSG);
					return;
				}

				vm.fileName = fileName;

				// ファイル内容取得および整形の実処理部分
				let fileReader = new FileReader();
				fileReader.onload = function (event) {
					
					// ファイル内容取得
					let uint8 = new Uint8Array(event.target.result);
					let workBook = XLSX.read(uint8, { type: "array" });

					// シート名一覧取得
					const workSheetNames = Array.from(workBook.SheetNames);
					// ファイル名をチェックして処理を実行
					workSheetNames.forEach((workSheetName, index) => {
						// アクティブセルを"A1"に移動
						workBook.Sheets[workSheetName]['origin'] = "A1";
						// 表示倍率を100%に変更
						workBook.Sheets[workSheetName]['scale'] = 1;
					});
					
					XLSX.writeFile(workBook, fileName);
				}
				// ファイル読み込み
				let file = document.getElementById("excelFile").files[0];
				fileReader.readAsArrayBuffer(file);
			},
		}
	});
</script>

</html>
```
</details>

# ソースの中身について

あくまで、簡易的なツールなので、エラーハンドリングしていない箇所が多々ありますが、お見逃しを。

## CDNでVue、SheetJS諸々の読み込み

L52～L54
```HTML
<script src="https://unpkg.com/vue@2.5.17"></script>
<script src="https://unpkg.com/xlsx/dist/xlsx.full.min.js"></script>
<script src="./document_check_logics/checkExtension.js"></script>
```

最後の`checkExtension.js`は自作のJSファイルです。
ただアップロードされたファイルの拡張子がxlsx,xls,xlsmかチェックするだけのFunctionが定義されてます。

## ファイルの読み込みとアクティブセル、表示倍率変更

L83～L100

```js
fileReader.onload = function (event) {
					
					// ファイル内容取得
					let uint8 = new Uint8Array(event.target.result);
					let workBook = XLSX.read(uint8, { type: "array" });

					// シート名一覧取得
					const workSheetNames = Array.from(workBook.SheetNames);
					// ファイル名をチェックして処理を実行
					workSheetNames.forEach((workSheetName, index) => {
						// アクティブセルを"A1"に移動
						workBook.Sheets[workSheetName]['origin'] = "A1";
						// 表示倍率を100%に変更
						workBook.Sheets[workSheetName]['scale'] = 1;
					});
					
					XLSX.writeFile(workBook, fileName);
				}
```

上記の箇所がこのツールの処理の核部分になります。
やっていることは単純で各ワークシートオブジェクトの`origin`プロパティと`scale`プロパティにA1(アクティブセルをA1にする)と1（表示倍率100%）をそれぞれ設定しているだけです。
なんのプロパティに値を設定したらいいかわからなかったんですが、純度100%の勘でプロパティ名を書いたらうまくいきました。

## ファイルの出力
L99

```js
XLSX.writeFile(workBook, fileName);
```

最後にファイルを出力してます。

# 動作確認

テストで動かしてみます。

## テストファイル
シートが3つあり、かつ、各シートがアクティブセル、表示倍率パッパラパーのエクセルを用意しました。

<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549748/eac29e51-ffb6-8488-da78-1209a91e690e.png">
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549748/83dfbdb0-224e-4ccb-f3d9-c1352ca366a3.png">
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549748/d102e7dd-5a49-fcc7-27a0-cbea79fe55dc.png">

## 画面

このあまりにもダサい画面にアップロードします↓

<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549748/d6fdec97-8dc2-96ad-90f4-caeba2469c67.png">

ファイルを選択してボタン押下↓
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549748/d7cdcc81-9e18-aff4-b7f1-2e5f1207921c.png">

すると整形？されたファイルがダウンロードできます。
ダウンロードしたファイルは中身は↓のようにアクティブセルがA1、表示倍率100%になっております。
（他のシートも同様）

<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549748/e833079c-de31-2ee8-d4d7-18fe18ffcc92.png">

これで全国の悩めるエンジニアとGO!皆川を救うことができました。
きっとこんなツールは死ぬほどあるけどいい勉強になりました。