概要
フォルダに格納されているWordファイルを結合します。
指定フォルダ直下のみ処理します(サブフォルダ配下は対象外)。
注意事項
VBAがどうというより、Wordの結合時の仕様として気をつけること。
- 結合元のファイルで同じテンプレート(同じスタイル)を使っていないとスタイルが変更されることがあります。
- 改行の動きとか、クセがあります(2文書結合しようとして、1文書目末尾に改行が入ってないと2文書目の冒頭と文がつながります。1文書目末尾の改行については処理を追加することもできそうです)
ソース
Sub ファイル結合() Dim StartTime As Date '開始時間 Dim EndTime As Date '終了時間 Dim WSH As Variant 'WSH(Windows Scripting Host) Dim DefaultPath As String 'フォルダダイアログで開くときのデフォルトパス Dim FSO As Object 'ファイルシステムオブジェクト Dim FolderPath As String 'ダイアログで指定されたフォルダパス Dim objFolder As Object 'フォルダオブジェクト Dim objFiles As Object 'ファイルオブジェクト Dim objF As Object 'ファイルオブジェクト用for文変数 Dim FileCount As Long '処理するファイル数 Dim FilePaths() '処理するファイルパス(配列) Dim i As Long Dim k As Long Dim temp As String 'ソート用変数 Dim docWord1 As Document 'Wordファイル(1ファイル目) Dim docWord2 As Document 'Wordファイル(2ファイル目以降) Dim SectionBreakFlag As Boolean '結合時のセクション区切りフラグ(True:入れる、False:入れない) Dim MsgRtn As Long Dim strOutputFolder As String '出力先フォルダ Const JoinFormat As Long = wdFormatOriginalFormatting '元のスタイル保持 ''Const JoinFormat As Long = wdUseDestinationStylesRecovery '貼り付け先のスタイル利用 StartTime = Now() '開始時間 Set FSO = CreateObject("Scripting.FileSystemObject") Set WSH = CreateObject("WScript.Shell") '-------------------------------------- 'フォルダと直下のファイルを取得 '-------------------------------------- 'フォルダダイアログ DefaultPath = WSH.SpecialFolders("Desktop") & "\" 'デスクトップに指定 With Application.FileDialog(msoFileDialogFolderPicker) .InitialFileName = DefaultPath 'デフォルトフォルダをデスクトップにする If .Show = True Then FolderPath = .SelectedItems(1) End If End With 'フォルダダイアログで「キャンセル」したので終了 If FolderPath = "" Then Exit Sub 'フォルダ取得 Set objFolder = FSO.GetFolder(FolderPath) 'ファイルが1つもない場合は終了 If objFolder.Files.Count = 0 Then '終了メッセージ MsgBox "指定されたフォルダにはファイルが1つもないので、終了します。", _ vbOKOnly + vbExclamation Exit Sub End If 'ファイル取得 Set objFiles = objFolder.Files '-------------------------------------- 'ファイルパスを取得 '-------------------------------------- '処理するファイル数の初期化 FileCount = 0 For Each objF In objFiles 'Wordのファイルのみ処理 If LCase(FSO.GetExtensionName(objF.Name)) = "doc" Or _ LCase(FSO.GetExtensionName(objF.Name)) = "docx" Then 'ファイルカウント FileCount = FileCount + 1 'ファイルパスを取得するための動的配列を定義 If FileCount = 1 Then ReDim FilePaths(FileCount) Else ReDim Preserve FilePaths(FileCount) End If 'ファイルパスを配列に格納 FilePaths(FileCount) = objF End If Next objF '処理対象のファイルが1つ以下の場合は終了 If FileCount = 0 Then '終了メッセージ MsgBox "指定されたフォルダには処理対象となるファイルが1つもないので、終了します。", _ vbOKOnly + vbExclamation Exit Sub ElseIf FileCount = 1 Then '終了メッセージ MsgBox "指定されたフォルダには処理対象となるファイルが1つしかないので結合不要です。終了します。", _ vbOKOnly + vbExclamation Exit Sub End If '-------------------------------------- 'ファイルパスをソート(ファイル名の昇順で結合するため) '-------------------------------------- For i = 1 To FileCount For k = FileCount To 1 If FilePaths(i) > FilePaths(k) Then temp = FilePaths(i) FilePaths(i) = FilePaths(k) FilePaths(k) = temp End If Next k Next i '-------------------------------------- '結合オプション選択 '-------------------------------------- MsgRtn = MsgBox("結合時に、セクション区切りを入れますか?" & _ vbCrLf & vbCrLf & _ "はい :セクション区切りを入れる" & vbCrLf & _ "いいえ:セクション区切りを入れない", _ vbYesNo + vbInformation) If MsgRtn = vbYes Then SectionBreakFlag = True ElseIf MsgRtn = vbNo Then SectionBreakFlag = False End If '-------------------------------------- 'ファイルを開く '-------------------------------------- For i = 1 To FileCount If i = 1 Then 'ファイルを開く Documents.Open FilePaths(i), ReadOnly:=True Set docWord1 = ActiveDocument docWord1.Repaginate '改ページ自動調整 Else 'セクション区切りを入れる場合 If SectionBreakFlag = True Then 'カーソル位置を最後に Selection.EndKey unit:=wdStory 'ファイルを開く Documents.Open FilePaths(i), ReadOnly:=True Set docWord2 = ActiveDocument docWord2.Repaginate '改ページ自動調整 'コピー Selection.WholeStory Selection.Copy 'セクション区切りを入れて貼り付け docWord1.Activate Selection.InsertBreak Type:=wdSectionBreakNextPage Selection.PasteAndFormat (JoinFormat) 'ファイルを閉じる docWord2.Close SaveChanges:=False 'セクション区切りを入れない場合 Else 'カーソル位置を最後に Selection.EndKey unit:=wdStory '1ファイル目の最後に空行がないと、1ファイル目の最後の行と '2ファイルの最初の行がつながってしまうので改行されてなければ改行。 'カーソル前が改行のASC(13)か判別する。 'ASC(11)は2ファイル目の最初の行のスタイルが意図せず変わる可能性があるので不可 If Asc(Selection.Characters.Last.Previous) = 13 Then Else '改行 Selection.TypeParagraph End If '結合 Selection.InsertFile FileName:=FilePaths(i) End If End If Next i '-------------------------------------- '結合したファイルの出力先フォルダを作成 '-------------------------------------- Do strOutputFolder = FolderPath & "\" & "join_" & Format(Now(), "yymmdd_hhmmss") 'フォルダがなかったら If FSO.FolderExists(strOutputFolder) = False Then 'フォルダ作成 On Error Resume Next FSO.CreateFolder (strOutputFolder) If Err.Number = 0 Then On Error GoTo 0 Exit Do Else MsgBox "出力用フォルダを作成できませんでした。「" & docWord1.Name & "」を自分で保存してください。" & _ vbCrLf & vbCrLf & _ Err.Number & " : " & Err.Description, _ vbOKOnly + vbExclamation Exit Sub End If End If Loop '-------------------------------------- '結合したファイルを保存して閉じる '-------------------------------------- docWord1.SaveAs FileName:=strOutputFolder & "\" & FSO.GetBaseName(docWord1.Name) & _ "_結合_" & Format(Now(), "yymmdd_hhmmss") & "." & FSO.GetExtensionName(docWord1.Name) docWord1.Close SaveChanges:=wdDoNotSaveChanges '-------------------------------------- '終了 '-------------------------------------- '終了時間 EndTime = Now() '終了メッセージ MsgBox FileCount & " ファイル結合しました。" & vbCrLf & vbCrLf & _ "出力先フォルダ:" & strOutputFolder & vbCrLf & _ "処理時間: " & Format(EndTime - StartTime, "hh:mm:ss"), _ vbOKOnly + vbInformation 'オブジェクトクリア Set WSH = Nothing Set FSO = Nothing Set objFolder = Nothing Set objFiles = Nothing Set objF = Nothing Set docWord1 = Nothing Set docWord2 = Nothing End Sub