複数フォルダ内のファイル群を纏める方法

このQ&Aのポイント
  • Excel2003のVBAを使用して、複数フォルダ内のファイル群を一つに纏める方法を教えてください。
  • 任意のフォルダAの直下にある複数のフォルダ内には約3万個のファイルがあります。これらのファイルを新しいフォルダにコピーして纏める方法を教えてください。
  • Excel2003のVBAを使って、複数のフォルダ内にあるファイル群を一つのフォルダにまとめる方法を教えてください。
回答を見る
  • ベストアンサー

複数フォルダ内のファイル群をひとつに纏める

Excel2003のVBA で、以下の作業を行いたいので宜しくご教示下さい。   サーバー上や自分のPC上にある、任意フォルダA直下には、   複数のフォルダがあり、その複数フォルダ内に多数のファイル(約3万個)が入っている。   そのファイル群を、任意フォルダAの直下に新しいフォルダを1つ作り、全てコピーし纏めたい。   当方の構想(希望)としては、   1.エクセルシート1に全ファイル名を書きだす。(行:フォルダ名、列:ファイル名)   2.同名ファイルの有無を判定し、有ればエクセルシート2にフォルダ名とファイル名を抽出する。     (同名ファイルは、エクセルシート2を確認し、手動で変更する)   3.同名ファイルが無ければ、新しいフォルダに全てコピーする。 コードを記載しご教示頂ければ助かります。 皆様よろしくお願い致します。

noname#148866
noname#148866

質問者が選んだベストアンサー

  • ベストアンサー
  • mitarashi
  • ベストアンサー率59% (574/965)
回答No.3

#2の続きです。 1番目のシートにファイルリストを出力(形式はご質問の仕様と異なります)→日付と、サイズも出力しますので、こちらでファイル名をキーに並び替えして重複チェックする事をお勧めします。 2番目のシートに、重複したファイル名と、フォルダー名(,区切りで列挙)を出力します。 xl2000とxl2010で動作を確認しました。(ファイルコピー部分はあまり試してないです)。但しxl2000はTranspose関数が配列の要素数4095個までしか対応しておりません。それから、4G以上のファイルにも対応していません。 xl2010で、2万個位のファイルの抽出(コピーを除く)が2分未満でした。(但し、Dドライブ、Celeron2.4GHz)#1で紹介されているFileSystemObjectが遅く感じたら、使ってみてください。 APII部分はWEB上の情報の切り貼りなので質問されても答えられませんのでよろしく。また、文字数制限対策で、エラー処理とか色々削ってありますので、ご承知置き下さい。 'ファイルを検索する Private Sub FindFile( _ ByVal DirPath As String, _ ByVal SearchFileName As String, _ ByRef filePath() As String, _ ByRef fName() As String, _ ByRef updateDate() As Date, _ ByRef fileSize() As Long, _ Optional ByVal CheckSubFolder As Boolean = False _ ) Dim wfd As WIN32_FIND_DATA Dim hFind As Long Dim i As Long Dim j As Long Dim DirName As String Dim myFileName As String Dim SubFolders() As String ' パス終端の補正 If Right$(DirPath, 1) <> "\" Then DirPath = DirPath & "\" ' サブフォルダ列挙 i = -1 If CheckSubFolder Then hFind = FindFirstFile(DirPath & "*", wfd) If hFind <> INVALID_HANDLE_VALUE Then Do DirName = Left$(wfd.cFileName, InStr(wfd.cFileName, Chr(0)) - 1) If DirName <> "." And DirName <> ".." Then If CBool(wfd.dwFileAttributes And FILE_ATTRIBUTE_DIRECTORY) Then i = i + 1 ReDim Preserve SubFolders(i) SubFolders(i) = DirPath & DirName End If End If Loop Until FindNextFile(hFind, wfd) = 0 FindClose (hFind) End If End If ' ファイル列挙 hFind = FindFirstFile(DirPath & SearchFileName, wfd) If hFind <> INVALID_HANDLE_VALUE Then Do myFileName = Left$(wfd.cFileName, InStr(wfd.cFileName, Chr(0)) - 1) If myFileName <> "." And myFileName <> ".." Then If CBool(wfd.dwFileAttributes And FILE_ATTRIBUTE_DIRECTORY) = False Then On Error Resume Next j = UBound(fName) + 1 If Err Then j = 0 On Error GoTo 0 ReDim Preserve filePath(j) ReDim Preserve fName(j) ReDim Preserve updateDate(j) ReDim Preserve fileSize(j) filePath(j) = DirPath fName(j) = myFileName updateDate(j) = FILETIME2Date(wfd.ftLastWriteTime) '4GB以下であれば、nFileSizeHighは無視できる fileSize(j) = wfd.nFileSizeLow j = j + 1 End If End If Loop Until FindNextFile(hFind, wfd) = 0 FindClose (hFind) End If ' サブフォルダ探索 If CheckSubFolder And i > -1 Then For i = 0 To UBound(SubFolders) ' サブフォルダ再帰呼び出し Call FindFile(SubFolders(i), _ SearchFileName, _ filePath, _ fName, _ updateDate, _ fileSize, _ CheckSubFolder) Next i End If End Sub 'FILETIME構造体をDate型に変換 Private Function FILETIME2Date(udtFileTime As FILETIME) As Date Dim udtLclTime As FILETIME 'ローカル時間補正後 Dim udtSysTime As SystemTime Dim dummyRetVal As Long dummyRetVal = FileTimeToLocalFileTime(udtFileTime, udtLclTime) dummyRetVal = FileTimeToSystemTime(udtLclTime, udtSysTime) With udtSysTime FILETIME2Date = CDate(.wYear & "/" & .wMonth & "/" & .wDay & " " & _ .wHour & ":" & .wMinute & ":" & .wSecond) End With End Function

