Extract filename from path [duplicate] - vba

This question already has answers here:
How to extract file name from path?
(16 answers)
Closed 1 year ago.
I need to extract the filename from a path (a string):
e.g.,
"C:\folder\folder\folder\file.txt" = "file" (or even "file.txt" to get me started)
Essentially everything before and including the last \
I've heard of using wildcards in place of Regex (as it's an odd implementation in VBA?) but can't find anything solid.
Cheers in advance.

I believe this works, using VBA:
Dim strPath As String
strPath = "C:\folder\folder\folder\file.txt"
Dim strFile As String
strFile = Right(strPath, Len(strPath) - InStrRev(strPath, "\"))
InStrRev looks for the first instance of "\" from the end, and returns the position. Right makes a substring starting from the right of given length, so you calculate the needed length using Len - InStrRev

Thanks to kaveman for the help. Here is the full code I used to remove both the path and the extension (it is not full proof, does not take into consideration files that contain more than 2 decimals eg. *.tar.gz)
sFullPath = "C:\dir\dir\dir\file.txt"
sFullFilename = Right(sFullPath, Len(sFullPath) - InStrRev(sFullPath, "\"))
sFilename = Left(sFullFilename, (InStr(sFullFilename, ".") - 1))
sFilename = "file"

I was looking for a solution without code. This VBA works in the Excel Formula Bar:
To extract the file name:
=RIGHT(A1,LEN(A1)-FIND("~",SUBSTITUTE(A1,"\","~",LEN(A1)-LEN(SUBSTITUTE(A1,"\","")))))
To extract the file path:
=MID(A1,1,LEN(A1)-LEN(MID(A1,FIND(CHAR(1),SUBSTITUTE(A1,"\",CHAR(1),LEN(A1)-LEN(SUBSTITUTE(A1,"\",""))))+1,LEN(A1))))

`You can also try:
Sub filen()
Dim parts() As String
Dim Inputfolder As String, a As String
'Takes input as any file on disk
Inputfolder = Application.GetOpenFilename("Folder, *")
parts = Split(Inputfolder, "\")
a = parts(UBound(parts()))
MsgBox ("File is: " & a)
End Sub
This sub can display Folder name of any file

Here's simpler method: a one-line function to extract only the name — without the file extension — as you specified in your example:
Function getName(pf):getName=Split(Mid(pf,InStrRev(pf,"\")+1),".")(0):End Function
...so, using your example, this:
       MsgBox getName("C:\folder\folder\folder\file.txt")
  returns:
       
For cases where you want to extract the filename while retaining the file extension, or if you want to extract the only the path, here are two more single-line functions:
Extract Filename from x:\path\filename:
Function getFName(pf)As String:getFName=Mid(pf,InStrRev(pf,"\")+1):End Function
Extract Path from x:\path\filename:
Function getPath(pf)As String: getPath=Left(pf,InStrRev(pf,"\")): End Function
Examples:
(Source)

Using Java:
String myPath="C:\folder\folder\folder\file.txt";
System.out.println("filename " + myPath.lastIndexOf('\\'));

I used kaveman's suggestion successfully as well to get the Full File name but sometimes when i have lots of Dots in my Full File Name, I used the following to get rid of the .txt bit:
FileName = Left(FullFileName, (InStrRev(FullFileName, ".") - 1))

You can use a FileSystemObject for that.
First, include a reference for de Microsoft Scripting Runtime (VB Editor Menu Bar > Tools > References).
After that, you can use a function such as this one:
Function Get_FileName_fromPath(myPath as string) as string
Dim FSO as New Scripting.FileSystemObject
'Check if File Exists before getting the name
iF FSO.FileExists(myPath) then
Get_FileName_fromPath = FSO.GetFileName(myPath)
Else
Get_FileName_fromPath = "File not found!"
End if
End Function
File System Objects are very useful for file manipulation, especially when checking for their existence and moving them around. I like to use them early bound (Dim statement), but you can use them late bound if you prefer (CreateObject statement).

'[/vba]
' Keep It Simple
' .. why use FileSystemObject or Split when Left and Mid will do it
' the FSO has some 33 Subs or Functions
that have to be loaded each time it is created.
' and needs the file to exist ... yet is only a bit slower
... under twice time.. some good code in FSO
' conservation is good .. spare a few electrons. ????... save a few millionths of a sec
'Also
' .. why the format of a function that we all seem to use like
'
' .. Function GetAStr(x) as string
' dim extraStr as string
' a lot of work with extraStr..
' that could have been done with the string variable GetAStr
already created by the function
' then .. GetAStr=extraStr to put it in its right place
' .. End Function
Function GetNameL1$(FilePath$, Optional NLess& = 1)
' default Nless=1 => name only
' NLess =2 => xcopya.xls xcopyb.xls xcopy7.xlsm all as xcopy to get find latest version
' Nless = - 4 or less => name with name.ext worka.xlsm
GetNameL1 = Mid(FilePath, InStrRev(FilePath, "") + 1)
GetNameL1 = Left(GetNameL1, InStrRev(GetNameL1, ".") - NLess)
End Function
Function LastFold$(FilePath$)
LastFold = Left(FilePath, InStrRev(FilePath, "") - 1)
LastFold = Mid(LastFold, InStrRev(LastFold, "") + 1)
End Function
Function LastFoldSA$(FilePath$)
Dim SA$(): SA = Split(FilePath, "")
LastFoldSA = SA(UBound(SA) - 1)
End Function
[<vba]

Related

Count words in an external file using delimiter of a space

I want to calculate the number of words in a text file using a delimiter of a space (" "), however I am struggling.
Dim counter = 0
Dim delim = " "
Dim fields() As String
fields = Nothing
Dim line As String
line = Input
While (SR.EndOfStream)
line = SR.ReadLine()
End While
Console.WriteLine(vbLf & "Reading File.. ")
fields = line.Split(delim.ToCharArray())
For i = 0 To fields.Length
counter = counter + 1
Next
SR.Close()
Console.WriteLine(vbLf & "The word count is {0}", counter)
I do not know how to open the file and to get the do this, very confused; would like an explanation so I can edit and understand from it.
You're going to be reading a file as the source of the data, so let's create a variable to refer to its filename:
Dim srcFile = "C:\temp\twolines.txt"
As you have shown already, a variable is needed to hold the number of words found:
Dim counter = 0
To read from the file, a StreamReader will do the job. Now, we look at the documenation for it (yes, really) and notice that it has a Dispose method. That means that we have to explicitly dispose of it after we've used it to make sure that no system resources are tied up until the computer is next rebooted (e.g there could be a "memory leak"). Fortunately, there is the Using construct to take care of that for us:
Using sr As New StreamReader(srcFile)
And now we want to iterate over the content of the file line-by-line until the end of the file:
While Not sr.EndOfStream
Then we want to read a line and find how many items separated by spaces it has:
counter += sr.ReadLine().Split({" "c}, StringSplitOptions.RemoveEmptyEntries).Length
The += operator is like saying "add n to a" instead of saying "a = a + n". The {" "c} is a literal array of the character " "c. The c tells it that is a character and not a string of one character. The StringSplitOptions.RemoveEmptyEntries means that if there was text of "one two" then it would ignore the extra spaces.
So, if you were writing a console program, it might look like:
Imports System.IO
Module Module1
Sub Main()
Dim srcFile = "C:\temp\twolines.txt"
Dim counter = 0
Using sr As New StreamReader(srcFile)
While Not sr.EndOfStream
counter += sr.ReadLine().Split({" "c}, StringSplitOptions.RemoveEmptyEntries).Length
End While
End Using
Console.WriteLine(counter)
Console.ReadLine()
End Sub
End Module
Any embellishments such as writing out what the number represents or error checking are left up to you.
With Path.Combine you don't have to worry about where the slashes or back slashes go. You can get the path of special folders easily using the Environment class. The File class of System.IO is shared so you don't have to create an instance.
Public Sub Main()
Dim p As String = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "Chapters.txt")
Debug.Print(Environment.SpecialFolder.MyDocuments.ToString)
Dim count As Integer = GetCount(p)
Console.WriteLine(count)
Console.ReadKey()
End Sub
Private Function GetCount(Path As String) As Integer
Dim s = File.ReadAllText(Path)
Return s.Split().Length
End Function
Use Split function, then Directly get the length of result array and add 1 to it.

open/import multiple files vb.net

ok im going to try to explain this the best i can.
So i have a list viewer for image thumbnails.
I need to be able to click a button and it load the full dir. The issue is the normal way loads the images in but they are out of order. 1.jpg 10.jpg 100.jpg
For Each file As String In My.Computer.FileSystem.GetFiles(appPath + "\" + ConfigurationManager.AppSettings("activedisplay").ToString + "\" + Bfolder.Text + "\")
ImageListView1.Items.Add(file)
Next
So i went and looked around for a filter
Dim files = Directory.EnumerateFiles(appPath + "\" + ConfigurationManager.AppSettings("activedisplay").ToString + "\" + Bfolder.Text + "\").
Select(Function(s) Path.GetFileName(s)).ToList
Console.WriteLine("Before: {0}", String.Join(", ", files))
' sort the list using the Natural Comparer:
files.Sort(myComparer)
MsgBox((String.Join(", ", files)))
So this script puts them in the right order 1,2,3,4,5.. but i cant figure out how to open it this way. Cause
ImageListViewer1.items.addrange((String.Join(", ", files)))
overloads.
Like openFileDialog.FileNames has the ability to open multiple files at once so I know its possible but i don't want to use a dialog.
To the point i need a way to load the file string produced by this which is 1.jpg,2.jpg,3.jpg into the ImageViewerList.
This creates a string of the file in the correct order "(String.Join(", ", files))" is there a way i can load files from a string.
For Each file As String In My.Computer.FileSystem.GetFiles(appPath, string
and it be able to load the string of files it creates the string like so
1.jpg,2.jpg,3.jpg continued for all files in the dir it looked at
iv looked around google for assistance and looked at the ms page on getfiles but i have had no luck.
any ways any help would be greatly appreciated
thanks in advance
-Fox
You need to write your own sort function to sort the numeric values.
I referred the link, for CustomSort function. Below code sorts the file names and works nicely for me.
Dim Dir As String = appPath + "\" + ConfigurationManager.AppSettings("activedisplay").ToString + "\" + Bfolder.Text + "\"
Dim fileList = New DirectoryInfo(Dir).GetFiles("*.jpg").[Select](Function(o) o.Name).ToList()
Dim sortedList = CustomSort(fileList).ToList()
Public Shared Function CustomSort(list As IEnumerable(Of String)) As IEnumerable(Of String)
Dim maxLen As Integer = list.[Select](Function(s) s.Length).Max()
Return list.[Select](Function(s) New With { _
Key .OrgStr = s, _
Key .SortStr = Regex.Replace(s, "(\d+)|(\D+)", Function(m) m.Value.PadLeft(maxLen, If(Char.IsDigit(m.Value(0)), " "c, "?"c))) _
}).OrderBy(Function(x) x.SortStr).[Select](Function(x) x.OrgStr)
End Function

InSTR or find function in VBA

I am stuck with an issue. I've done my research and found out that I can use InSTR function to search for a specific character in a string.
What I am trying to do is get a file name extracted from a file path.
Currently I have
InStr(StrFrom(pName), "\")
The issue here is, it returns the first occurrence of slash, where as I want to get the last occurrence of the slash (so that I can use a 'right' function wrapped around the above code to capture the file name)
Any help is appreciated on how to get the last slash in a string!
Thanks!
Instr looks from the start of the text string, InstrRev starts looking from the other end.
Public Function FileNameOnly(ByVal FileNameAndPath As String) As String
FileNameOnly = Mid(FileNameAndPath, InStrRev(FileNameAndPath, "\") + 1, Len(FileNameAndPath))
End Function
Consider:
Sub marine()
Dim s As String, ary
s = "C:\whatever\sub1\sub2\reallydeep\x.xlsm"
ary = Split(s, "\")
MsgBox ary(UBound(ary))
End Sub
Use InStrRev() to find the first occurrence of the slash from the right side of the string.
https://msdn.microsoft.com/en-us/library/t2ekk41a(v=vs.90).aspx
Assuming StrFrom is some user defined function, the following will do what you want:
Dim filename as String
Dim path as String
path = StrFrom(pName)
filename = Mid$(path, InstrRev(path, "\") + 1)
Note that its easier to use Mid$ than Right$, as InstrRev returns the character position from the left of the string. Omitting the final parameter of Mid$, returns the rest of the string from that position.

Need to strip numbers out of a filename string to change save location

I'm having an issue where I need to strip a filename from a path but can't quite figure out the code.
An example filename would be C:\Checked out parts\001-1099-01.slddrw. I need to extract the "001-1099-01." portion. The file location to the left could be anything and the only constants in the file name are the "001-" portion (which I should point out, could repeat if the filename was 001-1001-03) and the ".slddrw". Other than that the filename could be named "001-10999-03-02-01".
I have stripped out the slddrw portion easily, I tried using Right and InStr functions to strip the rest off but I think that InStr only works with letters (couldn't find any number examples anyways)
I believe this is what you are looking for:
Public Sub test()
Dim strFileName As String
'Your sample file name
strFileName = "C:\Checked out parts\001-1099-01.slddrw"
'Search for the first occurance of \ in the reversed (!) file name
' if you substract this result from the length of the string
' you know where to start (+ 2 to avoid the \ itself)
strFileName = Mid(strFileName, Len(strFileName) - InStr(1, StrReverse(strFileName), "\") + 2)
'Remove the .slddrw portion from the end
strFileName = Replace(strFileName, ".slddrw", "")
'Done
Debug.Print strFileName
End Sub
Note the comments in the code for more information.
You can use a sub in which you define the path and extension of your file and it will give you the filename.
Sub getFileName()
Dim myString() As String
Dim path As String, extension As String
Dim fileName As String
path = "C:\Checked out parts\"
extension = ".slddrw"
'Say your string is in cell A1
myString = Split(Range("A1"), path)
fileName = Split(myString(1), extension)(0)
MsgBox fileName 'fileName can be used elsewhere after
End Sub
You could also do it as a function:
Function getFileName(cel As Range, path As String, extension As String)
Dim myString() As String
myString = Split(cel, path)
getFileName = Split(myString(1), extension)(0)
End Function
If you have the path and extensions stored in cells, you can use this function:
Function getFileName2(cel As Range, path As Range, extension As Range)
Dim myString() As String
myString = Split(cel, path)
getFileName2 = Split(myString(1), extension)(0)
End Function
Those are the options I can think of, hope it helps.
EDIT:
If you don't know the path nor the extension, you can use this instead:
myString = Split(Range("A1"), "\")
fileName = Split(myString(UBound(myString)), ".")(0)

Check if part of file name exists in a path using .net

I would like to check in my weapplication if a file exists in a path provided. File name can be anything eg:pic.jpg, pic.txt,pic1.txt,pic2.jpg etc.
I need to check if "pic" name exists in the path.Only check if 'pic' exists or pic+anything+.jpg or pic.anything.txt exists using vb.net.
Please help.
You'll want to check the File.Exists method. Don't forget, this only work for finding files on the server, not the client. Finding a file on the client side is a totaly different mather.
You can get the list of files in the given directory and then check the filenames to see if the fragment of text you're looking for is in any of them. Assuming you want to include the extension in the test and you don't care if it is upper or lower case:
Function FilenameFragmentExists(srcDir As String, fragment As String) As Boolean
Dim files() As String = IO.Directory.GetFiles(srcDir)
Dim found As Boolean = False
For i = 0 To files.Length - 1
If IO.Path.GetFileName(files(i)).IndexOf(fragment, StringComparison.OrdinalIgnoreCase) > -1 Then
found = True
Exit For
End If
Next
Return found
End Function
Or you can do it in one line with LINQ, and if you are using .NET framework >=4 then you can use .EnumerateFiles instead of .GetFiles, which has a chance of being faster:
Function FilenameFragmentExists(srcDir As String, fragment As String) As Boolean
Return IO.Directory.EnumerateFiles(srcDir).Any(Function(f) IO.Path.GetFileName(f).IndexOf(fragment, StringComparison.OrdinalIgnoreCase) >= 0)
End Function
You should use Directory.GetFiles(path, pattern) to check if it returns some files corresponding to your pattern. For example
Dim files = Directory.GetFiles("C:\temp", "*.jpg")
if files.Length > 0 Then
Console.WriteLine("Directory contains " + files.Length + " with the required pattern")
Else
Console.WriteLine("Directory doesn't contain any file with the required pattern")
End if
In the second parameter you could pass any kind of pattern following the usual wildcard rules used for directory listing