4

Using MS Access VBA how can I check a file to know whether it is in Excel format?

Erik A
  • 31,639
  • 12
  • 42
  • 67
Alex
  • 2,081
  • 14
  • 49
  • 76
  • 1
    Can you elaborate on what you are trying to do? Often it is sufficient to check if the file extension is .xls or .xlsx (and possibly some of the Excel extensions listed in the "Save As Type" portion of the Excel "save" dialog, depending on what you need it for). If doing that isn't feasible for your project, we'd need to know. – transistor1 Nov 19 '12 at 03:12
  • 1
    I have a folder with many files. Many, but not all, are in Excel format. But that can't be determined by the extension. I want to open them - using Workbook object - for various data checking in a program, but I need to know whether it is an Excel table. Also I would like to segregate the Excel and non Excel. – Alex Nov 19 '12 at 03:27
  • There are many file formats associated with Excel. [See here](http://msdn.microsoft.com/en-us/library/office/ff198017(v=office.15).aspx). What do you define as an Excel format? – cheezsteak Jun 05 '14 at 16:18

3 Answers3

2

I have never had an issue where an Excel file can't directly be determined by extension, but if I had to do that, the first thing that comes to mind is the UNIX utility file, which identifies a file type by looking at its' contents. It recognizes a very large number of file types.

I use Cygwin for Windows, which is essentially a UNIX environment on Windows.

When I use the file command in Cygwin on an Excel 2010 (xlsx) file I've renamed '.csv', I get:

$ file afile.csv
afile.csv: Microsoft Excel 2007+

It's a slightly awkward solution, but in your VBA you could fork a C:\cygwin\bin\file.exe process using Windows Script Host, and capture the output for each file.

If you code the path to the Excel file with single ticks around it (i.e. 'C:\path\to\file'), Cygwin should interpret it correctly (Cygwin utilities expect to see a unix-like path: /path/to/file). I just verified this in a normal Windows command prompt, and it worked:

c:\>c:\cygwin\bin\file.exe 'C:\path\to\afile.csv'
C:\path\to\afile.csv: Microsoft Excel 2007+

There is also a native Windows binary of file in the GnuWin32 SourceForge project, but it seems to be a little outdated; I haven't tried it, but it may still recognize modern Excel versions.

If you need a native Excel solution -- I'm not entirely sure off the top of my head; hopefully someone else has done this before.

Community
  • 1
  • 1
transistor1
  • 2,915
  • 26
  • 42
  • Thanks for you reply. It is interesting and certainly awkward. I am looking for something kind of straight forward that I can code from Access VBA. – Alex Nov 19 '12 at 04:42
  • 1
    As for never having an where an Excel file can't directly be determined from its extensions - well if someone saved it as such, wrongly. – Alex Nov 19 '12 at 04:44
  • I understand... without something that scans the contents of the file, I'm not sure how else it can be done automatically. For example, I just tried using `Workbooks.Open` to open a DLL file, and Excel still opens it, but displays garbage. I haven't seen anything built into Office that would do this, but you never know... you might get lucky & find someone that has! – transistor1 Nov 19 '12 at 04:50
  • 2
    Also, maybe take a look at the Excel files in a text editor like Notepad... if they all have a common string at the beginning of the file, you could use VBA to scan the first few bytes of each file, similar to how the `file` utility works. – transistor1 Nov 19 '12 at 05:01
  • 1
    Not really Notepad, you need a special text editor which can read in byte value. – Quannt Nov 19 '12 at 06:41
2

This isn't for Access but for Excel I use this. This is not the greatest nor anybodies preferred solution, but brace yourself.

Public Function IsExcelFormat(ByVal filePath As String) As Boolean

    On Error GoTo Nope
    Application.ScreenUpdating = False

    Dim wb As Workbook
    Set wb = Workbooks.Open(filePath )
    IsExcelFormat = (wb.FileFormat > 50)

CleanExit:
    Application.ScreenUpdating = True
Exit Function

Nope: ' Clearly not Excel format
    Err.clear
    IsExcelFormat = False
    Resume CleanExit:

End Function

Yeah it uses Excel's automagic. I know. It's hideous. And the ScreenUpdating doesn't work entirely. Your taskbar will update as you open an close the file. But still, it works.

You might need to create an instance Excel in your Access VBA script and optionally pass it to function something like this. Note I haven't tested this.

Public Function IsExcelFormat(ByVal file_path As String, _
        Optional byRef excel_instance as Excel.Application = Nothing) As Boolean
    On Error GoTo Nope

    Dim local_excel as boolean
    If excel_instance Is Nothing Then 
       Set excel_instance = New Excel.Application
       local_excel = True
    End If

    Dim wb As Excel.Workbook

    excel_instance.ScreenUpdating = False

    Set wb = excel_instance.Workbooks.Open(file_path)
    IsExcelFormat = (wb.FileFormat > 50)
    wb.Close savechanges:=False

CleanExit:
    If local_excel Then 
        excel_instance.Quit
    Else
        excel_instance.ScreenUpdating = True    
    End If
Exit Function
Nope: ' Clearly not Excel format
    Err.clear
    IsExcelFormat = False
    Resume CleanExit:
End Function
cheezsteak
  • 2,731
  • 4
  • 26
  • 41
  • No reason to set screen updating to false. Just don't make the instance of excel visible. (which you don't, but for OPs benefit...) – RubberDuck Oct 15 '14 at 20:08
