25

I need to get file name without extension name by VBA. I know ActiveWorkbook.Name property , but if user haves Windows property Hide extensions for known file types turn off, the result of my code will be [Name.Extension]. How can I return only name of Workbook independent of windows property?

I try even ActiveWorkbook.Application.Caption but I can't customize this property.

Community
  • 1
  • 1
Liniel
  • 669
  • 1
  • 6
  • 14

9 Answers9

71

The answers given here already may work in limited situations, but are certainly not the best way to go about it. Don't reinvent the wheel. The File System Object in the Microsoft Scripting Runtime library already has a method to do exactly this. It's called GetBaseName. It handles periods in the file name as is.

Public Sub Test()

    Dim fso As New Scripting.FileSystemObject
    Debug.Print fso.GetBaseName(ActiveWorkbook.Name)

End Sub

Public Sub Test2()

    Dim fso As New Scripting.FileSystemObject
    Debug.Print fso.GetBaseName("MyFile.something.txt")

End Sub

Instructions for adding a reference to the Scripting Library

Community
  • 1
  • 1
RubberDuck
  • 11,070
  • 4
  • 46
  • 94
  • 4
    Didn't know that was there! Nice answer. – bp_ Jan 13 '15 at 15:09
  • 6
    RbeerDuck, When I run this command, there is a compile error "User-defined type not defined" – Isu Oct 09 '15 at 05:33
  • @Isu you need to add a reference to the library. – RubberDuck Oct 09 '15 at 09:03
  • Can you explain that please? – Isu Oct 09 '15 at 22:48
  • and if "Hide extensions for known file types" is on, how will GetBasename know that "John.and.Mary.spreadsheet" is already the base name ? I think it will assume "spreadsheet" is the file extension and will return "John.and.Mary", so this doesn't address OP's problem. – ThreeStarProgrammer57 Apr 08 '16 at 14:08
  • 2
    @ThreeStarProgrammer57 I think you should try it before you suggest it doesn't work. – RubberDuck Apr 08 '16 at 16:44
  • 1
    It certainly doesn't work if you use the `Workbook.Name` property as the argument for these fso functions when "Hide extensions for known file types" is set. `Workbook.Fullname` should be used instead. – blackworx Aug 08 '16 at 09:57
  • 5
    Sorry - should've explained myself. It won't work if you have extensions hidden in explorer and the filename is something stupid like "Myworkbook.csv.xlsx" (far from uncommon). In this case the `.Name` property is "Myworkbook.csv" and `GetBaseName` returns "Myworkbook" which is incorrect. Furthermore: if you try to use the companion fso function `GetExtensionName` with `Workbook.Name` property when extensions are hidden you won't get an answer. Far better practice to just use the `Workbook.Fullname` property, which returns the same string regardless of Explorer's "hide extensions" setting. – blackworx Aug 08 '16 at 10:20
  • 7
    I prefer late binding - `Dim fso: Set fso = CreateObject("Scripting.FileSystemObject")` – ZygD Jun 19 '18 at 15:50
17

Simple but works well for me

FileName = ActiveWorkbook.Name 
If InStr(FileName, ".") > 0 Then 
   FileName = Left(FileName, InStr(FileName, ".") - 1) 
End If
Petter Friberg
  • 20,644
  • 9
  • 57
  • 104
Ifca
  • 171
  • 1
  • 2
2

Using the Split function seems more elegant than InStr and Left, in my opinion.

Private Sub CommandButton2_Click()


Dim ThisFileName As String
Dim BaseFileName As String

Dim FileNameArray() As String

ThisFileName = ThisWorkbook.Name
FileNameArray = Split(ThisFileName, ".")
BaseFileName = FileNameArray(0)

MsgBox "Base file name is " & BaseFileName

End Sub
1

This gets the file type as from the last character (so avoids the problem with dots in file names)

Function getFileType(fn As String) As String

''get last instance of "." (full stop) in a filename then returns the part of the filename starting at that dot to the end
Dim strIndex As Integer
Dim x As Integer
Dim myChar As String

strIndex = Len(fn)
For x = 1 To Len(fn)

    myChar = Mid(fn, strIndex, 1)

    If myChar = "." Then
        Exit For
    End If

    strIndex = strIndex - 1

Next x

getFileType = UCase(Mid(fn, strIndex, Len(fn) - x + 1))

End Function

0

To be verbose it the removal of extension is demonstrated for workbooks.. which now have a variety of extensions . . a new unsaved Book1 has no ext . works the same for files

Function WorkbookIsOpen(FWNa$, Optional AnyExt As Boolean = False) As Boolean

