I wrote a script to download files using VBA. The VBA script has to download items that start with https://collaboration.company.corp/collrooms/specificfolder or with \collaboration.company.corp#SSL\DavWWWRoot\collrooms\specificfolder
The specific folders are the same.
If I allow the script to select the specific mapping, it will only recognize it if I use the definition \collaboration.company.corp#SSL\DavWWWRoot\collrooms\specificfolder
How can I create a mapping in VBA to tell Excel that https://collaboration.company.corp/collrooms/specificfolder and \collaboration.company.corp#SSL\DavWWWRoot\collrooms\specificfolder is the same and that the first specification is also valid?
My code:
Option Explicit
Sub FolderSelection()
'Shows the folder picker dialog in order the user to select the folder
'in which the downloaded files will be saved.
Dim FoldersPath As String
'Show the folder picker dialog.
With Application.FileDialog(msoFileDialogFolderPicker)
.Title = "Select a folder to save your files..."
.Show
If .SelectedItems.Count = 0 Then
Sheets("Main").Range("B4") = "-"
MsgBox "You did't select a folder!", vbExclamation, "Canceled"
Exit Sub
Else
FoldersPath = .SelectedItems(1)
End If
End With
'Pass the folder's path to the cell. HERE I AM MISSING THE MAPPING. It will show files starting with https if selected and not transfer it to the other structure.
Sheets("Main").Range("B4") = FoldersPath
End Sub
Sub Clear()
'Clears the URLs, the result column and the folder's path.
Dim LastRow As Long
'Find the last row.
With Sheets("Main")
.Activate
LastRow = .Cells(.Rows.Count, "C").End(xlUp).Row
End With
'Clear the ranges.
If LastRow > 7 Then
With Sheets("Main")
.Range("C8:D" & LastRow).ClearContents
.Range("B4:D4").ClearContents
.Range("B4").Select
End With
End If
End Sub
and the other part of the download macro is
'Check if the folder exists. I did not check whether it will also download with the https structure?
DownloadFolder = sh.Range("B4")
On Error Resume Next
If Dir(DownloadFolder, vbDirectory) = vbNullString Then
MsgBox "The path is incorrect!", vbCritical, "Folder's Path Error"
sh.Range("B4").Select
Exit Sub
End If
On Error GoTo 0
I tried with a script that I found on Stackoverflow but it does not work
I created an additional module:
Sub test()
Dim dm As New DriveMapper
Dim sharepointFolder As Scripting.Folder
Set sharepointFolder = dm.MapDrive("https://collaboration.company.corp/collrooms/")
' unsure whether I have to add something here and whether this will work with https
Debug.Print sharepointFolder.Path
End Sub
and added the following WebDAV mapping as a new CLASS
Option Explicit
Private oMappedDrive As Scripting.Drive
Private oFSO As New Scripting.FileSystemObject
Private oNetwork As New WshNetwork
Private Sub Class_Terminate()
UnmapDrive
End Sub
Public Function MapDrive(NetworkPath As String) As Scripting.Folder
Dim DriveLetter As String, i As Integer
UnmapDrive
For i = Asc("Z") To Asc("A") Step -1
DriveLetter = Chr(i)
If Not oFSO.DriveExists(DriveLetter) Then
oNetwork.MapNetworkDrive DriveLetter & ":", NetworkPath
Set oMappedDrive = oFSO.GetDrive(DriveLetter)
Set MapDrive = oMappedDrive.RootFolder
Exit For
End If
Next i
End Function
Private Sub UnmapDrive()
If Not oMappedDrive Is Nothing Then
If oMappedDrive.IsReady Then
oNetwork.RemoveNetworkDrive oMappedDrive.DriveLetter & ":"
End If
Set oMappedDrive = Nothing
End If
End Sub
The question is also whether removing the dispose method "Class_Terminate" which unmaps the drive would help? When the class goes out of scope then the drive get's unmapped. And how I could put it all together.
Related
I'm experiencing some trouble with my VBA code. I have created an application in Excel and its copies have been distributed to users. To be able to correct bugs or add some new functions, every copy stores information what version it is. I have written procedure, that opens (read-only) a central file, that is providing some data a and information, which version is current. If the file, that opened this central file is older, it gets updated.
So the auto_open calls a procedure discovers that it has to be updated, saves the current file AS FileName_old.xlsm (to have some backup), kills the FileName.xlsm and copies a new file from a template. The problem is that the procedure crashes when it tries to kill the old file (to be more precise, it just ends without any error message). What confuses me is that when I run the auto_open macro manually (F5), everything goes correctly. Even step by step goes right. Also, when I call the update process via a button in a worksheet, it works perfectly. Any idea, what might cause this problem?
Thanks
Sub auto_open()
If Range("H_User").Value = "" Then UserNameWindows 'Write a user that is using this workbook in the range H_User
If Range("H_Updated").Value < FileDateTime(Range("H_File_Data").Value) Then UpdateData
End Sub
Sub UpdateData()
Dim ActWB As String
ActWB = ActiveWorkbook.Name
Application.ScreenUpdating = False
ThisWorkbook.Activate
If Not FileExists(Range("H_File_Data").Value) Then
MsgBox "The data file is not available!", vbCritical
Workbooks(ActWB).Activate
Application.ScreenUpdating = True
Exit Sub
End If
Dim WB As String, oknoData As String, IsTeam As Boolean, User As String
Dim version As Integer, Subversion As Integer, DataPath As String
On Error GoTo konec
Application.EnableCancelKey = xlDisabled
IsTeam = False
User = Range("H_User").Value
WB = ActiveWindow.Caption
version = Range("H_version").Value
Subversion = Range("H_Subversion").Value
Range("C_Data_All").ClearContents
DataPath = Range("H_File_Data").Value
Workbooks.Open fileName:=DataPath, ReadOnly:=True
oknoData = ActiveWindow.Caption
If Range("H_version_Spec").Value <= version Or (Range("H_version_Spec").Value = version And Range("H_Subversion_Spec").Value <= Subversion) Then
FileUpdate
End If
'If there is no need to update the file then continue with in this procedure
End Sub
Sub FileUpdate()
Dim NewPath As String, NewWB As String, OldPath As String, OldWB As String, BackupWB As String, BackupPath As String
Dim MainWB As String, version As String, Subversion As String
Dim versionMax As Integer, SubversionMax As Integer, versionMin As Integer, SubversionMin As Integer
ThisWorkbook.Activate
version = Range("H_version").Value
Subversion = Range("H_Subversion").Value
OldPath = ThisWorkbook.FullName
OldWB = ThisWorkbook.Name
BackupWB = Left(ThisWorkbook.Name, Len(ThisWorkbook.Name) - 5) & "_old.xlsm"
BackupPath = ThisWorkbook.Path & "\" & BackupWB
If Not FileExists(Workbooks(OldWB).Names("H_File_Data").RefersToRange.Value) Then
MsgBox "The data file is not available!", vbCritical
Exit Sub
End If
Workbooks.Open fileName:=Workbooks(OldWB).Names("H_File_Data").RefersToRange.Value, ReadOnly:=True
MainWB = ActiveWorkbook.Name
If version = Range("O_Spec_version").Value And Subversion >= Range("O_Spec_Subversion").Value Then
'Just some little piece of code if the version is not lower
Else
If FileExists(BackupPath) Then Kill (BackupPath)
If Not FileExists(Range("H_Path_Spec_Actual").Value) Then
MsgBox "The spec template is not available!", vbCritical
Exit Sub
End If
ThisWorkbook.SaveAs BackupPath
Kill (OldPath)
'Continue with update
End If
End Sub
Function FileExists(FilePath As String) As Boolean
Dim fso As Object
Set fso = CreateObject("scripting.filesystemobject")
FileExists= fso.FileExists(FilePath)
End Function
Option Explicit
Private Sub Workbook_Open()
Dim BackupPath As String
Dim OldPath As String
BackupPath = "folder\Filename_old.xlsm"
With ThisWorkbook
OldPath = .FullName
.SaveCopyAs BackupPath
.Saved = True
.ChangeFileAccess xlReadOnly
Kill .FullName
.Close False
End With
End Sub
I am trying to automate the tasks I would normally run through to compact my database, save backups, and update revision numbers for an automatic update system I am using. I am stuck on trying to make an accde file with a vba script.
Everything I find pertaining to the subject seems to point to using something like this.
function MakeACCDE(InPath As String, OutPath As String)
Dim app As New Access.Application
app.AutomationSecurity = msoAutomationSecurityLow
app.SysCmd 603, InPath, OutPath
End Function
A few users on various forums claim that this code works for them but I have not had any luck. My database runs the code without errors, but nothing actually happens.
Is there a particular piece of syntax I am not using or maybe something with the format of the file paths?
I found the following code at: http://www.experts-exchange.com/questions/28429044/How-do-I-create-an-Access-2010-accde-from-VBA.html
I inserted into my Access 2010 accdb, ran it, and it created an accde
**UPDATE: Seeing you want to run from a different DB, I tested that also... just change the line 'tmpDB_Full_Name = CurrentProject.FullName' to be your source database
Option Compare Database
Option Explicit
Function Create_MDE()
Dim tmpDB_Full_Name As String
Dim tmpDB_Name As String
Dim tmpDB_Backup_Full_Name As String
Dim tmpCopy_File As Variant
Dim tmpDirectory As String
'Call SetStartupOptions("AllowBypassKey", dbBoolean, False) '---This runs a procedure to deactivate the Shift & F11 key
'tmpDB_Full_Name = CurrentProject.FullName
tmpDB_Full_Name = "C:\data\access\MyDb.accdb"
tmpDirectory = CurrentProject.Path
tmpDB_Name = CurrentProject.Name
tmpDB_Backup_Full_Name = tmpDirectory & "\" & left(tmpDB_Name, Len(tmpDB_Name) - 6) & "-Backup.accdb"
'this removes a file created on the same day
If Dir(tmpDB_Backup_Full_Name) <> "" Then
Kill tmpDB_Backup_Full_Name
End If
'this creates a backup into destination tmpDirectory
If Dir(tmpDB_Backup_Full_Name) = "" Then
Set tmpCopy_File = CreateObject("Scripting.FileSystemObject")
tmpCopy_File.CopyFile tmpDB_Full_Name, tmpDB_Backup_Full_Name, True
End If
Dim app As New Access.Application
app.AutomationSecurity = msoAutomationSecurityLow
app.SysCmd 603, tmpDB_Backup_Full_Name, tmpDirectory & "\" & left(tmpDB_Name, Len(tmpDB_Name) - 9) & ".accde"
'Call SetStartupOptions("AllowBypassKey", dbBoolean, True) '---This runs a procedure to activate the Shift & F11
MsgBox ("Compile Complete!")
End Function
I have prepared a ready-made solution that creates an ACCDE file and at the same time allows you to protect it with a password. With frequent updates, it makes my life so much easier. I tested it on Microsoft Access 2016 and 2019.
The function SaveAccdbAsAccde() performs the following steps:
compiles and saves changes to the database
copies the database to '...(~temp~).ACCDB'
creates the file '...(~temp~).ACCDE'
if everything worked, it sets a password to the database and copies it as the target file
deletes working files
To protect the database with a password, do the following: SaveAccdbAsAccde("password")
I used a few functions that might also come in handy for other tasks:
helper functions based on Scripting.FileSystemObject for handling files use : CopyFile(),DeleteFile(),FileExists()
functions to secure / unsecure the database with a password EncryptDb() and DecryptDb()
All details below:
Option Explicit
'------------------------------------------------------------------------------------
'main function
Public Sub SaveAccdbAsAccde(Optional filePassword As String)
On Error Resume Next
Application.RunCommand acCmdCompileAndSaveAllModules
err.Clear
If err <> 0 Then MsgBox "Save changes in forms and reports before preparing the ACCDE file.": Exit Sub
On Error GoTo err_proc
Dim strFile0 As String, strFile1 As String, strFile2 As String, strFile3 As String
strFile0 = CurrentDb.Name
strFile1 = Replace(CurrentDb.Name, ".accdb", "(~temp~).accdb")
strFile2 = Replace(CurrentDb.Name, ".accdb", "(~temp~).accde")
strFile3 = Replace(CurrentDb.Name, ".accdb", ".accde")
If Not DeleteFile(strFile1) Then MsgBox "Can't felete file: " & strFile2: Exit Sub
If Not CopyFile(strFile0, strFile1) Then MsgBox "Can't copy file: " & strFile0 & " na " & strFile1: Exit Sub
If Not DeleteFile(strFile2) Then MsgBox "Can't delete file: " & strFile2: Exit Sub
MakeACCDESysCmd strFile1, strFile2
If Not FileExists(strFile2) Then MsgBox "Can't create file: " & strFile2: Exit Sub
If Not DeleteFile(strFile3) Then MsgBox "Can't delete file: " & strFile3: Exit Sub
EncryptDb strFile2, strFile3, filePassword
If Not FileExists(strFile3) Then MsgBox "Can't create file: " & strFile3: Exit Sub
If Not DeleteFile(strFile2) Then MsgBox "Can't delete file: " & strFile2: Exit Sub
If Not DeleteFile(strFile1) Then MsgBox "Can't delete file: " & strFile2: Exit Sub
MsgBox "Done: " & strFile3
exit_proc:
Exit Sub
err_proc:
MsgBox err.Description, vbCritical, "Error"
Resume exit_proc
End Sub
'------------------------------------------------------------------------------------
Public Sub EncryptDb(strSourcePath As String, strDestPath As String, pwd As String)
If pwd <> "" Then pwd = ";pwd=" & pwd
DBEngine.CompactDatabase strSourcePath, strDestPath, dbLangGeneral & pwd, dbVersion167, pwd
End Sub
Public Sub DecryptDb(strSourcePath As String, strDestPath As String, pwd As String)
If pwd <> "" Then pwd = ";pwd=" & pwd
DBEngine.CompactDatabase strSourcePath, strDestPath, dbLangGeneral & ";pwd=", dbVersion167, pwd
End Sub
Public Function MakeACCDESysCmd(InPath As String, OutPath As String)
Dim app As Access.Application
Set app = New Access.Application
app.AutomationSecurity = 1 'msoAutomationSecurityLow - Enables all macros. This is the default value when the application is started.
app.SysCmd 603, InPath, OutPath 'an undocumented action
app.Quit acQuitSaveNone
Set app = Nothing
End Function
'------------------------------------------------------------------------------------
Public Function CopyFile(strFromFile, strToFile)
On Error Resume Next
Dim objFSO
Set objFSO = CreateObject("Scripting.FileSystemObject")
err.Clear
objFSO.CopyFile strFromFile, strToFile, True
CopyFile = err = 0
Set objFSO = Nothing
End Function
Public Function DeleteFile(strFile)
If Not FileExists(strFile) Then DeleteFile = True: Exit Function
On Error Resume Next
Dim objFSO
Set objFSO = CreateObject("Scripting.FileSystemObject")
err.Clear
objFSO.DeleteFile strFile, True
DeleteFile = err = 0
Set objFSO = Nothing
End Function
Public Function FileExists(strFile)
On Error Resume Next
Dim objFSO
Set objFSO = CreateObject("Scripting.FileSystemObject")
On Error Resume Next
FileExists = objFSO.FileExists(strFile)
Set objFSO = Nothing
End Function
I have tested the following code in Access 2016 using ACCDE and ACCDR as the destination file extension:
Dim otherAccess As Access.Application
Set otherAccess = New Access.Application
otherAccess.AutomationSecurity = 1 'msoAutomationSecurityLow
otherAccess.SysCmd 603, InPath, OutPath
otherAccess.Quit acQuitSaveNone
Set otherAccess = Nothing
I have a spreadsheet I open programmatically using the VBA in Access:
Set xl = CreateObject("Excel.Application")
With xl
Call RunASCFormatting(xl, wb, strPath)
'More code
Sub RunASCFormatting(xl As Excel.Application, wb As Excel.Workbook, strPath As String)
With xl
If .ProtectedViewWindows.count > 0 Then
.ActiveProtectedViewWindow.Edit
End If
Set wb = .Workbooks.Open(Trim(strPath) & "ASC.xls", True, False)
wb.Sheets(1).Rows("1:1").Delete Shift:=xlUp
.ActiveWorkbook.SaveAs FileName:=Trim(strPath) & "ASC.xlsx" _
, FileFormat:=xlOpenXMLWorkbook, CreateBackup:=False
End With
End Sub
I have added in the "If" statement in the sub as I was hoping it would remove the "Protected View - Editing this file type is not recommended due to your File Block settings in the Trust Center" message. What I'm trying to achieve is to get the "Enable Editing" button removed, so this macro can enable editing and run as planned.
Currently, the code falls at the "Set wb" line. What is the proper way to achieve what I'm after?
One possibility is to change the macro security settings programmatically to the lowest before you open the Excel workbook. After manipulating your data, re-enable the previous setting of the macro security.
Here's some revised code which I found at http://www.mrexcel.com/forum/excel-questions/631545-change-trust-center-settings-visual-basic-applications.html:
Public Sub MySubroutine()
Dim lSecurity As Long
lSecurity = Application.AutomationSecurity
Application.AutomationSecurity = msoAutomationSecurityLow
'''''''''''''''''''''
' Run code here '
'''''''''''''''''''''
Application.AutomationSecurity = lSecurity
End Sub
As a side comment, VBA implements Integer as Long, so it could actually be slightly more performance degrading to declare Integer variables as it has to reinterpret the Integer keyword. When I learned that, I started declaring an Integer as Long instead. I actually read this in some Microsoft documentation, but I lost the link to it years ago.
Sub trusted_locations(path_to_add)
Const HKEY_CURRENT_USER = &H80000001
Dim oRegistry
Dim sDescription 'Description of the Trusted Location
Dim bAllowSubFolders 'Enable subFolders as Trusted Locations
Dim bAllowNetworkLocations 'Enable Network Locations as Trusted
' Locations
Dim bAlreadyExists
Dim sParentKey
Dim iLocCounter
Dim arrChildKeys
Dim sChildKey
Dim sValue
Dim sNewKey
Dim vers As Variant
'Determine the location/path of the user's MyDocuments folder
'*******************************************************************************
Set oRegistry = GetObject("winmgmts:\\.\root\default:StdRegProv")
bAllowSubFolders = True
bAlreadyExists = False
vers = Application.Version
sParentKey = "Software\Microsoft\Office\" & vers & "\Excel\Security\Trusted Locations"
iLocCounter = 0
oRegistry.EnumKey HKEY_CURRENT_USER, sParentKey, arrChildKeys
For Each sChildKey In arrChildKeys
oRegistry.GetStringValue HKEY_CURRENT_USER, sParentKey & "\" & sChildKey, "Path", sValue
If sValue = spath Then bAlreadyExists = True
If CInt(Mid(sChildKey, 9)) > iLocCounter Then
iLocCounter = CInt(Mid(sChildKey, 9))
End If
Next
'Uncomment the following 4 linesif your wish to enable network locations as Trusted
' Locations
bAllowNetworkLocations = True
If bAllowNetworkLocations Then
oRegistry.SetDWORDValue HKEY_CURRENT_USER, sParentKey, "AllowNetworkLocations", 1
End If
If bAlreadyExists = False Then
sNewKey = sParentKey & "\Location" & CStr(iLocCounter + 1)
oRegistry.CreateKey HKEY_CURRENT_USER, sNewKey
oRegistry.SetStringValue HKEY_CURRENT_USER, sNewKey, "Path", path_to_be_added
oRegistry.SetStringValue HKEY_CURRENT_USER, sNewKey, "Description", description_of_path
If bAllowSubFolders Then
oRegistry.SetDWORDValue HKEY_CURRENT_USER, sNewKey, "AllowSubFolders", 1
End If
End If
End Sub
You can try turning off protected view settings in the Trust Center
http://office.microsoft.com/en-us/excel-help/what-is-protected-view-HA010355931.aspx#BM5
http://www.howtogeek.com/60310/enable-editing-for-all-office-2010-documents-by-disabling-protected-view/
This may be harmful.
Additionally you should set trusted locations.
Sub fileBlock(value As Long)
Const HKEY_CURRENT_USER = &H80000001
Dim oRegistry
Dim sParentKey
Dim vers As Variant
Dim item As String: item = filetype_to_change_fileblock
'Determine the location/path of the user's MyDocuments folder
'*******************************************************************************
Set oRegistry = GetObject("winmgmts:\.\root\default:StdRegProv")
vers = Application.Version
sParentKey = "Software\Microsoft\Office\" & vers & "\Excel\Security\FileBlock"
oRegistry.SetDWORDValue HKEY_CURRENT_USER, sParentKey, item, value
End Sub
My goal is to export excel file to txt file format. The idea is to has a GUI to let user select the excel file that she/he wish to export and she/he can decide which file path and file name to save. Once users has finish input and output setting, he/she just need to click Export text button to export the excel file to txt file and save in the location that he/she has decided. The GUI as below
I've a macro to convert excel file to txt format
Private Sub ConvertToText()
ActiveWorkbook.SaveAs FileName:="C:\Projects\ExelToText\Text.txt", FileFormat:=xlCurrentPlatformText, CreateBackup:=False
End Sub
My question is how could I pass value from FileInput and FileOutput as variable to above macro instead harcode the filepath. Appreciate your helps and if you have any better suggestions, please share it out. Thanks
Below is the full source code
Private Sub ReadButton_Click()
OpenWorkbookUsingFileDialog
End Sub
------------------------------
Private Sub WriteButton_Click()
WriteWorkbookUsingFileDialog
End Sub
------------------------------
Private Sub ExportButton_Click()
ConvertToText
End Sub
------------------------------
Private Sub OpenWorkbookUsingFileDialog()
Dim fdl As FileDialog
Dim FileName As String
Dim FileChosen As Integer
Set fdl = Application.FileDialog(msoFileDialogFilePicker)
fdl.Title = "Please Select a Excel File"
fdl.InitialFileName = "c:\"
fdl.InitialView = msoFileDialogViewSmallIcons
fdl.Filters.Clear
fdl.Filters.Add "Excel Files", "*.xlsx; *.xls"
FileChosen = fdl.Show
If FileChosen <> -1 Then
MsgBox "You have choosen nothing"
ReadTextBox = Null
Else
MsgBox fdl.SelectedItems(1)
FileName = fdl.SelectedItems(1)
ReadTextBox = FileName
End If
End Sub
-----------------------------------
Private Sub WriteWorkbookUsingFileDialog()
Dim file_name As Variant
file_name = Application.GetSaveAsFilename( _
FileFilter:="Text Files,*.txt,All Files,*.*", _
Title:="Save As File Name")
If file_name = False Then Exit Sub
If LCase$(Right$(file_name, 4)) <> ".txt" Then
file_name = file_name & ".txt"
End If
WriteTextBox = file_name
End Sub
----------------------------
Private Sub ConvertToText()
ActiveWorkbook.SaveAs FileName:="C:\Projects\ExelToText\Text.txt",FileFormat:=xlCurrentPlatformText, CreateBackup:=False
End Sub
Make it so your subroutine ConvertToText requires a file path/string argument:
Private Sub ConvertToText(sourcePath as String, destPath as String)
Dim wb as Workbook
Set wb = Workbooks.Open(sourcePath)
wb.SaveAs FileName:=destPath,
FileFormat:=xlCurrentPlatformText, CreateBackup:=False
wb.Close
End Sub
Then, make small modifications to your ExportButton to send this parameter to the ConvertToText sub:
Private Sub ExportButton_Click()
On Error Resume Next
ConvertToText Me.TextBox1.Value, Me.TextBox2.Value 'Modify this so that it refers to the TextBoxes on your form
If Err.Number <> 0 Then
MsgBox "Unable to convert file. Please ensure a valid file was entered.", vbCritical
End If
On Error GoTo 0
End Sub
This question already has answers here:
Get File Path (ends with folder)
(6 answers)
Closed 4 years ago.
I have a small Access VBA application that requires users to select a folder. I was wondering if there is a way to tell VBA the path at which to start the folder picker. i.e. start the folder picker at C:\data\forms. Currently it seems to be starting from the directory that was previously used. Also is there a way to limit what the folder picker can access. So it can access anything within C:\data but not anything else in C:
I have been using the following code (Not My Code) successfully for many years.
Sub Sample()
Dim Ret
'~~> Specify your start folder here
Ret = BrowseForFolder("C:\")
End Sub
Function BrowseForFolder(Optional OpenAt As Variant) As Variant
'Function purpose: To Browser for a user selected folder.
'If the "OpenAt" path is provided, open the browser at that directory
'NOTE: If invalid, it will open at the Desktop level
Dim ShellApp As Object
'Create a file browser window at the default folder
Set ShellApp = CreateObject("Shell.Application"). _
BrowseForFolder(0, "Please choose a folder", 0, OpenAt)
'Set the folder to that selected. (On error in case cancelled)
On Error Resume Next
BrowseForFolder = ShellApp.self.Path
On Error GoTo 0
'Destroy the Shell Application
Set ShellApp = Nothing
'Check for invalid or non-entries and send to the Invalid error
'handler if found
'Valid selections can begin L: (where L is a letter) or
'\\ (as in \\servername\sharename. All others are invalid
Select Case Mid(BrowseForFolder, 2, 1)
Case Is = ":"
If Left(BrowseForFolder, 1) = ":" Then GoTo Invalid
Case Is = "\"
If Not Left(BrowseForFolder, 1) = "\" Then GoTo Invalid
Case Else
GoTo Invalid
End Select
Exit Function
Invalid:
'If it was determined that the selection was invalid, set to False
BrowseForFolder = False
End Function
Here is a quick and dirty method I use all the time. The function below will only get the user to select the folder they want to start at - I think the simplest way to limit access to a given path is to perhaps check GetFolderName below against the path(s) you want to restrict e.g.
If GetFolderName = "C:\" then
MsgBox("This folder is not for you buddy")
Exit Sub
end if
Also not my code :)
Public Function GetFolderName(Optional OpenAt As String) As String
Dim lCount As Long
GetFolderName = vbNullString
With Application.FileDialog(msoFileDialogFolderPicker)
.InitialFileName = OpenAt
.Show
For lCount = 1 To .SelectedItems.Count
GetFolderName = .SelectedItems(lCount)
Next lCount
End With
End Function
If you do not need to restrict the folder-view to your user, then I would suggest using the FileDialog method (the interface is more intuitive then what invoking the shell gives you). For additional details, you can read more on CPearson's site. He has a lengthy article on browsing for folders using VBA (mulitple ways; the FileDialog option is at the very end):
Function BrowseFolder(Title As String, _
Optional InitialFolder As String = vbNullString, _
Optional InitialView As Office.MsoFileDialogView = _
msoFileDialogViewList) As String
Dim V As Variant
Dim InitFolder As String
With Application.FileDialog(msoFileDialogFolderPicker)
.Title = Title
.InitialView = InitialView
If Len(InitialFolder) > 0 Then
If Dir(InitialFolder, vbDirectory) <> vbNullString Then
InitFolder = InitialFolder
If Right(InitFolder, 1) <> "\" Then
InitFolder = InitFolder & "\"
End If
.InitialFileName = InitFolder
End If
End If
.Show
On Error Resume Next
Err.Clear
V = .SelectedItems(1)
If Err.Number <> 0 Then
V = vbNullString
End If
End With
BrowseFolder = CStr(V)
End Function
This function takes two parameters. The first, Title is a string specifying the title to be displayed with the file dialog. The second InitialFolder, which is optional, specifies the initial folder to which the dialog should open. The third parameter, also optional, InitialView specifies the view type. See MsoFileDialogView in the Object Browser for the valid values of this parameter. The function returns the fully-qualified folder name selected by the user or an empty string if the user cancelled the dialog.
Here is a much simpler way. This code snippet lets user pick a folder and then prints that folder address to the screen:
Sub PrintSelectedFolder()
Dim selectedFolder
With Application.FileDialog(msoFileDialogFolderPicker)
.Show
selectedFolder = .SelectedItems(1)
End With
'print to screen the address of folder selected
MsgBox (selectedFolder)
End Sub
For mac users:
Sub Select_Folder_On_Mac()
Dim folderPath As String
Dim RootFolder As String
On Error Resume Next
RootFolder = MacScript("return (path to desktop folder) as String")
'Or use RootFolder = "Macintosh HD:Users:YourUserName:Desktop:TestMap:"
folderPath = MacScript("(choose folder with prompt ""Select the folder""" & _
"default location alias """ & RootFolder & """) as string")
On Error GoTo 0
If folderPath <> "" Then
MsgBox folderPath
End If
End Sub
Stolen from http://www.rondebruin.nl/mac/mac017.htm ;)