VBA100本ノック 89本目:2つのフォルダの統合
2つのフォルダをサブフォルダも含めて統合する問題です。
同一フォルダに同じファイル名が存在する場合は更新日時のより新しいファイルを採用します。
ツイートでの見やすさを考慮して、ブック・シート指定等を適宜省略しています。
出題
全サブフォルダの全ファイルを対象としてください。
同一フォルダに同一ファイル名となる場合は、より更新日時の新しいファイルを採用してください。
同一更新日時の場合はどちらでも良い。
※パスは任意
VBA作成タイム
この下に頂いた回答へのリンクと解説を掲載しています。
途中まででも良いので、できるだけ自分でVBAを書いてみましょう。
他の人の回答および解説を見て、書いたVBAを見直してみましょう。
頂いた回答
解説
フォルダ、ファイル、再帰、これらの復習問題です。
最初のフォルダ「A」はフォルダごとコピーしています。
フォルダ「B」コピー時にファイルが既に存在していた場合に更新日付を確認してからコピーしています。
Sub VBA100_89_01()
Dim sPathA As String: sPathA = ThisWorkbook.Path & "\A"
Dim sPathB As String: sPathB = ThisWorkbook.Path & "\B"
Dim sPathC As String: sPathC = ThisWorkbook.Path & "\C"
Dim fso As New FileSystemObject
If fso.FolderExists(sPathC) Then Call fso.DeleteFolder(sPathC, True)
Call fso.CopyFolder(sPathA, sPathC, True)
Call copyFile(fso, fso.GetFolder(sPathB), sPathB, sPathC)
Set fso = Nothing
End Sub
Sub copyFile(ByVal fso As FileSystemObject, ByVal fromFolder As Folder, ByRef fromRoot As String, ByRef toRoot As String)
Dim sToPath As String
sToPath = repFolderName(fromFolder.Path, fromRoot, toRoot)
If Not fso.FolderExists(sToPath) Then
Call fso.CopyFolder(fromFolder, sToPath, True)
Exit Sub
End If
Dim oFile As File, sFilePath As String
For Each oFile In fromFolder.Files
sFilePath = repFolderName(oFile.Path, fromRoot, toRoot)
If fso.FileExists(sFilePath) Then
If oFile.DateLastModified > fso.GetFile(sFilePath).DateLastModified Then
Call fso.copyFile(oFile.Path, sFilePath, True)
End If
Else
Call fso.copyFile(oFile.Path, sFilePath, True)
End If
Next
Dim oFolder As Folder
For Each oFolder In fromFolder.SubFolders
Call copyFile(fso, oFolder, fromRoot, toRoot)
Next
End Sub
Function repFolderName(ByVal sFromFolder As String, ByRef sFromFolderR As String, ByRef sRootToR As String) As String
repFolderName = sRootToR & Mid(sFromFolder, Len(sFromFolderR) + 1)
End Function
この処理内容は、DOSコマンドのxcopyで/d指定した場合と同じです。
そこで、WshShellでxcopyを実行するサンプルVBAを記事補足に掲載しました。
補足
xcopy /d /i /e /y "元フォルダ" "先フォルダ"
これを「A」「B」それぞれについて行った結果と同じになります。
ExecまたはRunでコマンドを実行できます。
以下では2通りを紹介しておきます。
「Windows Script Host Object Model」
Dim wsh As New IWshRuntimeLibrary.WshShell
Dim wExec As WshExec
Dim wsh As Object: Set wsh = CreateObject("Wscript.Shell")
Dim wExec As Object
Sub VBA100_88_02()
Dim sPathA As String: sPathA = ThisWorkbook.Path & "\A"
Dim sPathB As String: sPathB = ThisWorkbook.Path & "\B"
Dim sPathC As String: sPathC = ThisWorkbook.Path & "\C"
Dim fso As New FileSystemObject
If fso.FolderExists(sPathC) Then Call fso.DeleteFolder(sPathC, True)
Set fso = Nothing
Dim sLogFile As String
sLogFile = ThisWorkbook.Path & "\VBA100_88_" & Format(Now(), "yyyymmddhhmmss") & ".log"
Call execXcopy(sPathA, sPathC, sLogFile)
Call execXcopy(sPathB, sPathC, sLogFile)
ThisWorkbook.FollowHyperlink sLogFile
End Sub
Sub execXcopy(ByVal fromPath As String, ByVal toPath As String, ByVal aLogFile As String)
Dim wsh As New IWshRuntimeLibrary.WshShell
Dim wExec As WshExec
Dim sCmd As String
sCmd = "xcopy /d /i /e /y """ & fromPath & """ """ & toPath & "\"" >> """ & aLogFile & """"
Set wExec = wsh.Exec("%ComSpec% /c " & sCmd)
Do While wExec.Status = 0
DoEvents
Loop
Set wsh = Nothing
End Sub
DOS窓が一瞬表示されます。
戻り値のオブジェクトを使う事で、標準出力も取得できます。
詳細は以下のMS公式ページを参照してください。
WshScriptExec オブジェクト
StdOut プロパティ (WshScriptExec)
Sub VBA100_88_03()
Dim sPathA As String: sPathA = ThisWorkbook.Path & "\A 1"
Dim sPathB As String: sPathB = ThisWorkbook.Path & "\B 2"
Dim sPathC As String: sPathC = ThisWorkbook.Path & "\C 3"
Dim fso As New FileSystemObject
If fso.FolderExists(sPathC) Then Call fso.DeleteFolder(sPathC, True)
Set fso = Nothing
Dim sLogFile As String
sLogFile = ThisWorkbook.Path & "\VBA100_88_" & Format(Now(), "yyyymmddhhmmss") & ".log"
Call runXcopy(sPathA, sPathC, sLogFile)
Call runXcopy(sPathB, sPathC, sLogFile)
ThisWorkbook.FollowHyperlink sLogFile
End Sub
Sub runXcopy(ByVal fromPath As String, ByVal toPath As String, ByVal aLogFile As String)
Dim wsh As New IWshRuntimeLibrary.WshShell
Dim sCmd As String
sCmd = "xcopy /d /i /e /y """ & fromPath & """ """ & toPath & "\"" >> """ & aLogFile & """"
Call wsh.Run("%ComSpec% /c " & sCmd, 0, True)
Set wsh = Nothing
End Sub
WshShellオブジェクト.Run(strCommand, [intWindowStyle], [bWaitOnReturn])
object | WshShell オブジェクトです。 | ||||||||||||||||||||||||
strCommand | 実行するコマンド ラインを示す文字列値です。 この引数には、実行可能ファイルに渡すべきパラメータをすべて含める必要があります。 |
||||||||||||||||||||||||
intWindowStyle | 省略可能です。 プログラムのウィンドウの外観を示す整数値です。
|
||||||||||||||||||||||||
bWaitOnReturn | 省略可能です。 スクリプト内の次のステートメントに進まずにプログラムの実行が終了するまでスクリプトを待機させるかどうかを示すブール値です。 TRUE を指定すると、プログラムの実行が終了するまでスクリプトの実行は中断され、Runメソッドはアプリケーションから返される任意のエラー コードを返します。 bWaitOnReturnにFALSE を指定すると、プログラムが開始するとRunメソッドは即座に復帰して自動的に 0 を返します。 |
詳細は以下のMS公式ページを参照してください。
WshShell オブジェクトのプロパティとメソッド
Run メソッド
サイト内関連ページ
同じテーマ「VBA100本ノック」の記事
86本目:全シートの総当たり表を作成
87本目:数式のシート間の依存関係
88本目:クロスABC分析作成
89本目:2つのフォルダの統合
90本目:セルに重なっている画像の削除
91本目:時間計算(残業時間の月間合計)
92本目:セルの色を16進で返す関数
93本目:複数ブックを連結して再分割
94本目:表範囲からHTMLのtableタグを作成
95本目:図形のテキストを検索するフォーム作成
96本目:Accessデータを取得(マスタ結合&抽出)
新着記事NEW ・・・新着記事一覧を見る
TRIMRANGE関数(セル範囲をトリム:端の空白セルを除外)|エクセル入門(2024-08-30)
正規表現関数(REGEXTEST,REGEXREPLACE,REGEXEXTRACT)|エクセル入門(2024-07-02)
エクセルが起動しない、Excelが立ち上がらない|エクセル雑感(2024-04-11)
ブール型(Boolean)のis変数・フラグについて|VBA技術解説(2024-04-05)
テキストの内容によって図形を削除する|VBA技術解説(2024-04-02)
ExcelマクロVBA入門目次|エクセルの神髄(2024-03-20)
VBA10大躓きポイント(初心者が躓きやすいポイント)|VBA技術解説(2024-03-05)
テンキーのスクリーンキーボード作成|ユーザーフォーム入門(2024-02-26)
無効な前方参照か、コンパイルされていない種類への参照です。|エクセル雑感(2024-02-17)
初級脱出10問パック|VBA練習問題(2024-01-24)
アクセスランキング ・・・ ランキング一覧を見る
1.最終行の取得(End,Rows.Count)|VBA入門
2.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
3.変数宣言のDimとデータ型|VBA入門
4.繰り返し処理(For Next)|VBA入門
5.RangeとCellsの使い方|VBA入門
6.ブックを閉じる・保存(Close,Save,SaveAs)|VBA入門
7.セルのクリア(Clear,ClearContents)|VBA入門
8.メッセージボックス(MsgBox関数)|VBA入門
9.条件分岐(Select Case)|VBA入門
10.マクロとは?VBAとは?VBAでできること|VBA入門
- ホーム
- マクロVBA入門編
- VBA100本ノック
- 89本目:2つのフォルダの統合
このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。
記述には細心の注意をしたつもりですが、
間違いやご指摘がありましたら、「お問い合わせ」からお知らせいただけると幸いです。
掲載のVBAコードは動作を保証するものではなく、あくまでVBA学習のサンプルとして掲載しています。
掲載のVBAコードは自己責任でご使用ください。万一データ破損等の損害が発生しても責任は負いません。