Dim wWB As Workbook, WBNa$, PD%
FWNa = Trim(FWNa)
If FWNa <> "" Then
    For Each wWB In Workbooks
        WBNa = wWB.Name
        If AnyExt Then
            PD = InStr(WBNa, ".")
            If PD > 0 Then WBNa = Left(WBNa, PD - 1)
            PD = InStr(FWNa, ".")
            If PD > 0 Then FWNa = Left(FWNa, PD - 1)
            '
            ' the alternative of using split..  see commented out  below
            ' looks neater but takes a bit longer then the pair of instr and left
            ' VBA does about 800,000  of these small splits/sec
            ' and about 20,000,000  Instr Lefts per sec
            ' of course if not checking for other extensions they do not matter
            ' and to any reasonable program
            ' THIS DISCUSSIONOF TIME TAKEN DOES NOT MATTER
            ' IN doing about doing 2000 of this routine per sec

            ' WBNa = Split(WBNa, ".")(0)
            'FWNa = Split(FWNa, ".")(0)
        End If

        If WBNa = FWNa Then
            WorkbookIsOpen = True
            Exit Function
        End If
    Next wWB
End If

End Function
Daniel L. VanDenBosch
  • 1,806
  • 3
  • 26
  • 51
Harry S
  • 431
  • 6
  • 5
0

You could always use Replace() since you're performing this on the workbook's Name, which will almost certainly end with .xlsm by virtue of using VBA.

Using ActiveWorkbook per your example:

Replace(Application.ActiveWorkbook.Name, ".xlsm", "")

Using ThisWorkbook:

Replace(Application.ThisWorkbook.Name, ".xlsm", "")

David Metcalfe
  • 1,993
  • 1
  • 25
  • 41
0

I use a macro from my personal.xlsb and run it on both xlsm and xlsx files so a variation on David Metcalfe's answer that I use is

Dim Wrkbook As String

Wrkbook = Replace(Application.ActiveWorkbook.Name, ".xlsx", ".pdf")

Wrkbook = Replace(Application.ActiveWorkbook.Name, ".xlsm", ".pdf")

Vulka
  • 21
  • 4
0

Here is a solution if you do not want to use FSO. There were some similar answers before, but here some checks are done to handle multiple dots in name and name without extension.

Function getFileNameWithoutExtension(FullFileName As String)

    Dim a() As String
    Dim ext_len As Integer, name_len As Integer


    If InStr(FullFileName, ".") = 0 Then
       getFileNameWithoutExtension = FullFileName
       Exit Function
    End If
    
    a = Split(ActiveWorkbook.Name, ".")
    ext_len = Len(a(UBound(a))) 'extension length (last element of array)
    name_len = Len(FullFileName) - ext_len - 1 'length of name without extension and a dot before it
    getFileNameWithoutExtension = Left(FullFileName, name_len)
    
End Function

Sub test1() 'testing the function
 MsgBox (getFileNameWithoutExtension("test.xls.xlsx")) ' -> test.xls
 MsgBox (getFileNameWithoutExtension("test")) ' -> test
 MsgBox (getFileNameWithoutExtension("test.xlsx")) ' -> test
End Sub
Leo
  • 410
  • 2
  • 16
-1
strTestString = Left(ThisWorkbook.Name, (InStrRev(ThisWorkbook.Name, ".", -1, vbTextCompare) - 1))

full credit: http://mariaevert.dk/vba/?p=162

bp_
  • 402
  • 4
  • 14
  • 2
    This doesn't work if there is no file extension but there is a dot in the name. – Johnny Bones Jan 13 '15 at 14:25
  • No? Can you tell me what error is occuring? I am missing it. – bp_ Jan 13 '15 at 14:29
  • 3
    Think it through. You're using an InStrRev to find the dot. Well, what if the file name is "John.And.Mary.Spreadsheet", because they have Hide Extensions option on? Now it thinks the file is "John.And.Mary" and the file extension is "Spreadsheet". – Johnny Bones Jan 13 '15 at 14:32
  • 1
    Not according to my system. Not sure if the version you are using changes things, but the .Name property returns the full name, regardless of the Hidden extensions. At least, that is what it is doing for me. – bp_ Jan 13 '15 at 14:44
  • 1
    Read the OP's question. He's saying he gets the extension only if that option is turned off. – Johnny Bones Jan 13 '15 at 14:48
  • 3
    Is it possible the OP is wrong, hence asking for help on SO? Or are all OPs infallible? – bp_ Jan 13 '15 at 14:56
  • the Hide known extensions extensions is just a setting in file explorer it doesn't have an effect in VBA. Having said that a file doesn't have to have any extension so that may be what is happening here – Matt Wilko Jan 13 '15 at 15:28
  • I saved my test file with no extension, then manually opened it in Excel and produced the same results. Wondering if Windows 'assigns' an extension when you manually select a program to open the file? – bp_ Jan 13 '15 at 21:06
  • 1
    Hiding the Extension doesn't mean that the file doesn't have one, it means it isn't being shown by the file explorer – Malachi Jan 22 '15 at 20:25