noname#148866
質問者

お礼

コード記載ありがとうございます。 大変感謝しております。 内容については、ひとつひとつ確認して実行して行きたいと思います。 (はっきり、私の能力では解読出来ないかも知れませんが…。) >「ちょっと興味があったので・・・」 本当に興味を持って頂きありがとうございました。 コア(?)な、質問で回答無しかなと思っていましたし。 時々参考にしていたサイトなので、皆様の実力には感服していた次第です。 今回の質問は、かなり手こずった(糸口が見えない)末の投稿でした。 ベストアンサーだと思いますが、解読してみてからのチェックとさせて下さい。 (かなり時間がかかると思います)

その他の回答 (6)

  • imogasi
  • ベストアンサー率27% (4737/17068)
回答No.7

コピー元(移動元)対象ファイルに付いて >多数のファイル(約3万個)が 写し(移し)たくないファイルが混じってあるのかな。 エクセルファイルばかりではないのかな。 ファイル名の先頭とかに選別の印(文字列)は無いのか ーーー 除外ファイルが少なければ、フォルダ単位で、1つのフォルダ内に写すか移したら。 そこで不要のファイルを道家手削除する(出来ればプログラムロジックでプログラムを組んで)。 トイのも30000ファイルも扱うとVBAのようなインターpリター的な処理では、時間が大変かかるような気がする。 ーー >クセルシート1に全ファイル名を書きだす 出来るならここから手を付けたら。 Googleで「VBA フォルダ ファイル名 取得」で照会したのかな。沢山コードレが出るに、10行以内で済む。 ドレくらい時間がかかるかとか、ダブリの情況が実感できるだろう。 1シートに複数フォルダのファイル名(フォルダ名+ファイル名)も累積できるだろう。 この複数フォルダ名は、セル範囲に入れるか配列に定義する。10-20ぐらいかと予想。質問異は複数とあいまいにせず、20ファオルダとか概数を書けば良いのに。 そしてソートしてプログラムでチェックしてサインで別列に出して、詳細は質問者がチェックする

noname#148866
質問者

お礼

かなりお礼が遅くなりすみません。 大変参考となりました。

  • mitarashi
  • ベストアンサー率59% (574/965)
回答No.6

