Windows エクスプローラーでフォルダーを開くアクセス フォームのボタンをクリックしたいと考えています。
VBAでこれを行う方法はありますか?
次のコードを使用して、vba からファイルの場所を開くことができます。
Dim Foldername As String
Foldername = "\\server\Instructions\"
Shell "C:\WINDOWS\explorer.exe """ & Foldername & "", vbNormalFocus
このコードは、Windows 共有とローカル ドライブの両方に使用できます。
最大化されたビューが必要な場合は、VbNormalFocus を VbMaximizedFocus のスワッパーにすることができます。
PhilHibbs のコメント (VBwhatnow の回答) のおかげで、既存のウィンドウを再利用し、ユーザーで CMD ウィンドウのフラッシュを回避するソリューションを最終的に見つけることができました。
Dim path As String
path = CurrentProject.path & "\"
Shell "cmd /C start """" /max """ & path & """", vbHide
ここで、「パス」は開きたいフォルダーです。
(この例では、現在のブックが保存されているフォルダーを開きます。)
長所:
短所:
最初はvbHideだけでやってみました。これはうまく機能します...そのようなフォルダーが既に開かれている場合を除き、その場合、既存のフォルダーウィンドウは非表示になり、消えます! ゴーストウィンドウがメモリ内に浮かんでおり、その後フォルダーを開こうとすると、非表示のウィンドウが再利用されます-一見効果がありません。
つまり、「開始」コマンドが既存のウィンドウを検出すると、指定された vbAppWinStyle がCMD ウィンドウと再利用されたエクスプローラ ウィンドウの両方に適用されます。(幸いなことに、別の vbAppWinStyle 引数を指定して同じコマンドを再度呼び出すことで、これを使用してゴースト ウィンドウを非表示に戻すことができます。)
ただし、'start' を呼び出すときに /max または /min フラグを指定すると、CMD ウィンドウに設定された vbAppWinStyle が再帰的に適用されなくなります。(またはそれをオーバーライドしますか? 技術的な詳細が何であるかはわかりません。ここで一連のイベントが何であるかを正確に知りたいと思っています。)
これに関連するさらにクールな知識を次に示します。
レコード内の少しの基準に基づいてフォルダーを検索し、見つかったフォルダーを開く必要がある状況がありました。解決策を見つける作業をしているときに、検索開始フォルダーを要求する小さなデータベースを作成しました基準。
フォームのコード全体は次のとおりです。
Option Compare Database
Option Explicit
Private Sub cmdChooseFolder_Click()
Dim inputFileDialog As FileDialog
Dim folderChosenPath As Variant
If MsgBox("Clear List?", vbYesNo, "Clear List") = vbYes Then DoCmd.RunSQL "DELETE * FROM tblFileList"
Me.sfrmFolderList.Requery
Set inputFileDialog = Application.FileDialog(msoFileDialogFolderPicker)
With inputFileDialog
.Title = "Select Folder to Start with"
.AllowMultiSelect = False
If .Show = False Then Exit Sub
folderChosenPath = .SelectedItems(1)
End With
Me.txtStartPath = folderChosenPath
Call subListFolders(Me.txtStartPath, 1)
End Sub
Private Sub cmdFindFolderPiece_Click()
Dim strCriteria As String
Dim varCriteria As Variant
Dim varIndex As Variant
Dim intIndex As Integer
varCriteria = Array(Nz(Me.txtSerial, "Null"), Nz(Me.txtCustomerOrder, "Null"), Nz(Me.txtAXProject, "Null"), Nz(Me.txtWorkOrder, "Null"))
intIndex = 0
For Each varIndex In varCriteria
strCriteria = varCriteria(intIndex)
If strCriteria <> "Null" Then
Call fnFindFoldersWithCriteria(TrailingSlash(Me.txtStartPath), strCriteria, 1)
End If
intIndex = intIndex + 1
Next varIndex
Set varIndex = Nothing
Set varCriteria = Nothing
strCriteria = ""
End Sub
Private Function fnFindFoldersWithCriteria(ByVal strStartPath As String, ByVal strCriteria As String, intCounter As Integer)
Dim fso As New FileSystemObject
Dim fldrStartFolder As Folder
Dim subfldrInStart As Folder
Dim subfldrInSubFolder As Folder
Dim subfldrInSubSubFolder As String
Dim strActionLog As String
Set fldrStartFolder = fso.GetFolder(strStartPath)
' Debug.Print "Criteria: " & Replace(strCriteria, " ", "", 1, , vbTextCompare) & " and Folder Name is " & Replace(fldrStartFolder.Name, " ", "", 1, , vbTextCompare) & " and Path is: " & fldrStartFolder.Path
If fnCompareCriteriaWithFolderName(fldrStartFolder.Name, strCriteria) Then
' Debug.Print "Found and Opening: " & fldrStartFolder.Name & "Because of: " & strCriteria
Shell "EXPLORER.EXE" & " " & Chr(34) & fldrStartFolder.Path & Chr(34), vbNormalFocus
Else
For Each subfldrInStart In fldrStartFolder.SubFolders
intCounter = intCounter + 1
Debug.Print "Criteria: " & Replace(strCriteria, " ", "", 1, , vbTextCompare) & " and Folder Name is " & Replace(subfldrInStart.Name, " ", "", 1, , vbTextCompare) & " and Path is: " & fldrStartFolder.Path
If fnCompareCriteriaWithFolderName(subfldrInStart.Name, strCriteria) Then
' Debug.Print "Found and Opening: " & subfldrInStart.Name & "Because of: " & strCriteria
Shell "EXPLORER.EXE" & " " & Chr(34) & subfldrInStart.Path & Chr(34), vbNormalFocus
Else
Call fnFindFoldersWithCriteria(subfldrInStart, strCriteria, intCounter)
End If
Me.txtProcessed = intCounter
Me.txtProcessed.Requery
Next
End If
Set fldrStartFolder = Nothing
Set subfldrInStart = Nothing
Set subfldrInSubFolder = Nothing
Set fso = Nothing
End Function
Private Function fnCompareCriteriaWithFolderName(strFolderName As String, strCriteria As String) As Boolean
fnCompareCriteriaWithFolderName = False
fnCompareCriteriaWithFolderName = InStr(1, Replace(strFolderName, " ", "", 1, , vbTextCompare), Replace(strCriteria, " ", "", 1, , vbTextCompare), vbTextCompare) > 0
End Function
Private Sub subListFolders(ByVal strFolders As String, intCounter As Integer)
Dim dbs As Database
Dim fso As New FileSystemObject
Dim fldFolders As Folder
Dim fldr As Folder
Dim subfldr As Folder
Dim sfldFolders As String
Dim strSQL As String
Set fldFolders = fso.GetFolder(TrailingSlash(strFolders))
Set dbs = CurrentDb
strSQL = "INSERT INTO tblFileList (FilePath, FileName, FolderSize) VALUES (" & Chr(34) & fldFolders.Path & Chr(34) & ", " & Chr(34) & fldFolders.Name & Chr(34) & ", '" & fldFolders.Size & "')"
dbs.Execute strSQL
For Each fldr In fldFolders.SubFolders
intCounter = intCounter + 1
strSQL = "INSERT INTO tblFileList (FilePath, FileName, FolderSize) VALUES (" & Chr(34) & fldr.Path & Chr(34) & ", " & Chr(34) & fldr.Name & Chr(34) & ", '" & fldr.Size & "')"
dbs.Execute strSQL
For Each subfldr In fldr.SubFolders
intCounter = intCounter + 1
sfldFolders = subfldr.Path
Call subListFolders(sfldFolders, intCounter)
Me.sfrmFolderList.Requery
Next
Me.txtListed = intCounter
Me.txtListed.Requery
Next
Set fldFolders = Nothing
Set fldr = Nothing
Set subfldr = Nothing
Set dbs = Nothing
End Sub
Private Function TrailingSlash(varIn As Variant) As String
If Len(varIn) > 0& Then
If Right(varIn, 1&) = "\" Then
TrailingSlash = varIn
Else
TrailingSlash = varIn & "\"
End If
End If
End Function
フォームにはテーブルに基づくサブフォームがあり、フォームには基準用の 4 つのテキスト ボックス、クリック手順につながる 2 つのボタン、および開始フォルダーの文字列を格納するための 1 つのテキスト ボックスがあります。リストされたフォルダーの数と、条件を検索するときに処理された数を表示するために使用される 2 つのテキスト ボックスがあります。
担当者がいたら、写真を投稿します... :/
このコードに追加したいことがいくつかありますが、まだ機会がありません。機能したものを別のテーブルに保存するか、ユーザーに保存してもよいとマークしてもらう方法が必要です。
すべてのコードの完全な功績を主張することはできません。スタックオーバーフローの他の投稿であっても、あちこちで見つけたものからいくつかをまとめました。
リンクされた記事にあるように、後で参照するために回答を簡単に見つけることができるため、ここに質問を投稿してから自分で回答するというアイデアが本当に気に入っています.
追加したい他の部分が完成したら、そのコードも投稿します。:)