複数のExcelファイルをPDFに一括変換する

# 概要

`excel2pdf.js`または`excel2pdf.vbs`にExcelファイル(.xls*)をドロップすると、ドロップされた全ファイルをpdfとして保存します。

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

# ソースコード

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

|eachSheet|処理内容|
|:----|:----|
|true|各シート毎にpdfファイルを出力します（1シート1pdf）|
|false|全シートまとめてpdfファイルを出力します（1ブック1pdf）|

|makeSubFolder|処理内容(eachSheet=Trueの場合のみ有効)|
|:----|:----|
|true|ファイルごとにサブフォルダを作成してその中にpdfファイルを保存|
|false|ファイルと同じフォルダにpdfファイルを保存|

|IncludeDocProperties|処理内容|
|:----|:----|
|true|pdfファイルにドキュメント プロパティ(作成者等)を含めます|
|false|pdfファイルにドキュメント プロパティ(作成者等)を含めません|

## JScript

```javascript:excel2pdf.js
// vbsファイルにD&DされたすべてのExcelブックをpdfとして保存する

//-------------------------------------------------------
// 設定
//-------------------------------------------------------

//ここがtrueの場合 ：各シート毎にpdfファイルを出力します（1シート1pdf）
//ここがfalseの場合：全シートまとめてpdfファイルを出力します（1ブック1pdf）
var eachSheet = false;

//eachSheet = trueの場合で、
//ここがtrueの場合 ：ファイルごとにサブフォルダを作成してその中にpdfファイルを保存
//ここがfalseの場合：ファイルと同じフォルダにpdfファイルを保存
var makeSubFolder = false;

//ここがtrueの場合 ：pdfファイルにドキュメント プロパティ(作成者等)を含めます
//ここがfalseの場合：pdfファイルにドキュメント プロパティ(作成者等)を含めません
var IncludeDocProperties = false;

//-------------------------------------------------------
// main処理
//-------------------------------------------------------

var pathadd = makeSubFolder ? "_pdf\\" : "_";  // 出力パス

try {
    // Excelを使用する
    var xlApp = new ActiveXObject("Excel.Application");
    var xlTypePDF = 0;
    var xlQualityStandard = 1;
    var IgnorePrintAreas = false; //ここがTrueの場合印刷範囲を無視して変換

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

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

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

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

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

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

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

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

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

                // シートが非表示でない場合
                if (xlSheet.Visible) {
                    // 出力ファイル名作成
                    PdfPath = MakePdfPath(xlBookPath, xlSheet.Name, xlSheetCount);

                    // シートをpdf保存
                    xlSheet.ExportAsFixedFormat(xlTypePDF, PdfPath, xlQualityStandard, IncludeDocProperties, IgnorePrintAreas);
                }
            }
        } else {
            // ブックをpdf保存
            PdfPath = objFSO.GetParentFolderName(xlBookPath) + "\\" + objFSO.GetBaseName(xlBookPath) + ".pdf";
            xlBook.ExportAsFixedFormat(xlTypePDF, PdfPath, xlQualityStandard, IncludeDocProperties, IgnorePrintAreas);
        }

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

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

    //C:\work\book1.xls
    //makeSubFolder = false C:\work\book1.xls_sheetname.pdf
    //makeSubFolder = true  C:\work\book1.xls_pdf\sheetname.pdf

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

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

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

//-------------------------------------------------------
// eachSheet = trueの場合、シート名をファイル名とするので
// シート名文字列内のファイル名に使えない文字を_に置換
//-------------------------------------------------------
function String2Filename(str) {
    str = str.replace(/"/g, "_");
    str = str.replace(/</g, "_");
    str = str.replace(/>/g, "_");
    str = str.replace(/\|/g, "_");

    return str;
}
```

## VBScript

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

'-------------------------------------------------------
'設定
'-------------------------------------------------------
'ここがTrueの場合 ：各シート毎にpdfファイルを出力します（1シート1pdf）
'ここがFalseの場合：全シートまとめてpdfファイルを出力します（1ブック1pdf）
Dim eachSheet
eachSheet = False

'eachSheet = Trueの場合で、
'ここがTrueの場合 ：ファイルごとにサブフォルダを作成してその中にpdfファイルを保存
'ここがFalseの場合：ファイルと同じフォルダにpdfファイルを保存
Dim makeSubFolder
makeSubFolder = False

'ここがTrueの場合 ：pdfファイルにドキュメント プロパティ(作成者等)を含めます
'ここがFalseの場合：pdfファイルにドキュメント プロパティ(作成者等)を含めません
Dim IncludeDocProperties
IncludeDocProperties = False

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

'Excelを使用する
Dim xlApp
Dim xlTypePDF
Dim xlQualityStandard
Dim IgnorePrintAreas
Set xlApp = CreateObject("Excel.Application")
xlTypePDF = 0
xlQualityStandard = 1
IgnorePrintAreas = False'ここがTrueの場合印刷範囲を無視して変換

'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ブックをpdfに変換する
	ConvertToPdf(WScript.Arguments(i))
Next

'Excelを終了させる
xlApp.Quit

'解放
Set objFSO = Nothing
Set xlApp = Nothing

MsgBox "Completed"

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

	Dim xlBook, xlSheet, xlSheetCount, xlBookExt
	Dim PdfPath

	'拡張子がxls*の場合のみ処理
	xlBookExt = LCase(objFSO.GetExtensionName(xlBookPath)) 'xls
	If Len(xlBookExt) >= 3 And Left(xlBookExt,3) = "xls" Then
		'サブフォルダを作成してその中に保存する場合はフォルダを作成
		If eachSheet = True And 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

		If eachSheet = True Then
			'全てのシートに対して処理
			For Each xlSheet In xlBook.Worksheets

				'シートが非表示でない場合
				If xlSheet.Visible = True Then
					'出力ファイル名作成
					PdfPath = MakePdfPath(xlBookPath, xlSheet.name, xlSheetCount)

					'シートをpdf保存
					xlSheet.ExportAsFixedFormat xlTypePDF, PdfPath, xlQualityStandard, IncludeDocProperties, IgnorePrintAreas
				End If
			Next
		Else
			'ブックをpdf保存
			PdfPath = objFSO.GetParentFolderName(xlBookPath) & "\" & objFSO.GetBaseName(xlBookPath) & ".pdf"
			xlBook.ExportAsFixedFormat xlTypePDF, PdfPath, xlQualityStandard, IncludeDocProperties, IgnorePrintAreas
		End If

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

		'解放
		Set xlBook = Nothing
	End If

End Sub

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

	'C:\work\book1.xls
	'makeSubFolder = False C:\work\book1.xls_sheetname.pdf
	'makeSubFolder = True  C:\work\book1.xls_pdf\sheetname.pdf

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

End Function

'-------------------------------------------------------
'eachSheet = Trueの場合、シート名をファイル名とするので
'シート名文字列内のファイル名に使えない文字を_に置換
'-------------------------------------------------------
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
```

# 参考文献

[Worksheet.ExportAsFixedFormat メソッド (Excel) | Microsoft Learn](https://learn.microsoft.com/ja-jp/office/vba/api/excel.worksheet.exportasfixedformat)  
[Workbook.ExportAsFixedFormat メソッド (Excel) | Microsoft Learn](https://learn.microsoft.com/ja-jp/office/vba/api/excel.workbook.exportasfixedformat)