Option Explicit
Const book_folder As String = "C:\Users\owner\Desktop\テスト用" '終端に\をつけないこと
Const start_folder As String = "C:\Users\owner\Desktop\A\B" '終端に\をつけないこと
Const Hyper_Link As Boolean = True 'True=ハイパーリンク表示 する False=通常表示
Dim T_count As Long
Dim T_folders() As String
Dim T_endnames() As String
Public Sub 一括移動処理()
Dim ws As Worksheet
Dim wrow As Long
Dim maxrow As Long
Dim i As Long
Dim ecode As Long
Dim fname As String
Dim keyword As String
Dim dest_path As String
Dim exctr As Long: exctr = 0
Set ws = Worksheets("移動結果")
ws.Rows("2:" & Rows.Count).ClearContents
'ハイパーリンクを削除
ws.Range("C2:C" & Rows.Count).ClearHyperlinks
ws.Range("E2:E" & Rows.Count).ClearHyperlinks
'フォントの下線を削除
ws.Range("C2:C" & Rows.Count).Font.Underline = False
ws.Range("E2:E" & Rows.Count).Font.Underline = False
'選択範囲のフォント文字色を標準色に変更
ws.Range("C2:C" & Rows.Count).Font.ColorIndex = xlAutomatic
ws.Range("E2:E" & Rows.Count).Font.ColorIndex = xlAutomatic
'ファイル一覧を取得する
Dim FSO As Object
Set FSO = CreateObject("Scripting.FileSystemObject")
Dim FSO_folder As Object
Dim FSO_files As Object
Dim FSO_file As Object
'ブックの格納フォルダ情報
Set FSO_folder = FSO.getfolder(Book_folder)
'ブックの一覧取得
Set FSO_files = FSO_folder.files
wrow = 2
'取得したブック一覧をシートへ書き込む
For Each FSO_file In FSO_files
ws.Cells(wrow, "A").Value = FSO_file.name
wrow = wrow + 1
Next
maxrow = wrow - 1
'フォルダ一覧を取得する(3階層目のフォルダのみ)
T_count = 0
Call get_subfolders(FSO, Start_folder, 1)
'取得したフォルダ一覧をシートへ書き込む
For i = 0 To T_count - 1
If Hyper_Link = True Then
ws.Hyperlinks.Add anchor:=Range("E" & i + 2), Address:=T_folders(i), TextToDisplay:=T_folders(i)
Else
ws.Cells(i + 2, "E").Value = T_folders(i)
End If
Next
'ファイルを移動する
For wrow = 2 To maxrow
fname = ws.Cells(wrow, "A").Value
If CheckFileName(fname, keyword) = True Then
'ファイル名が異動対象の場合、移動を行う
ecode = move_book(FSO, fname, keyword, dest_path)
If dest_path <> "" Then
If Hyper_Link = True Then
ws.Hyperlinks.Add anchor:=Range("C" & wrow), Address:=dest_path, TextToDisplay:=dest_path
Else
ws.Cells(wrow, "C").Value = dest_path
End If
End If
If ecode = 0 Then
'移動結果が正常の場合
ws.Cells(wrow, "B").Value = "完了"
exctr = exctr + 1
Else
'移動結果が以上の場合
ws.Cells(wrow, "B").Value = "ERR" & ecode
End If
Else
'ファイル名が異動対象外の場合
ws.Cells(wrow, "B").Value = "ERR1"
End If
Next
MsgBox ("移動件数=" & exctr & "件")
End Sub
'ファイル移動
'戻り値 0:正常 2:該当フォルダ無し 3:既に移動先のフォルダ内にファイルが存在する
Private Function move_book(ByRef FSO As Object, ByVal fname As String, ByVal keyword As String, ByRef dest_path As String) As Long
Dim i As Long
Dim end_path As String
Dim dest_file As String
Dim src_file As String
move_book = 3
'全フォルダをチェックする
For i = 0 To T_count - 1
'1フォルダを取り出す
dest_path = T_folders(i)
'終端のフォルダ名を取得
end_path = T_endnames(i)
'終端のフォルダ名とキーワードの両方を大文字に変換後比較する
If UCase(end_path) = UCase(keyword) Then
'終端フォルダとキーワードが一致すれば、移動対象となる
dest_file = dest_path & "\" & fname
'移動先のフォルダ内に移動しようとするファイルが存在するなら、戻り値=3で終了
If FSO.fileexists(dest_file) = True Then Exit Function
'ファイルの移動を行う
src_file = Book_folder & "\" & fname
Call FSO.movefile(src_file, dest_file)
'戻り値=0で終了
move_book = 0
Exit Function
End If
Next
'移動対象のフォルダが存在しない場合
'戻り値=2で終了
dest_path = ""
move_book = 2
End Function
'ファイル名チェック
Private Function CheckFileName(ByVal fname As String, ByRef keyword As String) As Boolean
Dim RE As Object
Dim REmatch As Object
CheckFileName = False
Set RE = CreateObject("VBScript.RegExp")
RE.Pattern = "^\d{6}(\s+)\d{4}(\s+)(.+?)(\s+)記録用\.xlsx$"
RE.Global = True
RE.IgnoreCase = True
'正規表現によるファイル名のマッチ試験
Set REmatch = RE.Execute(fname)
'マッチしないなら終了
If REmatch.Count < 1 Then Exit Function
'日付の後の空白、通し番号の後の空白、記録用の前の空白が1桁でないなら終了
If Len(REmatch(0).submatches(0)) <> 1 Then Exit Function
If Len(REmatch(0).submatches(1)) <> 1 Then Exit Function
If Len(REmatch(0).submatches(3)) <> 1 Then Exit Function
'キーワードを設定
keyword = REmatch(0).submatches(2)
CheckFileName = True
End Function
'サブフォルダの取得(再帰)
Sub get_subfolders(ByRef FSO As Object, ByVal s_folder As String, ByVal level As Long)
Dim folder As Object
'指定フォルダ内の全フォルダを処理する
For Each folder In FSO.getfolder(s_folder).subfolders
ReDim Preserve T_folders(T_count)
ReDim Preserve T_endnames(T_count)
T_folders(T_count) = folder.path
T_endnames(T_count) = folder.name
T_count = T_count + 1
'取得したフォルダの下位フォルダを取得する
Call get_subfolders(FSO, folder.path, level + 1)
Next
End Sub