Check if directory exists, but string is relative path - vba

I am currently writing a program to check if hyperlinks in a file are broken. Some hyperlinks go directly to folders on a mapped drive.
I want to use dir() to check if the folder exists, but Excel shortens the string to the relative version "../../Random folder/Another random folder"
This string returns "" so my function thinks the folder does not exist, but it does and its link functions properly.
Any help is greatly appreciated.
Thanks!

I believe you need to use the overloaded function of Dir and specify vbDirectory as the additional argument. I believe it should look something like this:
If Dir("X:\random directory\other random directory", vbDirectory) = "" Then

Related

How to get DirectoryInfo for a Onedrive folder with VB.net

I have some code that uses System.IO to find files with a given extension. This works fine with regular folders but fails when the files are in Onedrive's local cache.
My assumption is that the problem is to do with the Onedrive cache folder because if the files are moved out of Onedrive and into a local folder e.g. c:\temp, it all works fine.
Dim Folder As New IO.DirectoryInfo(TextBox_RootFolder.Text)
Filelist = Folder.GetFiles("*.xlsx", IO.SearchOption.AllDirectories)
This is VB, so I believe there should not be any issues with string literals, so I'm stumped.
The path string comes out as something similar to: "C:\Users\user\OneDrive - ThisPlace\MyFolder" so there's nothing particularly weird about the string.
When presented with a folder on Onedrive, my variable 'Folder' is correctly assigned with the full path but an exception is thrown on calling Folder.Getfiles. This results in the error "The tag present in the reparse point buffer is invalid".
BTW, I'm a novice so example code would be really appreciated as a detailed technical explanation is likely to go whoosh over my head.
I'm please to report that I found an easy way to solve the problem.
Firstly I retained the code that uses Folder.Getfiles to provide a list of files as this is fast, elegant and retrieves files in sub-folders.
It still throws an exception when it encounters a cloud sync folder such as Onedrive, DropBox etc., so in the catch I use the Dir() function to loop through the files as this does not have problems with folders of this type.
Here is some pseudo-code to show an example:
Dim sFile As String
sFile = Dir(sPath + "\*.xlsx")
Do While sFile <> ""
[ do stuff here ]
sFile = Dir() '' Get the next file
Loop
I hope this is helpful to someone.

Showing the File Extensions inside the folder

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.

VBA store path including Environ("username") in a text file

I am trying to create a text file that stores a folder path. This text file is then referenced via a vba sub. The path I want to use is something like:
"C:\Users\" & Environ("username") & "\AppData\Roaming\Microsoft\Templates"
This works fine in the sub but I've tried all kinds of variations in the text file but none of them get recognised and trigger error 52 - bad file.
Is there a way to make this work? I'm trying to allow people to set a different file path without needing to modify the code.
If you are trying to provide a path to the folder where user templates are stored then you could try
ActiveDocument.AttachedTemplate.Path
as an alternative (returns the path to the folder where the current template is stored for the user).
Otherwise store the path template as something like
"C:\Users\###UserName###\AppData\Roaming\Microsoft\Templates"
Which gives you a single string to retrieve. Then you can use the VBA Replace function to change the ###UserName### to the value of Environ("UserName)"
my_user_path = replace(my_path_template, Environ$("UserName"))
You might also want to explore using either a CustomDocumentProperty, or a Variables, to store your path template as this keeps the path template string as part of the Document or Template and not in a separate file.

Visual Basic FileSystem.GetFiles

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()

copy all files with certain extension

Hello I want to copy all files with and a specific extension. I've tried a few things but it isn't working. During my debug I get an exception "Illegal characters used in path" I'm guessing it doesn't like *.xls any suggestions?
First try
My.Computer.FileSystem.CopyFile("C:\test\test\mxw\*.xls\", "C:\workorder1-23\workorder1-23\mxw\", True)
second try
For Each f In Directory.GetFiles("C:\test\test\mxw\*.xls\", CStr(SearchOption.AllDirectories))
If My.Computer.FileSystem.FileExists(f.ToString) Then
File.Copy("C:\test\test\mxw\*.xls\", "C:\workorder1-23\workorder1-23\mxw\", True)
End If
Next
CopyFile copies just one file.
You cannot use it with wildcards to copy a group of files. (The invalid character is probably the wildcard)
And you should not append a backslash at the end of the file.
So let me try to replace your code with this
For Each f In Directory.GetFiles("C:\test\test\mxw", "*.xls", SearchOption.AllDirectories)
If File.Exists(f) Then
File.Copy(f, Path.Combine("C:\workorder1-23\workorder1-23\mxw", Path.GetFileName(f)), True)
End If
Next
Also Directory.GetFiles has three parameters, a path, a pattern and a flag to read subfolders
Since File.Copy does not create directories the provided answer will only work if the target directories exist. Add a Create.Directory(f) before the File.Copy if they don't.