#2です。 更に悪のりして、 ファイルをコピーするSHFileOperationというAPIがあります。 http://homepage2.nifty.com/Dee/vb/soft/index.html フォルダの異なる複数ファイルをコピーするには、パスをChr(0)を介して結合し、最後にChr(0)を二個つけた文字列を生成して与える必要があります。My Documentsに置いたファイルのフルパス1800個程度では動作しました。 残念ながら、VBAのファイルコピーに対して速度上のメリットはなさそうですが、お馴染みのファイルをコピーするアニメーションのダイアログで進度表示されるので、気が紛れるというメリットは期待できます。 ご参考まで。 バグフィックス 重複ファイルが一つもないと、シート2への転写部でコケるので、 If myDic2.Count > 1 Then Sheets(2).Range("A1").Resize(myDic2.Count, 1) = Application.Transpose(myKeys) Sheets(2).Range("B1").Resize(myDic2.Count, 1) = Application.Transpose(myItems) End If と、条件を加えてください。 また、Thumbs.db(システムファイルでフォルダオプションをいじらないと見えない)で、コピーエラーが出る事がある様です。 ご参考まで。

  • mitarashi
  • ベストアンサー率59% (574/965)
回答No.5

#2です。 調子にのってファイルの同一チェックをハッシュを求めて行う方法を調べておりました。 参考URLの関数を借用してやってみました。#2のコードの最後の方に組み込みます。 http://su-u.jp/juju/%B5%A4%A4%DE%A4%B0%A4%EC%C6%FC%B5%AD/2007-03-08.html すべてPublicで宣言してくれてあるので、丸ごとModule2などにペーストすればよいでしょう。 あまり深く試してはありませんが、一応動くのは確認しました。ご参考まで。 (変数宣言部は含みませんので試すときはご自分でお願いします) myKeys = myDic2.keys For Each mykey In myKeys buf = Split(myDic2.Item(mykey), ",") For i = LBound(buf) To UBound(buf) srcFileName = buf(i) & "\" & mykey myHash = CreateSHA1HashFile(srcFileName) 'ハッシュの算出は数種類サポートされています。 destFileName = destpath & "\" & Left(mykey, InStr(mykey, ".") - 1) _ & "_" & myHash & Right(mykey, Len(mykey) - InStr(mykey, ".") + 1) If Dir(destFileName) = "" Then FileCopy srcFileName, destFileName End If Next i Next mykey

noname#148866
質問者

お礼

かなり遅くなりました(パスワードがわからなくなっていました) ハッシュもわかるのですね。これは凄い!なんらかの参照にさせて頂きます。

  • sknbsknb2
  • ベストアンサー率38% (1125/2899)
回答No.4

お求めの回答ではありませんが、よりよい方法を提示できる可能性もあるのでお聞きします。 世の中にはご希望の動作をするユーティリティがいくつもあると思うのですが、それをEXCELのVBAで実行したいというのは何か理由があるのですか?

noname#148866
質問者

お礼

 ご覧頂きありがとうございます。 なんらかのユーティリティは世の中に存在するとは思いましたが (自宅での)検索する時間が惜しく・・・  また、会社のセキュリティ(不要サイト閲覧禁止、ダウンロード禁止etcetc...)上で 融通が利かない状況です。 当方が強く推せば、特定のユーティリティを使えると思いますが。 この様な、(無駄な)理由でVBAでの実行に思いが行き当っているのでございます。

  • mitarashi
  • ベストアンサー率59% (574/965)
回答No.2

