複数のExcelファイルの全シートをCSVに一括変換する

# 概要

`excel2csv.js`または`excel2csv.vbs`にExcelファイル(.xls*)をドロップすると、ドロップされた全ファイルの全シートがcsvとして保存されます。

* Windows環境でExcelがインストールされている必要があります。
* ドロップされたファイルがExcelファイルかどうかの判定はしていません。

# ソースコード

ソースコード内の`makeSubFolder` `visibleOnly`の値によって挙動が変わります。

|makeSubFolder|処理内容　例としてsheet1,sheet2シートを含むbook.xlsxの場合|
|:----|:----|
|true|サブフォルダbook.xlsx_csvを作成しその中に<br>　sheet1.csv<br>　sheet2.csv<br>の名前で保存|
|false|book.xlsxと同じフォルダ内に<br>　book.xlsx_sheet1.csv<br>　book.xlsx_sheet2.csv<br>の名前で保存|

|visibleOnly|処理内容|
|:----|:----|
|true|非表示シートはcsvにしません|
|false|非表示シート含めてcsvにします|


## JScript

```javascript:excel2csv.js
// vbsファイルにD&DされたすべてのExcelブックの全シートをcsvとして保存する

//-------------------------------------------------------
// 設定
//-------------------------------------------------------
//ここがtrueの場合 ：ファイルごとにフォルダを作成してその中にcsvファイルを保存
//ここがfalseの場合：ファイルと同じフォルダにcsvファイルを保存
var makeSubFolder = false;

//ここがtrueの場合 ：非表示シートはcsvにしない
//ここがfalseの場合：非表示シート含めてcsvにする
var visibleOnly = false;

//-------------------------------------------------------
// main処理
//-------------------------------------------------------
var pathadd = makeSubFolder ? "_csv\\" : "_";  // 出力パス

try {
    // Excelを使用する
    var xlApp = new ActiveXObject("Excel.Application");
    var xlCSV = 6;

    // ファイルシステムオブジェクト
    var objFSO = new ActiveXObject("Scripting.FileSystemObject");

    // すべてのファイルに対して処理
    for (var i = 0; i < WScript.Arguments.Length; i++) {
        var xlBookPath = WScript.Arguments(i);
        ConvertToCsv(xlBookPath);
    }

    // Excelを終了させる
    xlApp.Quit();

    // 解放
    xlApp = null;
    objFSO = null;

    WScript.Echo("Completed");
} catch (e) {
    WScript.Echo("Excel does not exist.");
}

//-------------------------------------------------------
// Excelブックをcsvに変換する
//-------------------------------------------------------
function ConvertToCsv(xlBookPath) { // C:\work\book1.xls
    var xlBook, xlSheet, xlSheetCount, xlBookExt, CsvPath;

    // 拡張子がxls*の場合のみ処理
    xlBookExt = objFSO.GetExtensionName(xlBookPath).toLowerCase();  // xls
    if (xlBookExt.length >= 3 && xlBookExt.substring(0, 3) === "xls") {
        // サブフォルダを作成してその中に保存する場合はフォルダを作成
        if (makeSubFolder) {
            if (!objFSO.FolderExists(xlBookPath + pathadd)) {
                objFSO.CreateFolder(xlBookPath + pathadd);
            }
        }

        // ブックを開く
        xlBook = xlApp.Workbooks.Open(xlBookPath);
        xlSheetCount = xlBook.Worksheets.Count;

        // 全てのシートに対して処理
        for (var i = 1; i <= xlSheetCount; i++) {
            xlSheet = xlBook.Worksheets(i);

            // シートが非表示でない場合 または 非表示関係なく変換する場合
            if (xlSheet.Visible || !visibleOnly) {
                // 出力ファイル名作成
                CsvPath = MakeCsvPath(xlBookPath, xlSheet.Name, xlSheetCount);

                // シートをcsv保存
                xlSheet.SaveAs(CsvPath, xlCSV);
            }
        }

        // ブックを閉じる
        xlBook.Close(false);
        xlBook = null;
    }
}

//-------------------------------------------------------
// 出力ファイル名作成
//-------------------------------------------------------
function MakeCsvPath(filepath, sheetname, count) {

    //C:\work\book1.xls
    //makeSubFolder = False C:\work\book1.xls_sheetname.csv
    //makeSubFolder = True  C:\work\book1.xls_csv\sheetname.csv

    //同一ファイル名がある場合は名前に番号を追加
    var CsvPath, j;

    for (j = 0; j <= count; j++) {
        if (j === 0) {
            CsvPath = filepath + pathadd + String2Filename(sheetname) + ".csv";
        } else {
            CsvPath = filepath + pathadd + String2Filename(sheetname) + j.toString() + ".csv";
        }

        if (!objFSO.FileExists(CsvPath)) {
            return CsvPath;
        }
    }
}

//-------------------------------------------------------
// シート名をファイル名として使用するため、
// シート名に使えない文字を _ に置換
//-------------------------------------------------------
function String2Filename(str) {
    str = str.replace(/"/g, "_");
    str = str.replace(/</g, "_");
    str = str.replace(/>/g, "_");
    str = str.replace(/\|/g, "_");

    return str;
}
```

## VBScript

