ファイル名一覧を取得するバッチ処理

# はじめに
業務効率化のためにバッチファイルを作成したときのことをまとめます。
（Webアプリ開発とは毛色が違いますが、あくまでも効率化の一手段として捉えています）

# バッチ処理とは
コンピュータがデータをまとめた後で一括処理する方式です。
コンピュータ黎明期から使われてきた歴史の長い処理方式で、メインフレームといった企業の基幹業務システムに用いられる大型コンピュータで利用されてきました。

![20220129112250.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677000/51db17fe-11fb-2eca-0f78-7a5dbe4c6f43.jpeg)
>画像引用：[バッチ処理とオンライン処理の違い](https://req-definer.com/entry/batch-and-online)

## 実例
- 月次の売上げデータや販売データの処理
- 社員の勤怠管理や給与計算
- アプリケーションの自動実行

## メリット
- 大量のデータを短時間で処理できる
- 定期的な処理の自動化ができる（夜間実行することも可能）
- 自動処理のため正確性があり、ヒューマンエラーを減らせる

## デメリット
- リアルタイム処理のように、データの即時反映が難しい
- 柔軟性の低さ（エラーが発生した時に処理全体が中断し、復旧に時間がかかる場合がある）
- 環境依存（バッチ処理のプログラムは実行環境に依存しやすい）

# 業務内容
- 業務でリース返却対象PCのデータ消去時のログをクラウド上で管理している
- 消去済みのPCの「シリアルナンバー」と、「消去日」をExcelのリストに入力している
- なお、データ消去は多い時には、3~4日で100台くらい実施する場合もある
- ログファイル名は、「No_シリアル.pdf」のような形式で保存している

## 問題点
目視でログを確認しながら入力していると、入力ミスをする可能性があるし、工数がかかる

### イメージ
個人用のPCでフォルダの状況を再現した（つもりです）
エラー出ているのは無視してください。

これで数十台〜百数十台分のファイルがあって、番号もバラバラだと確認に時間がかかる
![スクリーンショット 2024-10-12 085030.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677000/d9038ec0-9aa3-db87-3dea-02c7e047c3c6.png)


## 解決方法
- クラウド上のファイル名の一覧をコピーし、Excelファイルにペーストする
- ファイル名を検索値として、既存のリストでVLOOKUP（XLOOKUP）検索を実行してリスト更新する

# 実現したこと
1. バッチ処理でWindowsエクスプローラーからクラウド上のファイル名一覧をコピー ◀︎ **今回の投稿**
2. マクロ付きExcelファイル（.xlsm）のパスをPowerShellに引数として渡す ◀︎ **今回の投稿**
3. PowerShellでマクロを実行する ◀︎[別記事の投稿](https://qiita.com/k12da/items/7a0ed02caa77b4c329e3)
4. 取得したファイル名一覧をマクロでExcelのシートにコピペする ◀︎[別記事の投稿](https://qiita.com/drafts/c240cfb3de1666d724c7)

コードをすぐに見たい方は[こちら](#作成したコード)から

## PowerShellとは？
- Microsoftが開発したスクリプト言語およびキャラクターユーザーインターフェイス（CUI） の1つです
- タスク自動化と構成管理によく使用されるシェルです
- Windows11にも標準搭載されていて、インストールは不要

### なぜPowerShellを使うのか？
#### 結論
言語の特性上で、バッチファイルから直接マクロを呼び出して実行することはできないため。

### VBScriptの代替手段
長年WindowsOSに標準搭載されていた**VBScript**というスクリプト言語が、[2023年10月に非推奨](https://news.mynavi.jp/techplus/article/programinglanguageoftheworld-50/)となったためです。

Microsoft社が今後のリリースからオンデマンド機能として利用できるようにしながら、段階的に廃止すると言っています。

そのため代替手段として、同じくWindowsOSに標準搭載されている**PowerShell**を採用しました。
PowerShellに関しては、[別の記事](https://qiita.com/k12da/items/7a0ed02caa77b4c329e3)で投稿しています。

# バッチファイルの作り方
1. テキストエディタで新しいファイルを作成する（メモ帳、Visual Studio Codeなど）
2. 実行したいコマンドを記述する
3. 拡張子を`.bat`に変更して保存する
4. バッチファイルを実行する（ダブルクリックするか、コマンドプロンプトでファイル名を指定して実行する）

:::note warn
バッチ実行した時に**文字化けして表示**されることがあります。
これは特定の文字コードで作成されたファイルが、別の文字コードで保存される場合によく発生します。

その場合は、以下のスクショのように**エンコード**から文字コードを変更することで解決することが多いです。

![スクリーンショット 2024-10-12 125053.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677000/9b894b94-d03f-d6a6-0f5d-06005f40fc59.png)
:::

# 作成したコード
:::note warn
パスは例です。実行環境によって異なります。
:::

```
@echo off
REM ユーザーIDを入力
set /p inputuserid=""
set userid=%inputuserid%

REM 選択肢から選ぶ
set /p selectedoption=choise /c 12 /m Trick or Treat🎃(1: お菓子, 2: いたずら): 
if %selectedoption%==1(
  set halloween=お菓子
) else (
  set halloween=いたずら
)

REM フォルダ名の日付を入力
set /p inputdate=""
set foldername=%inputdate%

REM 設定した動的なパスに移動
cd "C:¥Users¥%userid%¥パス¥%halloween%¥%foldername%"

echo %cd%

REM クリップボードにコピー
dir /b /a-d | clip

REM マクロ付きExcelのファイルパスを格納した変数
set macropath ="C:¥Users¥%userid%¥macro.xlsm"

REM PowerShellを実行する
powershell -ExecutionPolicy RemoteSigned -File "C:¥Users¥%userid%¥call₋macro.ps1" -filePath "%macropath%"
```

## コードの説明・補足
### `@echo off`
コマンドの実行結果をコマンドプロンプトに表示しないように設定します。
これがないと処理を実行するたびにコマンドも表示されてしまいます。

`echo off`と定義すると、最初の`echo off`だけ表示されてしまうので先頭に`@`を加えて定義します。

### `echo`
- 変数の値や文字列をコマンドプロンプトに表示します
- エコー機能のオンオフを設定します

#### エコー機能とは
コンピュータが受け取った情報をそのまま出力することです。
- `echo on`: 実行するコマンドを画面に表示します
- `echo off`: 実行するコマンドを画面に表示しません（上記の`@echo off`のように記述するのが一般的です）

##### エコー機能をオフにする理由
- **見やすさ**： バッチファイルの実行結果だけを表示することで見やすくなります
- **セキュリティ**： パスワードなどの個人情報を入力する場合、画面に表示されることを防ぎます
- **処理の高速化**： コマンドの表示をしないため、処理を高速化することが可能です

### `set`
- 変数に値を代入します
- 変数を展開する時は、変数を`%`で囲みます

```batch
set 変数名=値

echo %変数名%
```

`/p`はオプションで、ユーザーからの入力値を変数へ代入するために使います
```batch
set /p name=名前を入力してください: 
```

### `REM`
コメントアウトする時に使います

:::note info
バッチファイルでは複数行まとめてコメントアウトできないようなので、1行ずつコメントアウトします
:::

### `dir /b /a-d | clip`
現在のディレクトリにあるファイル名のみをクリップボードにコピーします
- `dir`: ディレクトリの内容を表示するコマンドです
- `/b`: 詳細な情報を表示せず、ファイル名のみを簡潔に表示します
- `/a-d`: ディレクトリを除外します。つまり、ファイルのみを表示します
- `|`: パイプ (pipe) です。前のコマンドの出力結果を次のコマンドの入力として渡します
- `clip`: 渡されたファイル名の一覧をクリップボードにコピーします

### `powershell -ExecutionPolicy [実行ポリシー] -File "パス" -filePath "%パス%"`
実行するファイルと実行ポリシーを指定して、PowerShellを起動します
- `powershell`: PowerShellを起動します
- `-ExecutionPolicy [実行ポリシー]`: [実行ポリシー](https://learn.microsoft.com/ja-jp/powershell/module/microsoft.powershell.core/about/about_execution_policies?view=powershell-7.4#powershell-execution-policies)を設定します（今回は`RemoteSigned`に設定しています）
- `-File "パス"`: 実行するスクリプトファイルを指定します
- `-filePath "パス"`: スクリプトに引数を渡します（今回はマクロ付きExcelファイルのパス）

# 結果
クリップボードに[ファイル名](#イメージ)の一覧がコピーされました🙌
![スクリーンショット (13).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677000/02d7b854-d585-c35c-2012-32069b0bfd57.png)


# おわりに
現代ではリアルタイム処理が主流なので、「バッチ処理なんてレガシーな手法じゃん」って思うかもしれません。
しかし全ての処理がすべてリアルタイムで行われるわけではないので、システムの要件などを考慮して使い分けることが重要だと思いました。

# 参考記事
- [バッチ処理について考える](https://qiita.com/koduki/items/e90ee1fea5aa75071d95)
- [バッチ処理とオンライン処理の違い](https://req-definer.com/entry/batch-and-online)
- [PowerShell(パワーシェル)は何ができるの？メリット、使い方、実例まで](https://www.dospara.co.jp/5info/cts_str_pcuse_powershell.html)
- [PowerShell 実行ポリシー](https://learn.microsoft.com/ja-jp/powershell/module/microsoft.powershell.core/about/about_execution_policies?view=powershell-7.4#powershell-execution-policies)