Option Explicit
'Code from this module is Common to Windows Media Player in the Spreadsheet and on UserForms
'Reference: https://danny.fyi/embedding-and-accessing-a-file-in-excel-with-vba-and-ole-objects-4d4e7863cfff
'Thank you Danial Chowdhury
#If VBA7 And Win64 Then
' 64 bit Excel
'The following line is supposed to be RED in 32 bit Excel
Public Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#Else
' 32 bit Excel
Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#End If
#If VBA7 Then
'64 Bit Excel
Private Declare PtrSafe Function CloseClipboard& Lib "user32" ()
Private Declare PtrSafe Function OpenClipboard& Lib "user32" (ByVal hWnd&)
Private Declare PtrSafe Function EmptyClipboard& Lib "user32" ()
Private Declare PtrSafe Function GetClipboardData& Lib "user32" (ByVal wFormat&)
Private Declare PtrSafe Function GlobalSize& Lib "kernel32" (ByVal hMem&)
Private Declare PtrSafe Function GlobalLock& Lib "kernel32" (ByVal hMem&)
Private Declare PtrSafe Function GlobalUnlock& Lib "kernel32" (ByVal hMem&)
Private Declare PtrSafe Sub CopyMem Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length&)
#Else
'32 Bit Excel
Private Declare Function CloseClipboard& Lib "user32" ()
Private Declare Function OpenClipboard& Lib "user32" (ByVal hWnd&)
Private Declare Function EmptyClipboard& Lib "user32" ()
Private Declare Function GetClipboardData& Lib "user32" (ByVal wFormat&)
Private Declare Function GlobalSize& Lib "kernel32" (ByVal hMem&)
Private Declare Function GlobalLock& Lib "kernel32" (ByVal hMem&)
Private Declare Function GlobalUnlock& Lib "kernel32" (ByVal hMem&)
Private Declare Sub CopyMem Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length&)
#End If
Public iGblOutputRow As Long
Public wsGblOutput As Worksheet
Sub AccessEmbeddedObjectPathsAndFileNamesDiagnostic()
Const sRoutineName = "AccessEmbeddedObjectPathsAndFileNamesDiagnostic()"
Dim wb As Workbook
Dim wsSheet1 As Worksheet
'Initialize the Output Row Number
iGblOutputRow = 0
'Create the Worksheet Objects
Set wb = ThisWorkbook
Set wsSheet1 = wb.Sheets("Sheet1")
Set wsGblOutput = wb.Sheets.Add(After:=Sheets(wb.Sheets.Count))
wsGblOutput.Name = Format(Now(), "yymmdd.hhmmss")
wsGblOutput.Cells.Font.Name = "Calibri"
wsGblOutput.Cells.Font.Size = 11
Call DiagnosticOutput(sRoutineName, "Start", "")
'Code being tested starts after this line
''''''''''''''''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''
Dim wks As Worksheet
Dim myOleObject As OLEObject
Dim i As Long
Dim iCount As Long
Dim sEmbeddedFileName As String
Dim sSheetName As String
For Each wks In ThisWorkbook.Worksheets
'Get the 'Sheet Name'
sSheetName = wks.Name
' Loop through all our OLE Objects to find the one we want.
For Each myOleObject In wks.OLEObjects
'Debug.Print "myOleObject.Name = " & myOleObject.Name
'Get the Embedded File Name (if any)
' We try to grab the embedded file name. We call this twice.
For i = 1 To 5
sEmbeddedFileName = GetOLETempPath(myOleObject)
If LCase(sEmbeddedFileName) Like "*.mp4*" Then
Exit For
End If
Next i
'If the Name is NOT BLANK - Display the File Path and File Name Combination
If Len(sEmbeddedFileName) > 0 Then
iCount = iCount + 1
Debug.Print iCount, sSheetName, sEmbeddedFileName
Dim sMessage As String
sMessage = iCount & " " & sSheetName & " " & sEmbeddedFileName
Call DiagnosticOutput(sRoutineName, "100", sMessage)
End If
'Only process the first Embedded file name
Exit For
Next myOleObject
Next wks
If iCount = 0 Then
Call DiagnosticOutput(sRoutineName, "", "There were NO Embedded Objects 'ActiveX' Objects found.")
End If
''''''''''''''''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''
'Code being tested ends before this line
'Put the Focus on the Output Sheet
'AutoFit the Output Columns
wb.Activate
wsGblOutput.Select
wsGblOutput.Columns("A:B").AutoFit
Call DiagnosticOutput(sRoutineName, "End", "")
'Clear Object Pointers
Set wb = Nothing
Set wsSheet1 = Nothing
Set wsGblOutput = Nothing
End Sub
Private Function GetOLETempPath(obj As OLEObject) As String
'Reference: https://danny.fyi/embedding-and-accessing-a-file-in-excel-with-vba-and-ole-objects-4d4e7863cfff
'Thank you Danial Chowdhury
Const sRoutineName = "GetOLETempPath()"
Call DiagnosticOutput(sRoutineName, "Start", "")
Dim sMessage As String
Dim B() As Byte, Pos&, iEnd&, iStart&, iLength&
Dim Header As String
obj.Copy ' (49156 = Native format)
sMessage = "Before Exit Function"
Call DiagnosticOutput(sRoutineName, "050", sMessage)
If Not GetData(49156, B) Then Exit Function
sMessage = "After Exit Function"
Call DiagnosticOutput(sRoutineName, "060", sMessage)
Dim Buffer$
Buffer = StrConv(B, vbUnicode)
Header = Chr$(0) & Chr$(0) & Chr$(3) & Chr$(0)
Pos = InStr(Buffer, Header)
' To do: probably check if we reached EOF
If Pos Then
iStart = Pos + 8
iEnd = InStr(iStart + 1, Buffer, Chr$(0)) + 1 'Inc Null terminator
'iEnd = iStart + 10
iLength = iEnd - iStart
End If
GetOLETempPath = Mid(Buffer, iStart, iLength)
'Debug.Print (GetOLETempPath)
sMessage = "Len(GetOLETempPath) = '" & Len(GetOLETempPath) & "'"
Call DiagnosticOutput(sRoutineName, "100", sMessage)
sMessage = "Path = '" & GetOLETempPath & "'"
Call DiagnosticOutput(sRoutineName, "100", sMessage)
On Error Resume Next
If Len(Dir(GetOLETempPath)) = 0 Then
GetOLETempPath = ""
End If
If Err.Number <> 0 Then
Err.Clear
GetOLETempPath = ""
End If
On Error GoTo 0
''''''''''''''''''''''''''''''
'diagnostic starts here
''''''''''''''''''''''''''''''
Dim i As Long
Dim iPos As Long
Dim c As String
Dim cc As String
Dim iValue As Long
For i = 1 To iEnd + 10
c = Mid(Buffer, i, 1)
iValue = Asc(c)
If iValue >= 32 And iValue <= 126 Then
cc = c
Else
cc = "Not Printable"
End If
sMessage = "Buffer " & Format(i, "000 ") & iValue & " '" & cc & "'"
Call DiagnosticOutput(sRoutineName, "200", sMessage)
Next i
For i = 1 To iLength
c = Mid(GetOLETempPath, i, 1)
iValue = Asc(c)
If iValue >= 32 And iValue <= 126 Then
cc = c
Else
cc = "Not Printable"
End If
sMessage = "GetOLETempPath " & Format(i, "000 ") & iValue & " '" & cc & "'"
Call DiagnosticOutput(sRoutineName, "250", sMessage)
Next i
iPos = InStr(Buffer, ".mp4")
sMessage = "InStr(Buffer, "".mp4"") = " & iPos
Call DiagnosticOutput(sRoutineName, "300", sMessage)
iPos = InStr(Buffer, "embedded")
sMessage = "InStr(Buffer, ""embedded"") = " & iPos
Call DiagnosticOutput(sRoutineName, "310", sMessage)
iPos = InStr(Buffer, ".mp4")
sMessage = "Pos, iStart, iEnd, iLength = " & Pos & " " & iStart & " " & iEnd & " " & iLength
Call DiagnosticOutput(sRoutineName, "400", sMessage)
Call DiagnosticOutput(sRoutineName, "End", "")
End Function
Private Function GetData(ByVal Format&, abData() As Byte) As Boolean
'Reference: https://danny.fyi/embedding-and-accessing-a-file-in-excel-with-vba-and-ole-objects-4d4e7863cfff
'Thank you Danial Chowdhury
Const sRoutineName = "GetData()"
Call DiagnosticOutput(sRoutineName, "Start", "")
Dim hWnd&, Size&, Ptr&
If OpenClipboard(0&) Then
' Get memory handle to the data
hWnd = GetClipboardData(Format)
' Get size of this memory block
If hWnd Then Size = GlobalSize(hWnd)
' Get pointer to the locked memory
If Size Then Ptr = GlobalLock(hWnd)
If Ptr Then
' Resize the byte array to hold the data
ReDim abData(0 To Size - 1) As Byte
' Copy from the pointer into the array
CopyMem abData(0), ByVal Ptr, Size
' Unlock the memory
Call GlobalUnlock(hWnd)
GetData = True
End If
EmptyClipboard
CloseClipboard
DoEvents
Dim sMessage As String
sMessage = "hWnd, Size, Ptr = " & hWnd & " " & Size & " " & Ptr
Call DiagnosticOutput(sRoutineName, "100", sMessage)
End If
Call DiagnosticOutput(sRoutineName, "End", "")
End Function
Sub DiagnosticOutput(sRoutineName As String, sLocation As String, sText As String)
'Increment the Output Row Number
iGblOutputRow = iGblOutputRow + 1
wsGblOutput.Cells(iGblOutputRow, "A").Value = sRoutineName
wsGblOutput.Cells(iGblOutputRow, "B").Value = sLocation
wsGblOutput.Cells(iGblOutputRow, "C").Value = sText
End Sub
Lewis
Bookmarks