Getting a Specific Image Property Using WIA in VBA

In a continuation of exploring working with image Exif metadata via VBA, specifically working this time with WIA, I thought I’d demonstrate how you can retrieve a single property value.

Reading A Specific Exif Property with WIA

Obviously, there are a couple of ways we could do this:

  • Get the complete list of properties and their values and pull out the one we’re after
  • Check if the property exists, and if it does pull just that one

Today, I’ve chosen to concentrate on the latter as it is more efficient IMHO.

The code is very simple:

'---------------------------------------------------------------------------------------
' Procedure : WIA_GetExifProperty
' Author    : Daniel Pineault, CARDA Consultants Inc.
' Website   : http://www.cardaconsultants.com
' Purpose   : Retrieve a specific Exif metadata property value for the specified image
' Copyright : The following is release as Attribution-ShareAlike 4.0 International
'             (CC BY-SA 4.0) - https://creativecommons.org/licenses/by-sa/4.0/
' Req'd Refs: Late Binding  -> None required
'             Early Binding -> Microsoft Windows Image Acquisition Library vX.X
'
' Input Variables:
' ~~~~~~~~~~~~~~~~
' sImage    : Fully qualified path and filename of the image file to retrieve the Exif
'               metadata of.
' sProperty : The property to retrieve the value of.  Be careful this is case sensitive!
'               EquipMake works, equipmake will not!
'
' Usage:
' ~~~~~~
' WIA_GetExifProperty("C:\Temp\Img01.jpg", "EquipModel")
'   Returns -> ELE-L04
' WIA_GetExifProperty("C:\Temp\Img01.jpg", "DateTime")
'   Returns -> 2021:05:08 17:01:56
' WIA_GetExifProperty("C:\Temp\Img01.jpg", "ExifVer")
'   Returns -> 0210
'
' Revision History:
' Rev       Date(yyyy-mm-dd)        Description
' **************************************************************************************
' 1         2022-02-10              Initial Public Release
'---------------------------------------------------------------------------------------
Function WIA_GetExifProperty(sImage As String, sProperty As String)
    On Error GoTo Error_Handler
    #Const WIA_EarlyBind = False    'True => Early Binding / False => Late Binding
    #If WIA_EarlyBind = True Then
        Dim oIF               As WIA.ImageFile
        Dim oV                As WIA.Vector

        Set oIF = New WIA.ImageFile
    #Else
        Dim oIF               As Object
        Dim oV                As Object
        Const RationalImagePropertyType = 1006    '(&H3EE)

        Set oIF = CreateObject("WIA.ImageFile")
    #End If
    Dim sValue                As String
    Dim j                     As Long

    oIF.LoadFile sImage
    If oIF.Properties.Exists(sProperty) Then
        '        WIA_GetExifProperty = oIF.Properties(sProperty).Value
        With oIF.Properties(sProperty)
            If .IsVector = False Then
                If .Type = RationalImagePropertyType Then
'                    Debug.Print .PropertyID, .Name, GetWiaImagePropertyType(.Type), .Value.Numerator & "/" & .Value.Denominator
                    WIA_GetExifProperty = .Value.Numerator & "/" & .Value.Denominator
                Else
'                    Debug.Print .PropertyID, .Name, GetWiaImagePropertyType(.Type), .Value
                    WIA_GetExifProperty = .Value
                End If
            Else
                'Vector objects
                Set oV = .Value
                For j = 1 To oV.Count
                    sValue = sValue & Chr(oV.Item(j)) '& ""
                Next j
                sValue = Trim(sValue)
'                Debug.Print .PropertyID, .Name, GetWiaImagePropertyType(.Type), sValue
                WIA_GetExifProperty = sValue
            End If
        End With
    End If

Error_Handler_Exit:
    On Error Resume Next
    If Not oIF Is Nothing Then Set oIF = Nothing
    Exit Function

Error_Handler:
    If Err.Number = -2147024894 Then
        MsgBox "The specified file '" & sImage & "' does not appear to exist.", _
               vbCritical Or vbOKOnly, "Operation Aborted"
    Else
        MsgBox "The following error has occured" & vbCrLf & vbCrLf & _
               "Error Number: " & Err.Number & vbCrLf & _
               "Error Source: WIA_GetExifProperty" & vbCrLf & _
               "Error Description: " & Err.Description & _
               Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
               , vbOKOnly + vbCritical, "An Error has Occured!"
    End If
    Resume Error_Handler_Exit
End Function

I’ve left a few Debug.Print statements that I used while exploring all of this, that I thought might interest some of you out there. If you do use them, then you’ll also need the following helper function:

'Converts numeric Image Property Type values into English terms
Private Function GetWiaImagePropertyType(ByVal lType As Long) As String
    Select Case lType
        Case 1000
            GetWiaImagePropertyType = "Undefined"
        Case 1001
            GetWiaImagePropertyType = "Byte"
        Case 1002
            GetWiaImagePropertyType = "String"
        Case 1003
            GetWiaImagePropertyType = "Unsigned Integer"
        Case 1004
            GetWiaImagePropertyType = "Long"
        Case 1005
            GetWiaImagePropertyType = "Unsigned Long"
        Case 1006
            GetWiaImagePropertyType = "Rational"
        Case 1007
            GetWiaImagePropertyType = "Unsigned Rational"
        Case 1100
            GetWiaImagePropertyType = "Vector Of Undefined"
        Case 1101
            GetWiaImagePropertyType = "Vector Of Bytes"
        Case 1102
            GetWiaImagePropertyType = "Vector Of Unsigned"
        Case 1103
            GetWiaImagePropertyType = "Vector Of Longs"
        Case 1104
            GetWiaImagePropertyType = "Vector Of UnsignedLongs"
        Case 1105
            GetWiaImagePropertyType = "Vector Of Rationals"
        Case 1106
            GetWiaImagePropertyType = "Vector Of Unsigned Rationals"
        Case Else
            GetWiaImagePropertyType = "Unknown Type"
    End Select
End Function

Examples Of Its Usage

Now, with a single line of code you can retrieve a property’s value.

? WIA_GetExifProperty("C:\Temp\Img01.jpg", "EquipModel")
? WIA_GetExifProperty("C:\Temp\Img01.jpg", "EquipMake")
? WIA_GetExifProperty("C:\Temp\Img01.jpg", "ExifVer")
? WIA_GetExifProperty("C:\Temp\Img01.jpg", "DateTime")
? WIA_GetExifProperty("C:\Temp\Img01.jpg", "XResolution")
? WIA_GetExifProperty("C:\Temp\Img01.jpg", "ExifISOSpeed")

Code Features

This code

  • can be used as both Early or Late Binding, the choice is yours and set by changing the value of the WIA_EarlyBind constant.
  • is architecture/bitness independent (works in both 32 and 64-bit installations)
  • is application independent (should work in any VBA applications – Access, Excel, Outlook, PowerPoint, Word, …)

A Few Resources on the Subject

One response on “Getting a Specific Image Property Using WIA in VBA

  1. Rusty Barker

    This code is great. I tried to use it to extract GPS lat and long but I am having some issues. I was using “GpsLatitude” and “GpsLongitude” as the sProperty field but it wasn’t returning what I was expecting. If you have any tips it would be greatly appreciated. Thanks!