ちょっと興味があったので、作成してみました。4K文字に収まらないので、二つに分けます。コメントは別途。 Declare Function FindFirstFile Lib "kernel32" Alias "FindFirstFileA" ( _ ByVal lpFileName As String, _ ByRef lpFindFileData As WIN32_FIND_DATA) As Long Declare Function FindNextFile Lib "kernel32" Alias "FindNextFileA" ( _ ByVal hFindFile As Long, _ ByRef lpFindFileData As WIN32_FIND_DATA) As Long Declare Function FindClose Lib "kernel32" ( _ ByVal hFindFile As Long) As Long Declare Function ShellExecute Lib "SHELL32" Alias "ShellExecuteA" (ByVal hwnd&, ByVal lpOperation$, ByVal lpFile$, ByVal lpParameters$, ByVal lpDirectory$, ByVal nShowCmd&) As Long Declare Function LocalFileTimeToFileTime Lib "kernel32" _ (lpLocalFileTime As FILETIME, _ lpFileTime As FILETIME) As Long Declare Function FileTimeToLocalFileTime Lib "kernel32" _ (lpFileTime As FILETIME, _ lpLocalFileTime As FILETIME) As Long Declare Function FileTimeToSystemTime Lib "kernel32.dll" _ (lpFileTime As FILETIME, lpSystemTime As SystemTime) As Long Const MAX_PATH As Long = 260 Const INVALID_HANDLE_VALUE As Long = (-1) Const FILE_ATTRIBUTE_DIRECTORY As Long = &H10 Const conDayZeroBios As Double = 109205# Const conMillisecondPerDay As Double = 10000000# * 60# * 60# * 24# / 10000# Type FILETIME dwLowDateTime As Long dwHighDateTime As Long End Type Type WIN32_FIND_DATA dwFileAttributes As Long ftCreationTime As FILETIME ftLastAccessTime As FILETIME ftLastWriteTime As FILETIME nFileSizeHigh As Long nFileSizeLow As Long dwReserved0 As Long dwReserved1 As Long cFileName As String * MAX_PATH cAlternate As String * 14 End Type Type SystemTime wYear As Integer wMonth As Integer wDayOfWeek As Integer wDay As Integer wHour As Integer wMinute As Integer wSecond As Integer wMilliseconds As Integer End Type Sub makeFileList() Dim j As Long, i As Long Dim filePath() As String, fName() As String Dim updateDate() As Date Dim fileSize() As Long Dim fieldName Dim myDic As Object, myDic2 As Object Dim myKeys, myItems, myKey Const myFolder As String = "C:\hoge" Call FindFile(myFolder, "*.*", filePath(), fName(), updateDate(), fileSize, True) On Error Resume Next j = UBound(fName) + 1 If Err.Number <> 0 Then Exit Sub On Error GoTo 0 With Sheets(1) .Cells.Clear fieldName = Array("Path", "Name", "UpdateDate", "Size") .Range("A1").Resize(1, 4) = fieldName .Range("A2").Resize(j, 1) = Application.Transpose(filePath) .Range("B2").Resize(j, 1) = Application.Transpose(fName) .Range("C2").Resize(j, 1) = Application.Transpose(updateDate) .Range("D2").Resize(j, 1) = Application.Transpose(fileSize) End With Set myDic = CreateObject("Scripting.Dictionary") Set myDic2 = CreateObject("Scripting.Dictionary") For i = 0 To UBound(fName) If myDic.exists(fName(i)) Then myDic.Item(fName(i)) = myDic.Item(fName(i)) & "," & filePath(i) If myDic2.exists(fName(i)) Then myDic2.Item(fName(i)) = myDic.Item(fName(i)) Else myDic2.Add fName(i), myDic.Item(fName(i)) End If Else myDic.Add fName(i), filePath(i) End If Next i myKeys = myDic2.keys myItems = myDic2.items Sheets(2).Range("A1").Resize(myDic2.Count, 1) = Application.Transpose(myKeys) Sheets(2).Range("B1").Resize(myDic2.Count, 1) = Application.Transpose(myItems) myKeys = myDic.keys For Each myKey In myKeys If Not myDic2.exists(myKey) Then FileCopy myDic.Item(myKey) & "\" & myKey, "C:\destination\" & myKey End If Next myKey MsgBox "処理終了" End Sub

回答No.1

<ファイルの書き出し> FileSystemObject を使用する。 http://www.google.co.jp/search?hl=ja&q=filesystemobject+%E5%86%8D%E5%B8%B0&lr=lang_ja ファイル名は File オブジェクトの Name プロパティ値。 フォルダ名は File オブジェクトの ParentFolder プロパティから得られる Folder オブジェクトの Path プロパティ。 <重複チェック> ソートして 1行上のセルと比べてファイル名が同じか判断する <ファイルのコピー> A列 と B列を合体させてコピー元ファイルのフルパスを生成。 「何等かのパス」と B列を合体させてコピー先ファイルのフルパスを生成。 FileSystemObject オブジェクトの CopyFile メソッドを使用する。 http://msdn.microsoft.com/ja-jp/library/cc428016.aspx コード記載なんて甘えないでがんばってください。

noname#148866
質問者

お礼

