(これはちょっと先日に書いたブログ「DXな対応」のつづき)
会社でちょっとしたニーズがあって、Excelのシート(かなり沢山ある100以上かな😂)をひとつのシートにまとめてピボットで処理したいとのこと。であれば一つのCSVにまとめた後に再度Excelで読み込んで並び替えればいいので、まずはCSVにまとめるプログラムをChatGPTを使って作成した。(ある程度は、会社でやったんだけど、時間的制約があるので、自学のために自宅🏠でやり直してみた。)
僕もVBScriptのプログラミングは超久しぶりだったけど、それなりに検証できたので、多少のプログラミングスキルがあれば、作ることができると思います。
まずは、どんなプログラムを作ればいいかを事前にChatGPTに相談した、そして、それっぽいプログラムをネットで拾って来て、そのプログラムをChatGPTのプロンプトへ依頼とともに渡した「複数のExcelファイルをドラッグ&ドロップすると、それぞれのExcelブック内の複数シートを一つのCSVにまとめるVBScriptのプログラムを作成して下さい。なお、以下のプログラムを参考にしてください。」と、
すると、いい感じのプログラムを生成してくれた。
そして、あらかじめ作成しておいたテスト用のExcelファイルをこのプログラムファイルにドロップしてみると、
残念😭
一発ではうまくいかなかった。エラーの内容をChatGPTに渡して、その都度プログラムを修正してもらうことにした。主なものとしては、変数名の重複、メッセージの文字化けとかがあったので指摘した。(終始ソースコードには一度も手を加えることは無く、ChatGPTに生成してもらった)
そして、見事に完成✌️
プログラムの修正を何度か繰り返して、やっと動作させることができた。ついでに複数のExcelブックを読み込む機能も追加した。(すぐに完成すると思ってたので、ちょっと心が折れかけた😩)
何度かの修正のうち、最初の数回は僕の環境に問題があって、実はExcelがインストールされてなくて😂、フリーのLibreOfficeでExcelファイルを使ってたから、LibreOfficeに対応する部分で手こずってしまった。
VBScriptではExcelを以下のように読み込むんだけど、インストールされて無いもんだから、当然エラーで動かない😆
Set xlsAp = CreateObject("Excel.Application")
LibreOfficeを制御するためには、COMオブジェクトを介してLibreOfficeを操作する必要があるとのこと。LibreOfficeをバックグラウンドで起動したりする対応を追加してくれた。(これはこれで勉強になった)
なんだか、ややこしいようだけど、それをChatGPTはサクッと解決してくれた。
そして、いろんな注文をChatGPTにお願いして、ようやくプログラムが完成した。あわせて、動作確認もサクッと完了したんだけど、目標のExcel環境でも確認したかったので、コロナ前に納戸の奥に片付けていたExcelの入った古いノートパソコンを引っ張り出して、検証をとり、こちらのパターンも動かすことができた。
いろんな奮闘があったけど、最終的に1時間ちょっとの時間でプログラムを完成させることができた。でも、このプログラムを作成する手間って、側(はた)から見ると、このシートを統合する作業を手作業でやってもあんまり変わらないように見えちゃうんだよねぇ(実際に手作業に負けちゃった😅)。でも、次からの実行は瞬殺なわけなので、これを定期的(月一とか)に繰り返していたら、とんでもないコスト差がつくと思う。そういったところが重要なんですよね🥸
ついでにだけど、時間があったので、勉強のためにJScript版とPowershell版、あとVBA版も追加で作ってみた。ChatGPTはサクッとスクリプトを生成してくれたので、簡単に確認することができた。
それぞれを試してみた結果だけど、VBA版は一般的なので別として、JScript版はVBScript版と同じくWindows Script Host (WSH)で動作するので、使い勝手が同じく非常に便利なんだけど、Powershell版は、shellから起動するか、実行前に一時的なポリシー設定をする必要があるので、ちょっと使い勝手が悪いかなと思った。
あとは、プログラミングについて、今回は超簡単なプログラムだったんだけど、とはいっても、VBScript、JScript、Powershellのプログラムを随分と組んでなかったので、すぐにプログラミングしろと言われたら、簡単にできるようなもんじゃ無いと思う。読むのもキツイかな、いや、CTFやってるんだから、そりゃ無いか😆
でも今は充分なスキルが無くても、ChatGPTやGeminiなどのLLMを利用したら、要件をしっかり伝えることができれば、簡単にプログラムを完成することができて、本当に便利になったもんだ。
さらに今回は無料版でやってここまでできたんだから、これが有料版だったら、さらに複雑で正確なものを作ってくれるんだろう、これから将来の姿を考えたら、すごく期待できるし、これを使いこなすかどうかで、すごく差が出るんでしょうね。
あと、おまけで、作成者を追加しておいた。ChatGPTのアドバイスで、以下のコメントも追加しておいた。
作成者: BorderHarry
本プログラムは、OpenAIが提供するAIモデル「ChatGPT」を利用し、その助言やコード生成を活用して作成されました。一部の内容は、ChatGPTによる提案を基にBorderHarryが編集および補足しています。
以上
付録に以下が生成したソースコードです。プログラム中のコメントを多く記述してもらったので、理解しやすいと思います。ただ、ご利用はご自由ですけど、これを使って何か問題が起こっても僕は一切の責任を負いませんのでよろしくお願いします。
(ファイル名をExcelSheet2CSV.vbsとして保存して下さい。)
横スクロールします。
'ExcelSheet2CSV.vbs
'----------------------------------------------------------------------
' 2024.12.27
' 作成者: BorderHarry with ChatGPT
'
' 本プログラムは、OpenAIが提供するAIモデル「ChatGPT」を利用し、
' その助言やコード生成を活用して作成されました。一部の内容は、
' ChatGPTによる提案を基にBorderHarryが編集および補足しています。
'
' 目的:このスクリプトは、複数の Excel ワークブックを CSV 形式に変換します。
' 機能:
' - 非表示シートを CSV 出力に含めるかどうかを選択可能。
' - すべての Excel ファイルを 1 つの CSV に統合するか、個別に保存するかを選択可能。
'
' 必要条件:
' Microsoft Excel がインストールされている必要があります。
' このスクリプトは、Excel COM オブジェクトを使用してワークブックを操作します。
'----------------------------------------------------------------------
Option Explicit
On Error Resume Next
'-------------------------------------------------------
' 初期設定
'-------------------------------------------------------
' すべてのファイルを 1 つの CSV に統合するかどうかを指定します。
' - True の場合: すべてのファイルを 1 つの統合 CSV ファイルとして保存します。
' - False の場合: 各 Excel ファイルを個別の CSV ファイルとして保存します。
Dim combineFiles
combineFiles = True
'combineFiles = False
'-------------------------------------------------------
' メイン処理
'-------------------------------------------------------
' スクリプトに渡された引数を確認します。
If WScript.Arguments.Count = 0 Then
MsgBox "No Excel file specified. Please drag and drop an Excel file onto the script or run it with a file path as an argument.", vbExclamation, "Error: No File Provided"
WScript.Quit
End If
' Excel アプリケーション オブジェクトを初期化します。
' このオブジェクトを使用して Excel ワークブックを操作します。
Dim xlApp
Set xlApp = CreateObject("Excel.Application")
' Excel アプリケーションが初期化できなかった場合、スクリプトを終了します。
If Err.Number <> 0 Then
MsgBox "Microsoft Excel is not installed. Please check your system.", vbCritical, "Error: Excel Not Found"
Set xlApp = Nothing
WScript.Quit
End If
' ファイル操作用に FileSystemObject を作成します。
Dim objFSO
Set objFSO = CreateObject("Scripting.FileSystemObject")
' combineFiles が True の場合に最終的な CSV 内容を保持する変数を初期化します。
Dim finalCsvOutputText
finalCsvOutputText = ""
' スクリプトに渡されたすべてのファイルを処理します。
Dim i
For i = 0 To WScript.Arguments.Count - 1
' 各ファイルを ConvertToCsv 関数で処理します。
Dim tempCsvOutput
tempCsvOutput = ConvertToCsv(WScript.Arguments(i))
' combineFiles が True の場合、CSV 内容を統合用の変数に追加します。
If combineFiles Then
finalCsvOutputText = finalCsvOutputText & tempCsvOutput
End If
Next
' combineFiles オプションが有効な場合、統合された CSV 内容をファイルに保存します。
If combineFiles Then
Dim finalCsvPath
' スクリプトと同じディレクトリに統合された CSV ファイルを保存します。
finalCsvPath = objFSO.GetParentFolderName(WScript.ScriptFullName) & "\combined_output.csv"
' 統合 CSV ファイルを作成して内容を書き込みます。
Dim textFile
Set textFile = objFSO.CreateTextFile(finalCsvPath, True)
textFile.Write finalCsvOutputText
textFile.Close
' MsgBox "Combined CSV file has been created: " & finalCsvPath, vbInformation, "Process Complete"
End If
' Excel アプリケーションを終了し、リソースを解放します。
xlApp.Quit
Set objFSO = Nothing
Set xlApp = Nothing
' 処理完了の通知をユーザーに表示します。
MsgBox "The process has been completed successfully!", vbInformation, "Process Complete"
'-------------------------------------------------------
' Excel ワークブックを CSV に変換する関数
'-------------------------------------------------------
Function ConvertToCsv(xlBookPath)
' 指定された Excel ワークブックの内容を CSV 形式に変換します。
' パラメータ:
' - xlBookPath: 処理対象の Excel ワークブックのファイルパス。
' 戻り値:
' - combineFiles が True の場合: CSV 内容を文字列として返します。
' - combineFiles が False の場合: 個別の CSV ファイルを作成します。
Dim xlBook, xlSheet, xlSheetCount
Dim CsvOutputText, CsvDelimiter
Dim bookName
' CSV 出力で使用する区切り文字(この場合はカンマ)を定義します。
CsvDelimiter = ","
' 指定されたパスの Excel ワークブックを開きます。
Set xlBook = xlApp.Workbooks.Open(xlBookPath)
' ワークブック名を取得します。
bookName = objFSO.GetFileName(xlBookPath)
' ワークブック内のシート数を取得します。
xlSheetCount = xlBook.Worksheets.Count
' このワークブックの CSV 出力用のテキストを初期化します。
CsvOutputText = ""
' ワークブック内のすべてのシートをループ処理します。
For Each xlSheet In xlBook.Worksheets
Dim row, col, lastRow, lastCol
' ブック名とシート名をヘッダーとして出力に追加します。
CsvOutputText = CsvOutputText & "### Book: " & bookName & " - Sheet: " & xlSheet.Name & vbCrLf
' 現在のシートで使用されている最終行と最終列を取得します。
lastRow = xlSheet.UsedRange.Rows.Count
lastCol = xlSheet.UsedRange.Columns.Count
' データを CSV 用に整形しながら各セルをループ処理します。
For row = 1 To lastRow
Dim rowText
rowText = ""
For col = 1 To lastCol
Dim cellValue
cellValue = xlSheet.Cells(row, col).Text
' セルの値を CSV 行に追加し、必要に応じて引用符をエスケープします。
If col > 1 Then rowText = rowText & CsvDelimiter
rowText = rowText & """" & Replace(cellValue, """", """""") & """"
Next
CsvOutputText = CsvOutputText & rowText & vbCrLf
Next
Next
' combineFiles の設定に応じてファイル出力を処理します。
If combineFiles Then
' CSV 内容を文字列として返します。
ConvertToCsv = CsvOutputText
Else
' 個別の CSV ファイルの出力パスを生成します。
Dim CsvPath
CsvPath = objFSO.GetParentFolderName(xlBookPath) & "\" & objFSO.GetFileName(xlBookPath)
CsvPath = Replace(CsvPath, ".xls", "_converted.csv")
CsvPath = Replace(CsvPath, ".xlsx", "_converted.csv")
' CSV ファイルを作成して内容を書き込みます。
Dim textFile
Set textFile = objFSO.CreateTextFile(CsvPath, True)
textFile.Write CsvOutputText
textFile.Close
' MsgBox "CSV file has been created: " & CsvPath, vbInformation, "File Created"
End If
' ワークブックを保存せずに閉じます。
xlBook.Close False
' ワークブック オブジェクトを解放します。
Set xlBook = Nothing
End Function
本当に細かいことを書くと、個別のCSVファイル名を組み立てているところとか、まだまだ改善の余地があるようだけど、動いて、使えればいいかな😚と、それと、セル単位で処理してるので、拡張すればいろんなことができそう🤔
やってて思ったのはExcelを制御するVBScript、VBAのプログラムは利用者が多いから、ネット上に沢山公開されているので、LLMが学習している濃度(僕のイメージ)が濃いいので、かなり賢く教えてくれると確信しました。
あとは、こういうツールがgithubみたいな方法で、社内にいっぱい転がっていれば、いちいちプログラム組むような苦労しなくてよくて、こういう発想が所謂、DXなんだろうけどなぁ🧐
最後に、これって自宅でやる場合は、今勉強してるPythonやR言語だったら、リソースが揃っているので瞬殺案件なんですよね🤣
(つづきがあります)