```vb:excel2csv.vbs
'vbsファイルにD&DされたすべてのExcelブックの全シートをcsvとして保存する
Option Explicit
On Error Resume Next

'-------------------------------------------------------
'設定
'-------------------------------------------------------
'ここがTrueの場合 ：ファイルごとにフォルダを作成してその中にcsvファイルを保存
'ここがFalseの場合：ファイルと同じフォルダにcsvファイルを保存
Dim makeSubFolder
makeSubFolder = False

'ここがTrueの場合 ：非表示シートはcsvにしない
'ここがFalseの場合：非表示シート含めてcsvにする
Dim visibleOnly
visibleOnly = False

'-------------------------------------------------------
'main処理
'-------------------------------------------------------
Dim pathadd
If makeSubFolder Then
	pathadd = "_csv\"
Else
	pathadd = "_"
End If

'Excelを使用する
Dim xlApp
Dim xlCSV
Set xlApp = CreateObject("Excel.Application")
xlCSV = 6

'Excelがないと思われる場合は終了
If Err.Number <> 0 Then
	MsgBox "Excel does not exist."
	Set xlApp = Nothing
	WScript.Quit
End If

'ファイルシステムへのアクセス用
Dim objFSO
Set objFSO = CreateObject("Scripting.FileSystemObject")

'全てのファイルに対して処理
Dim i
For i = 0 to WScript.Arguments.Count - 1
	'Excelブックをcsvに変換する
	ConvertToCsv(WScript.Arguments(i))
Next

'Excelを終了させる
xlApp.Quit

'解放
Set objFSO = Nothing
Set xlApp = Nothing

MsgBox "Completed"

'-------------------------------------------------------
'Excelブックをcsvに変換する
'-------------------------------------------------------
Sub ConvertToCsv(xlBookPath) 'C:\work\book1.xls

	Dim xlBook, xlSheet, xlSheetCount, xlBookExt
	Dim CsvPath

	'拡張子がxls*の場合のみ処理
	xlBookExt = LCase(objFSO.GetExtensionName(xlBookPath)) 'xls
	If Len(xlBookExt) >= 3 And Left(xlBookExt,3) = "xls" Then
		'サブフォルダを作成してその中に保存する場合はフォルダを作成
		If makeSubFolder Then
			If objFSO.FolderExists(xlBookPath & pathadd) Then
				'すでにフォルダがある場合は処理済みとみなす
				Exit Sub
			Else
				'フォルダがない場合は作成
				objFSO.CreateFolder(xlBookPath & pathadd)
			End If
		End If

		'ブックを開く
		Set xlBook = xlApp.Workbooks.Open(xlBookPath)

		'シートの数
		xlSheetCount = xlBook.Worksheets.Count

		'全てのシートに対して処理
		For Each xlSheet In xlBook.Worksheets

			'シートが非表示でない場合 または 非表示関係なく変換する場合
			If xlSheet.Visible = True Or visibleOnly = False Then
				'出力ファイル名作成
				CsvPath = MakeCsvPath(xlBookPath, xlSheet.name, xlSheetCount)

				'シートをcsv保存
				xlSheet.SaveAs CsvPath, xlCSV
			End If
		Next

		'ブックを閉じる
		xlBook.Close False

		'解放
		Set xlBook = Nothing
	End If

End Sub

'-------------------------------------------------------
'出力ファイル名作成
'-------------------------------------------------------
Function MakeCsvPath(filepath ,sheetname, count)

	'C:\work\book1.xls
	'makeSubFolder = False C:\work\book1.xls_sheetname.csv
	'makeSubFolder = True  C:\work\book1.xls_csv\sheetname.csv

	'同一ファイル名がある場合は名前に番号を追加
	Dim j
	For j = 0 To count
		If j = 0 Then
			MakeCsvPath = filepath & pathadd & String2Filename(sheetname) & ".csv"
		Else
			MakeCsvPath = filepath & pathadd & String2Filename(sheetname) & Cstr(j) & ".csv"
		End If
		
		If Not objFSO.FileExists(MakeCsvPath) Then Exit For
	Next

End Function

'-------------------------------------------------------
'シート名をファイル名とするので
'シート名文字列内のファイル名に使えない文字を_に置換
'-------------------------------------------------------
Function String2Filename(str)

	String2Filename = str

	If Instr(String2Filename,"""") > 0 Then
		String2Filename = Replace(String2Filename, """", "_")
	End If

	If Instr(String2Filename,"<") > 0 Then
		String2Filename = Replace(String2Filename, "<", "_")
	End If

	If Instr(String2Filename,">") > 0 Then
		String2Filename = Replace(String2Filename, ">", "_")
	End If

	If Instr(String2Filename,"|") > 0 Then
		String2Filename = Replace(String2Filename, "|", "_")
	End If

End Function
```

# 参考文献

[CreateObject 関数 (Visual Basic for Applications) | Microsoft Learn](https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/createobject-function)
[FileSystemObject オブジェクト | Microsoft Learn](https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/filesystemobject-object)
[Workbooks.Open メソッド (Excel) | Microsoft Learn](https://learn.microsoft.com/ja-jp/office/vba/api/excel.workbooks.open)
[Worksheet.SaveAs メソッド (Excel) | Microsoft Learn](https://learn.microsoft.com/ja-jp/office/vba/api/excel.worksheet.saveas)
[Workbook.Close メソッド (Excel) | Microsoft Learn](https://learn.microsoft.com/ja-jp/office/vba/api/excel.workbook.close)[Application.Quit メソッド (Excel) | Microsoft Learn](https://learn.microsoft.com/ja-jp/office/vba/api/excel.application.quit)
[VBScript でのエラー処理 | Microsoft Learn](https://learn.microsoft.com/ja-jp/office/client-developer/access/desktop-database-reference/handling-errors-in-vbscript)
[VBScript のエラー処理 - IBM Documentation](https://www.ibm.com/docs/ja/rational-clearquest/9.0.0?topic=vbscript-error-handling)
[VBScript のコード記述規則 | Microsoft Learn](https://learn.microsoft.com/ja-jp/previous-versions/windows/scripting/cc392255(v=msdn.10)?redirectedfrom=MSDN)