I have a program with two text boxes. One is for a file path the other for a folder path (directory). Right now, my drag and drop feature properly allows only files paths in one text box and folder paths (directories) in the other.
However, I'm not certain if my verification method is proper.
Here are the two parts of the code that verify if file or directory:
If e.Data.GetDataPresent(DataFormats.FileDrop) Then
Dim filePathDragDrop() As String = CType(e.Data.GetData(DataFormats.FileDrop), String())
For Each pathTemp In filePathDragDrop
' This checks if it is a file
If File.GetAttributes(pathTemp) = FileAttributes.Archive Then
TextBoxCopyFrom.Text = pathTemp
End If
Next
End If
And for checking for directory a similar set up as above only this is different
' Checks for directory
If File.GetAttributes(pathTemp) = FileAttributes.Directory Then
TextBoxCopyTo.Text = pathTemp
End If
Is this the proper way to check if the file being dropped is indeed a file,
and if the folder (directory) being dropped is indeed a folder (directory)?
Is there any item that could be dropped that would be incorrectly verified?
I am assuming the archive part of "FileAttributes.Archive" pertains to file data.
No, that's not correct. The Archive attribute doesn't have to be turned on. It will be turned off when the user has used a backup program and the file hasn't changed since it was backed-up. Not actually sure if backup programs still work that way these days, but you can't make any assumptions.
The test for a directory is not correct. You'll need to test it like this:
If (File.GetAttributes(pathTemp) And FileAttributes.Directory) = FileAttributes.Directory Then
'' It's a directory
Else
'' It's a file
End If
Related
I'm trying to automate a document handling process, and I need to check if there are any files inside a certain folder. The process itself removes the files from the folder once it finishes, so I need it to loop back and check if there are any files left.
So far I've been using a sample file like this:
File.Exists("C:\Users\gcaor\Desktop\OC\150.pdf")
150.pdf is the sample file it's searching for, but is there a way to search for any file at all? So that it returns true if there is a file in the folder and false if there isn't
You can use Directory.EnumerateFiles + Any:
Dim anyFileExist = Directory.EnumerateFiles(path).Any()
This is using standard .NET methods and also stops at the first file found.
I encountered the following issue:
When accidentally passing a folder path to the Documents.Open function in VBA Word I get the runtime error 5174 as one would expect.
However all files with names that begin with an underscore get deleted in that moment from that folder.
To replicate:
Assume folder C:/Test/
In said folder have two files:
test.txt
_test.txt
In Word VBA execute the command:
Documents.Open("C:/Test/")
(As part of a subroutine or in the immediate window.)
Result: Runtime Error 5174 and _test.txt is now missing.
Note: Passing a nonexisting file like "C:/Test/abc.txt" or a wrong folder path like "C:/Test" (without the last slash) will not have this effect and won't cause the runtime error.
I have only tested this on one system on a network drive under windows 10 with Microsoft Professional Plus 2019. It's entirely possible that it's an issue with the file system. Does anyone have any suggestions as to why is this happening? I now included the workaround to check if I'm passing a folder, but it's still unnerving.
The Documents.Open method opens the specified document and adds it to the Documents collection. It is designed to take the file path, not a folder. If you want to allow users to pick file(s) you may consider using the file open dialog. The FileOpenDialog triggered by your code which opens a folder for picking files allows specifying file formats that should be supported and visible via the dialog window.
Set dlgSaveAs = Application.FileDialog(msoFileDialogFilePicker)
dlgSaveAs.Filter = "Text Files (.txt)|*.txt|Word Documents (.docx)|*.docx|Word Template (.dotx)|*.dotx|All Files (*.*)|*.*"
dlgSaveAs.ValidateNames = true
Res = dlgSaveAs.Show
Currently, I am working on a feature that will make the files inside the folder that will not hide the file extensions using this code.
Imports Microsoft.Win32
Sub SetNoDrives(value As Integer, path as string)
Dim RegPath As String = "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced]"
Using Key As RegistryKey = Registry.LocalMachine.OpenSubKey(RegPath)
Key.SetValue("HideFileExt", value, RegistryValueKind.DWord)
End Using
End Sub
the problem is, I don't know where to place the string path (folder path) on the code. the path is the specific location where you will always show the file extensions of the files inside the folder.
Any help will be much appreciated.
The reason you don't know where to put the folder path is because there is nowhere to put the folder path. This is a user-wide option, i.e. either extensions are displayed in every folder or no folder for the current user. You don't get to choose on a folder by folder basis. At least, there is no option in Windows/File Explorer to do that and I've never seen mention of it being possible, even when specifically searching for it.
I have a file exists under this path:
//path/folder1/folder2/datafile.gdp
It is an input to an external program being called from vba in this manner:
Sub RunProgram()
Dim wsh As Object
SetCurrentDirectory "\\path\"
ChDir "\\path\folder1\folder2\" 'Set Directory
Set wsh = VBA.CreateObject("WScript.Shell")
check = CurDir
Statusnum = wsh.Run(Command:="program.exe ""\\path\folder1\folder2\datafile.gdp""", WindowStyle:=1, waitonreturn:=True)
But on the final line, including \path\folder1\folder2\ before the input file name appears to cause the external program to want to write some files into a duplicated directory that doesn't exist, causing an error. It used to work in this format before the .exe was updated by an external company. It now wants to write some files here, all prefixed with the name of my input file:
\\path\folder1\folder2\PATH\FOLDER1\FOLDER2\
Hoping to fix this, I changed the final line of the code to this, following some comments on a previous post here on SO:
Statusnum = wsh.Run(Command:="program.exe ""datafile.gdp""", WindowStyle:=1, waitonreturn:=True)
Since the directory is set correctly prior to calling the .exe, I thought removing the path for the input file would solve the issue.
The program now launches, but doesn't appear to load the input file with it and no longer runs calculations automatically in the background as it should. Instead, it launches and the main .exe window pops up to the user as if it had just been launched for setting up a new project, calculations don't occur automatically.
To check which directory the VBA code was try to pull my datafile.gdp from, I created these loops directly before calling the .exe:
If Len(Dir("\\path\folder1\folder2\datafile.gdp")) = 0 Then
FileIsMissing1 = True 'I use Excel-VBA watches to break if true
End If
If Len(Dir("datafile.gdp")) = 0 Then
FileIsMissing2 = True
End If
Bizarrely, neither of these loops causes a break. The file only exists in
\\path\folder1\folder2\datafile.gdp
Not in the duplicated directory... so why are both of these statements satisfied? Does entering the directory make no difference even when the current directory has been set? The current directory seems to be impacting the line:
Statusnum = wsh.Run(Command:="program.exe ""\\path\folder1\folder2\datafile.gdp""", WindowStyle:=1, waitonreturn:=True)
But not these if loops, and I'm not sure why.
I'm making a console application and I want to see what files is in a folder
For Each foundFile As String In My.Computer.FileSystem.GetFiles("c:\users\zac\desktop\booked vehicle\requested\")
Console.WriteLine(foundFile)
Next
after using this code and find that the folder is empty I need an If statement that say's
If foundfile has no files then
tell user no files found
end if
but I don't know how to write this so Visual Basic understands.
Load the files into a variable then check the count.
Dim files = My.Computer.FileSystem.GetFiles("c:\users\zac\desktop\booked vehicle\requested\")
If files.Count = 0 Then
'tell user no files
Else
For Each file In files
Console.WriteLine(file)
Next
End If
FileSystem.GetFiles() returns a collection of file name strings. As OneFineDay showed, you can use the collection's Count property to know if any files were found.
The downside of using FileSystem.GetFile() is that it has to search the entire folder before then returning the entire list of filenames. If you are searching large folders and speed is an issue, consider using Directory.EnumerateFiles() instead. That way, you can output a message if no file was found, otherwise loop throuh the list of found files. For example:
Dim files = Directory.EnumerateFiles("c:\users\zac\desktop\booked vehicle\requested\").GetEnumerator()
If files.MoveNext Then
' files were found
Do
Console.WriteLine(files.Current)
Loop Until Not files.MoveNext
Else
' no files were found
End If
I personally would use Linq to accomplish this. It's very quick and efficient to use in this case. I put the Console.ReadLine() at the end to show the files, you can remove this if need to be. Also you can change the Console.WriteLine to not include the string (s) if you don't want to. The s was declared if you want to show the files and also to see if there are any files. As I said, this was for my viewing to see the files. Straight to the point!
Dim s As String = String.Join(Environment.NewLine, New DirectoryInfo("YOUR DIRECTORY").GetFiles().[Select](Function(file) file.Name).ToArray)
Console.WriteLine(If(s.Length > 0, s, "No files found!"))
Console.ReadLine()