1

Some notes on a possible approach using ADOX

Sub SortFiles()
''Library reference: Windows Script Host Object Model
Dim fs As New FileSystemObject
Dim ts As TextStream
Dim sType As String
Dim sFile As File

For Each sFile In fs.GetFolder("Z:\Docs\").Files
    sType = sFile.Type

    If InStr(sType, "Microsoft") = 0 Then
        sList = ListTables(sFile.Name)
        If sList = "Error: Not Excel" Then
            ''Move to suitable folder
        Else
            Debug.Print sList
            Stop
            ''This can be read as Excel, most likely
        End If

    ElseIf sType Like "*Excel*" Then
       ''Includes CSV
        sFile.Move "z:\docs\Excelfiles\"
    Else
        sFile.Move "z:\docs\OtherMS\"
    End If
Next

End Sub

Function ListTables(sFile As String) As String
''Library reference: Microsoft ADO Ext. x.x for DDL and Security
Dim cat As New ADOX.Catalog
Dim scn As String
Dim t As ADOX.Table
Dim cn As New ADODB.Connection
Dim sList As String

On Error GoTo Handle_Err:

    scn = "Provider=Microsoft.ACE.OLEDB.12.0;" _
    & "Data Source=" & sFile & ";Extended Properties=""Excel 8.0;HDR=No"""

    cn.Open scn

    cat.ActiveConnection = cn

    For Each t In cat.Tables
        sList = sList & vbCrLf & t.Name
    Next t

    ListTables = sList

Exit_Proc:
Set cn = Nothing
Set cat = Nothing
Exit Function

Handle_Err:
    If Err.Number = -2147467259 Then
        ''External table is not in the expected format.
        ListTables = "Error: Not Excel"
        Err.Clear
        Resume Exit_Proc
    Else
        Debug.Print Err.Number, Err.Description
    End If

End Function
Fionnuala
  • 90,370
  • 7
  • 114
  • 152
  • are you suggesting that if I renamed an Excel file to .txt that it would be flagged as Excel nevertheless ? – Alex Nov 19 '12 at 17:50
  • I tested with a file called test.tst and it passed the ADOX test returning various sheet names for table names. – Fionnuala Nov 19 '12 at 17:52
  • I tried this by running it on a folder with only XLS files and it reported correctly. However when I renamed one of these Excel files to .txt it returns "Error: Not Excel". – Alex Nov 20 '12 at 03:09
  • This is not what happens on my PC, an Excel file called *.txt works. Excel files with the correct extension would never get as far as the ADOX test, so that does not count. It seems that the connection string is not right for your Excel version. Can you test the ADOX function with an Excel file with the correct extension to see if this is the case? If so, can you post notes on your set-up (Excel version etc)? I tested with quite a range of Excel types, but as you can see, using the latest ACE 12 drivers. – Fionnuala Nov 20 '12 at 10:34
  • I want to be able to know whether files are of Excel type no matter whether there is excel on the computer or not. And Excel can be any vesion, not a limited to a specific version. When I ran this code my Excel contained "Microsoft Office Excel 97-2003 Worksheet" not "Microsoft Excel" so I had to change in the code of course. – Alex Nov 26 '12 at 04:02