ヒントになる事項をお答え下さりありがとうございます。 「コード記載・・・」については、色々反応があると予測はして おりましたが、励ましのお言葉で助かりました^^ VBAについては、まったくの初心者でもないですが、独学(ほとんどの方がそうかも?) でして、私は基本がなっていないのです。 今回の質問は、やりたい事をやりたいにも、「全く糸口が見付からず」、投稿した次第です。

関連するQ&A

  • フォルダに入っている複数のファイルをコピーしたい。

    エクセルなのですが、 1つのフォルダに入っている複数のエクセルファイルを 1つのエクセルファイルに(下に付け加えて)まとめたいと思っています。 このようなことをやりたいと思っているのですが、 お力をお貸ししていただけないでしょうか? どのシートも形式は同じなのですが、 1つのエクセルファイルに複数のBookがある場合もあります。 中身としてはA~Z列まであり、また行についてはそれぞれのシートによって異なります。 そして、どのシートに対しても1~3行についてはタイトル等が書いてありますので、 4行目以降でデータが入っているところまで、同じフォルダに用意したファイルに 順番にコピーしていきたいと思っています。 色々と試してみたのですが、どうしても複数のファイルから取り出してくることができなくて、 すみませんがよろしくお願します。

  • 複数ファイルから特定シートのコピー

    同じフォルダ内に、エクセルファイルがいくつかあります。 そのフォルダ内のファイルから、特定のシート名(例:シートA)のシートをコピーしシートAだけの新しいファイルとして作成しようと思います。 シートAを含むファイルは複数あります。 何か方法がありましたらご教授お願いいたします。

  • VBAで複数のフォルダから最新のファイルを検索してコピーするには?

    はじめましてこんにちは!エクセルを少しいじり始めた者です。 エクセルのVBAで複数のフォルダから最新更新日のファイルを検索して特定シートのセルD1からF20までをコピーして貼り付けるにはどのようにコードを書いたらいいのでしょうか?具体的に申し上げますと、ある特定のフォルダの中に複数のフォルダが入っており、複数のフォルダにはそれぞれ同じ名前の後に日付が入っていて、さらにその中には同じファイル名の後に日付が付いているファイルがあります。(「日本」フォルダの中に「日本200401」、「日本200402」、「日本200403」フォルダが入っていてさらにそれぞれのフォルダ内には「全国200401」」、「全国200402」、「全国200403」みたいな感じでフォルダ名と同じ日付が付いたファイルが入っています。) その複数のフォルダの中から最新更新日時のファイルだけを開いて特定のシートからデータをコピーして貼り付けるにはどのようにコードを記述したら良いのでしょうか?

  • エクセル:マクロでの同名ファイル検索

    お世話になります。 あるフォルダの中に、たくさんフォルダが入っています。 子フォルダのファイルを全て親フォルダに移すのですが、同名ファイルがある可能性があります。 同名ファイルは枝番をつけるなどして処理するのですが、あらかじめ同名ファイルがあるかどうかを調べたいのです。 親フォルダの中にエクセルを入れておき、マクロの実行の結果、エクセルのシートに同名ファイルの情報を表示できればと思っています。 例)もし同名ファイルがあった場合、 まずセルA1にファイル名、B1に拡張子を表示する。123.xlsの場合 A1に123 B1に.xls そしてそのファイルが入っているフォルダ名をB2以降のB列に表示する。 3つのフォルダにA1のファイル名のデータがあれば、B2,B3,B4にそのフォルダ名が表示される。 もちろん同名ファイルが1組とは限りません。 2つ目以降はB列のフォルダ名が入った下の行のA列(上の例だとA5)にファイル名が入る。 この繰り返しです。 また、もし1つの同名ファイルがなかった場合は、A1に「同名ファイルなし」と表示させます。 ちなみに重複の場合の枝番の付け方に規則性がないため手作業で行いますが、枝番をつけて同名ファイルを無くした あとにまとめて親フォルダに全データを移すこともマクロで可能ならアドバイスください。 フォルダ構成は1つの親フォルダに対して複数の子フォルダで、孫フォルダはありません。 OSはWinXP、Excelは2002です。 よろしくお願いします。

  • VBA_フォルダ内複数のExcelファイルの集約

    Excel VBAに関する質問です。 特定のフォルダ内(例としてC:\folder1)の複数のExcelファイルにおける シート(例としてSheet1)内のセル範囲A2:I1000の情報をコピーし、 特定のフォルダ内に格納されたExcelファイル(例としてC:\tougou\tougou.xls)の シート(例としてTOUGOU)内のA2を起点に貼り付け処理をしたいのですが、可能でしょうか? <貼り付けイメージ> (例)特定のフォルダ内(例としてC:\folder1)のExcelファイル数が2つの場合 A2 B2 ・・・・・I2 ・ ・ ・ ・ ・ A1999・・・・・・I1999 A2~I1999の範囲にデータが集約される。 どうぞよろしくお願いいたします。

  • 異なるフォルダ内の複数ファイルを一括変換する方法について

    Windowsで、複数のフォルダ内に入っているファイルのファイル名を一括変換する方法を教えてください。具体的には、複数フォルダには規則性がありフォルダ「001」「002」「003」・・・に入っている同名ファイル「index.html」をフォルダ名を用いてそれぞれ「001.html」「002.html」「003.html」・・・と変換したい状況です。

  • 複数のブックから特定データ群を新ブックにまとめたい

    こんにちは。 EXCEL2007について、ご教示ください。 EXCEL2007で、複数ブック内の特定シート上にある特定のデータ(複数) を特定ブックにまとめたいのですが、うまくできずに悩んでいます。 <やりたいこと>  ・参照元は特定フォルダ内にある全ファイルが対象(100程度)  ・ブック内の特定シートが対象(シート名は  ・コピー   (1) 元シートのA4~F4セル(セル結合されています)のデータを、     先シートのB2セルへコピー   (2) 元シートのG4~L4(セル結合)のデータを、先シートのC2セル     へコピー   (3) 元シートのG6~R6セルのデータを、先シートのE2セルへコピー  ・コピー2   次ブックを読み込み、1行下(B3、C3、E3)にコピーする。  ・コピー3   以降1行下にコピーし、ファイルが無くなるまで繰り返す。 以上ですが、マクロでできるように教えていただけないでしょうか。 よろしくお願いいたします。

  • エクセル マクロ 複数ファイルを1枚のファイルに

    お世話になります。 私の業務で、多数のエクセルシートを1つのファイルにまとめ、 その上で縦串を通して合算を出す、という作業が頻発しております。 様々な資料で同様の作業が行われますので、簡素化ができればと思い、 質問させていただきます。 [作りたいマクロ] 『元データ』のフォルダに入っているエクセルファイルの 『指定シート(仮にA2セルにシート名を指定できるものとします)』を、 当マクロの入ったエクセルファイルにシートを追加したい。 その際、全てのシート名が同一になってしまうので、 『指定したセル(仮に各シートのB2セル)』をシート名にする。 ●各シートは全て同じフォーマットですので、書式等そのままコピーでOKです ●元のファイル名はバラバラになっていることが多いです

  • 複数のエクセルファイルの文字色を一括で黒にしたい

    こんにちは 下記のように、複数のフォルダの配下にある複数のエクセルファイルA~Fの 中の全ての文字色を一括で黒に変更したいと思っているのですが、 なにか良い方法があったらご教示頂けないでしょうか。 (ちなみに全シートが対象です。) フォルダ1   ┣フォルダ2   ┃  ┗エクセルファイルA   ┣フォルダ3   ┃  ┣エクセルファイルB   ┃  ┣エクセルファイルC   ┃  ┗エクセルファイルD   ┗フォルダ4      ┣エクセルファイルE      ┗エクセルファイルF 実現方法はシェアウェア以外であればソフトでもマクロでも何でも構いません。 よろしくお願い致します。

  • エクセルのマクロであるフォルダ内にある全エクセルファイルのシート1!(

    エクセルのマクロであるフォルダ内にある全エクセルファイルのシート1!(A1:X365)の値を取得し、コピー元のエクセルファイル名のシートに貼付ける方法を教えて頂けないでしょうか?できればコピー元のエクセルファイルは開かずに実行させたいです。エクセルは2003を使っています。

専門家に質問してみよう