[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]
『EXCEL2007での FileSearch 問題』(疑問者)
すみません。
EXCEL2003で動いていた下記VBAマクロ(関係部抜粋)ですが,excel2007になったら
全く動かなくなりました。
原因は下記のFileSearchという命令がexcel2007では無くなってしまったことが
原因とわかりました。
しかし,VBAに暗いので,これをEXCEL2007で使えるようにする方法がわかりません。
下記のコードの部分が直せれば直して置き換えたいのですが
だれか置き換えるコードをご存知でしょうか。
dirname, Filename2 は変数であり,この変数の条件に合うホルダ付ファイルを
セルに拾い出すマクロの一部です。
-------------------------------------
With Application.FileSearch .NewSearch .LookIn = dirname .SearchSubFolders = True .Filename = Filename2 .MatchTextExactly = False '文字を一部に含むものを検索 完全一致でない .FileType = msoFileTypeAllFiles
If .Execute() > 0 Then MsgBox .foundfile.Count & _ "個のファイルが見つかりました。" Cells(3, 2) = .FoundFiles.Count For i = 1 To .FoundFiles.Count Cells(rowlast + i, 3) = .FoundFiles(i)
next i ------------------------------
< 使用 Excel:Excel2007、使用 OS:unknown >
こんな感じですか?
Sub ファイル検索()
Dim DirName As String
Dim FileName2 As String
Dim FSO As Object
Dim F As Variant
Dim dic As Object
DirName = "C:\エクセルの学校"
FileName2 = "テスト"
Set FSO = CreateObject("Scripting.FileSystemObject")
Set dic = CreateObject("Scripting.Dictionary")
With FSO
For Each F In .GetFolder(DirName).Files
If F.Name Like "*" & FileName2 & "*" Then
dic.Add F.Name, ""
End If
Next F
End With
If dic.Count > 0 Then
MsgBox dic.Count & "個のファイルが見つかりました"
Cells(3, "B").Value = dic.Count
Cells(Rows.Count, "C").End(xlUp).Offset(1).Resize(dic.Count).Value = Application.Transpose(dic.keys)
End If
End Sub
(稲葉) 2015/04/01(水) 13:00
コードを置き換えて組んだところ,一応表示できましたが,今までと違い
ファイル名しか表示されませんでしたので,
ホルダ名を頭に付けたいのですが。 どう訂正すればよろしいのでしょうか。
(疑問者)
フォルダ名は指定しているのだからいらない気がしますが、Nameプロパティの代わりにPathプロパティ
使えばいいと思います!
dic.Add F.Name, ""
~~~~~
この部分
(稲葉) 2015/04/01(水) 13:35
稲葉さん 上記で希望通りできたと思ったのですが
今気づいたのですがサブホルダー内までは検索できませんでした。
サブホルダーまでは無理でしょうか。
(疑問者)
すいません、回答じゃないのですがコメントする時はコメント欄から書いてください。 (se_9) 2015/04/01(水) 15:01
あ、ごめんなさい.FileSearch使ったことないのでプロパティよく確認していませんでした。 で、サブフォルダ検索少々お待ちください・・・ (稲葉) 2015/04/01(水) 15:35
昔作った気がしたので、掘り出しました。
クラスモジュールを一つ挿入し、オブジェクト名を clsGetFilePath とし、以下のコードを入れてください。
Option Explicit
Private FolStp As Long '掘り進めるフォルダの最大階層(現在のフォルダなら0)
Private FolDic As Object 'フォルダの一覧Dictionaryオブジェクト
Private FilDic As Object 'ファイルの一覧Dictionaryオブジェクト
Private FinDic As Object 'ブック内検索で見つけたファイルの一覧Dictionaryオブジェクト
Private FstFol As String '初期フォルダーのパス
Private EXT As String '拡張子のフィルタ
Private Name As String 'ファイル名のフィルタ
Private FindStr As String '検索する文字列のフィルタ
Private FSO As Object 'フォルダ等を取得する、FileSystemObject
Private ExcAttr As Long
Private Cancel As Boolean
Enum ExcAttrType
ReadOnly = 1
Hidden = 2
System = 4
ShortCut = 64
ReadHid = 3
ReadSys = 5
ReadShort = 65
HidSys = 6
HidShort = 66
SysShort = 68
ReadHidSys = 7
ReadHidShort = 67
ReadHidSysShort = 71
'値 属性
'0 標準ファイル
'1 読み取り専用ファイル
'2 隠しファイル
'4 システムファイル
'8 ディスクドライブボリュームラベル (取得のみ可能)
'16 フォルダまたはディレクトリ (取得のみ可能)
'32 アーカイブファイル
'64 リンクまたはショートカット (取得のみ可能)
'128 圧縮ファイル (取得のみ可能)
End Enum
'//実体化時の処理
Private Sub Class_Initialize()
'//////////////////////////////
Set FolDic = CreateObject("Scripting.Dictionary")
Set FilDic = CreateObject("Scripting.Dictionary")
Set FinDic = CreateObject("Scripting.Dictionary")
Set FSO = CreateObject("Scripting.FileSystemObject")
End Sub
'//実体破棄時の処理
Private Sub Class_Terminate()
'//////////////////////////////
Set FolDic = Nothing
Set FilDic = Nothing
Set FinDic = Nothing
Set FSO = Nothing
End Sub
'■メソッド■
'■最初のフォルダをセットする
Public Function GetFirstFolder() As Boolean
'//////////////////////////////
GetFirstFolder = False
If FstFol = "" Then
With Application.FileDialog(msoFileDialogFolderPicker)
If .Show = True Then
FstFol = .SelectedItems(1) & "\"
GetFirstFolder = True
Else
Exit Function
End If
End With
Else
GetFirstFolder = True
End If
FolDic.Add FstFol, ""
End Function
'■ファイル名の取得
Public Function GetFileList() As Boolean
'//////////////////////////////
GetSubFolder FstFol
If FilDic.Count > 0 Then GetFileList = True: Exit Function
Dim k
Dim FilName
Dim F
For Each k In FolDic
On Error Resume Next
For Each F In FSO.GetFolder(k).Files
If Cancel = True Then Exit For
If Err = 0 Then
If GetAttr(F) Then
If F.Name Like Name & EXT Then
FilDic.Add F.Path, F.Name
Application.StatusBar = "ファイル検索:" & F.Path
Else
Application.StatusBar = "ファイル検索:No Match" & Time
End If
End If
Else
Application.StatusBar = "ファイル検索:スキップ" & Now
End If
DoEvents
Next F
On Error GoTo 0
Next k
Application.StatusBar = False
If FilDic.Count > 0 Then
GetFileList = True
Exit Function
End If
End Function
'■サブフォルダを取得するサブプロシジャー(再帰処理)
Private Sub GetSubFolder(ByVal FPath As String, Optional ByVal Nstp As Long = 0)
'//////////////////////////////
'FPath ---フォルダの名前
'Nstp ---現在の階層を指定する
Dim FName As String
Dim SubFol As String
Dim k
Dim SF
On Error Resume Next
For Each SF In FSO.GetFolder(FPath).SubFolders
If Cancel = True Then Exit For
If Err > 0 Then
Application.StatusBar = "サブフォルダ検索:スキップ" & Now
Exit For
Else
If GetAttr(SF) Then
SubFol = SubFol & Chr(2) & SF.Path & "\"
FolDic.Add SF.Path & "\", ""
Application.StatusBar = "サブフォルダ検索:" & SF.Path
End If
DoEvents
End If
Next SF
On Error GoTo 0
Application.StatusBar = False
If Cancel = True Then Exit Sub
If FolStp > Nstp Then
For Each k In Split(Mid(SubFol, 2), Chr(2))
GetSubFolder k, Nstp + 1
Next k
End If
End Sub
'■ファイル名の取得
Public Function GetFindStr() As Boolean
'//////////////////////////////
GetFindStr = False
Application.StatusBar = "出力の準備中..."
Dim xlApp As Application
Dim FN
Set xlApp = CreateObject("Excel.Application")
EV_SW False, xlApp
For Each FN In FilDic.keys
If Cancel = True Then Exit For
If FindInBook(FN, xlApp) Then
FinDic.Add FN, ""
End If
Next FN
EV_SW True, xlApp
xlApp.Quit
If FinDic.Count > 0 Then
GetFindStr = True
End If
End Function
'■検索条件をクリア
Sub Clear()
'//////////////////////////////
Set FolDic = CreateObject("Scripting.Dictionary")
Set FilDic = CreateObject("Scripting.Dictionary")
End Sub
'■ファイル(フォルダ)の属性検出
Private Function GetAttr(ByVal FP As Object) As Boolean
'//////////////////////////////
GetAttr = True
If FP.Attributes And ExcAttr Then GetAttr = False
End Function
'■ブック内検索のサブプロシージャ
Private Function FindInBook(ByVal Target As String, ByVal xlApp As Application) As Boolean
'//////////////////////////////
Dim WS As Worksheet
Dim F As Range
On Error Resume Next
With xlApp.Workbooks.Open(Target, ReadOnly:=True)
If Err = 0 Then
For Each WS In .Sheets
Application.StatusBar = Replace(Application.StatusBar, ":", ":" & WS.Name)
Set F = WS.Cells.Find( _
What:=FindStr, _
After:=WS.Range("A1"), _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchFormat:=False)
If Not F Is Nothing Then
FindInBook = True
Exit For
End If
Next WS
.Saved = True
.Close (False)
End If
DoEvents
End With
On Error GoTo 0
End Function
'■イベントスイッチ
Private Function EV_SW(ByVal flg As Boolean, ByRef xlApp As Application)
'//////////////////////////////
With xlApp
'.ScreenUpdating = flg
'.Calculation = IIf(flg, xlCalculationAutomatic, xlCalculationManual)
.DisplayAlerts = flg
.EnableEvents = flg
.AutomationSecurity = IIf(flg, msoAutomationSecurityByUI, msoAutomationSecurityForceDisable)
If flg = True Then xlApp.Quit
End With
End Function
'■最初のフォルダを指定する
Public Function SetFirstFolder(ByVal FirstFolder As String) As Boolean
'//////////////////////////////
SetFirstFolder = False
If Dir(FirstFolder) <> "" Then
FstFol = FirstFolder
SetFirstFolder = True
End If
End Function
'■プロパティー■
'■最大階層数を指定する
Public Property Let MaxStep(ByVal Steps As Long)
'//////////////////////////////
FolStp = Steps
End Property
'■拡張子を指定する(例:xls?)
Public Property Let SetEXT(ByVal FindEXT As String)
'//////////////////////////////
EXT = FindEXT
End Property
'■検索するファイル名を指定する
Public Property Let SetName(ByVal FindName As String)
'//////////////////////////////
Name = FindName
End Property
'■検索除外する属性を指定する
Public Property Let SetExcAttr(ByVal ExcAttrs As ExcAttrType)
'//////////////////////////////
ExcAttr = ExcAttrs
End Property
'■検索除外する属性を指定する
Public Property Let SetFindStr(ByVal StrFind As String)
'//////////////////////////////
FindStr = StrFind
End Property
'■検索除外する属性を指定する
Public Property Let clsCancel(ByVal Can As Boolean)
'//////////////////////////////
Cancel = Can
End Property
'■ファイルのパスを配列にして出力
Public Property Get FilePathList() As Variant
'//////////////////////////////
Application.StatusBar = "出力の準備中..."
FilePathList = FilDic.keys
Application.StatusBar = False
End Property
'■ブック内検索をして見つけたリストを出力
Public Property Get FindStrList() As Variant
'//////////////////////////////
If FinDic.Count > 0 Then
FindStrList = FinDic.keys
End If
Application.StatusBar = False
End Property
'■ファイルの名前を配列にして出力
Public Property Get FileNameList() As Variant
'//////////////////////////////
FileNameList = FilDic.Items
End Property
'■ファイル名の件数を出力
Public Property Get CountFile() As Variant
'//////////////////////////////
CountFile = FilDic.Count
End Property
'■検索した文字数の件数を出力
Public Property Get CountFind() As Variant
'//////////////////////////////
CountFind = FinDic.Count
End Property
'■検索した文字数の件数を出力
Public Property Let LookIn(DirPath As String)
'//////////////////////////////
If FSO.FolderExists(DirPath) Then
FstFol = DirPath
End If
End Property
標準モジュールに以下のコードを入れて、testを実行してください。
Sub test()
Dim clsGFP As clsGetFilePath
Set clsGFP = New clsGetFilePath
With clsGFP
.MaxStep = 2 'サブフォルダをさかのぼる階層数
.LookIn = "C:\エクセルの学校\" '検索を開始するパス ←これをセットしなければ、後でダイヤログで指定できる
.SetName = "*" & "テスト" & "*" '検索するファイル名
.SetEXT = "*.xls?" '検索する拡張子
.SetExcAttr = ReadHidSysShort '検索するファイルの属性(デフォルトは全部)
If .GetFirstFolder = False Then Exit Sub
If .GetFileList = False Then Exit Sub
If .CountFile > 0 Then
Cells(2, "B").Value = .CountFile
Cells(Rows.Count, "C").End(xlUp).Offset(1).Resize(.CountFile).Value = Application.Transpose(.FilePathList)
End If
End With
End Sub
(稲葉) 2015/04/01(水) 15:57
数行の手直し変更程度では簡単には行かないようですね。 そういう意味ではやはり,excel2003時代のApplication.FileSearchは優れものだったというわけですね。
あまりに長く複雑そうなので,大変という感じですね。 とりあえずは,サブフォルダーまでは諦めようと思います。
ありがとうございました。 (疑問者) 2015/04/01(水) 17:29
いや実際はもっと簡単ですよ。 質問者さんが変更するところは >標準モジュールに以下のコードを入れて、testを実行してください。 標準モジュールに入れたコードだけです。
全部掲載いただければ、そっくり書き換えてもいいんですが・・・
※FileSearch使ったことなかったので、それを再現できそうなもの、少し考えてみます。 面白い題材頂いてありがとうございます。
(稲葉) 2015/04/01(水) 17:46
と思ったら既に代替クラス作ってくれている人いました! http://d.hatena.ne.jp/xixiixiiixiv/20120806/1344258369
試してみてください。 (稲葉) 2015/04/01(水) 17:49
大変済みません
WScriptでサブフォルダ一気に出せるの忘れてました。
Sub WScript版()
Dim DirName As String
Dim FileName2 As String
Dim Files
DirName = "C:\エクセルの学校\dafdsafdsa\"
FileName2 = "テスト"
Files = Split(CreateObject("WScript.Shell").Exec("cmd /C DIR /S /B /O:N """ & DirName & "*" & FileName2 & "*""").StdOut.ReadAll(), vbLf)
If UBound(Files) > 0 Then
MsgBox UBound(Files) & "個のファイルが見つかりました"
Cells(3, "B").Value = UBound(Files)
Cells(Rows.Count, "C").End(xlUp).Offset(1).Resize(UBound(Files)).Value = Application.Transpose(Files)
End If
End Sub
(稲葉) 2015/04/01(水) 18:36
[ 一覧(最新更新順) ]
YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki.
Modified by kazu.