0

I have the code below to get file names from folders.

Sub GetFileNames_Assessed_As_T2()
    Dim sPath As String, sFile As String
    Dim iRow As Long, iCol As Long
    Dim ws As Worksheet: Set ws = Sheet9
    'declare and set the worksheet you are working with, amend as required
    
    sPath = "Z:\NAME\T2\"
    'specify directory to use - must end in ""
    
    sFile = Dir(sPath)
    Do While sFile <> ""
        LastRow = ws.Cells(ws.Rows.Count, "I").End(xlUp).Row 'get last row on Column I
        Filename = Left(sFile, InStrRev(sFile, ".") - 1) 'remove extension from file
        Set FoundFile = ws.Range("I1:I" & LastRow).Find(what:=Filename, lookat:=xlWhole) 'search for existing filename
        If FoundFile Is Nothing Then ws.Cells(LastRow + 1, "I") = Filename 'if not found then add it
        sFile = Dir  ' Get next filename
    Loop
End Sub

I need an adjustment to fetch the following and populate it on the spreadsheet:

  • File last updated by (Column O)
  • File last updated date (Column P)
  • Hyperlink the file to the spreadsheet (Column Q)
Community
  • 1
  • 1
DMO
  • 49
  • 5
  • 2
    Possible duplicate of [Using VBA to get extended file attributes](https://stackoverflow.com/questions/5651890/using-vba-to-get-extended-file-attributes) – eirikdaude Sep 12 '18 at 12:10
  • @nicomp I don't believe there is anyway one could record a macro that would populate a cell with a file's last modified date and created by values. – JNevill Sep 12 '18 at 13:13
  • @JNevill You're right. I would have bet we could find that. But I did find this VBA after 30 seconds of searching online: Public Function ModDate() ModDate = Format(FileDateTime(ThisWorkbook.FullName), "m/d/yy h:n ampm") End Function – nicomp Sep 12 '18 at 13:38
  • Thanks all for your comments.@nicomp my VBA is not amazing so could you please share how and where i would add this into the code so it populates in the correct location? – DMO Sep 12 '18 at 14:30

2 Answers2

1

Here is an example accessing the extended document properties via Dsofile.dll. 32 bit version is here. I am using re-written 64 bit alternative by robert8w8. After installation, of 64 bit version in my case, you go Tools >References >Add a reference to DSO OLE Document Properties Reader 2.1. It enables to access extended properties of closed files. Obviously, if the info is not available, it cannot be returned.

I have an optional filemask test in there which can be removed.

The DSO function is my re-write of a great sub that lists many more properties by xld here.

Option Explicit
Public Sub GetLastestDateFile()
    Dim FileSys As Object, objFile As Object, myFolder As Object
    Const myDir As String = "C:\Users\User\Desktop\TestFolder" '< Pass in your folder path
    Set FileSys = CreateObject("Scripting.FileSystemObject")
    Set myFolder = FileSys.GetFolder(myDir)

    Dim fileName As String, lastRow As Long, arr(), counter As Long

    With ThisWorkbook.Worksheets("Sheet1") '<== Change to your sheet where writing info to 
        lastRow = .Cells(.Rows.Count, "P").End(xlUp).Row 'find the last row with data in P

        For Each objFile In myFolder.Files 'loop files in folder
            fileName = objFile.Path
            If FileSys.GetExtensionName(fileName) = "xlsx" Then 'check if .xlsx
                arr = GetExtendedProperties(fileName)
                 counter = counter + 1
                .Cells(lastRow + counter, "O") = arr(0) 'Last updated
                .Cells(lastRow + counter, "P") = arr(1) 'Last save date
                .Hyperlinks.Add Anchor:=.Cells(lastRow + counter, "Q"), Address:=objFile.Path '<== Add hyperlink                 
            End If
        Next objFile
    End With
End Sub

Public Function GetExtendedProperties(ByVal FileName As String) As Variant
    Dim fOpenReadOnly As Boolean, DSO As DSOFile.OleDocumentProperties
    Dim oSummProps As DSOFile.SummaryProperties, oCustProp As DSOFile.CustomProperty
    Dim outputArr(0 To 1)
    Set DSO = New DSOFile.OleDocumentProperties
    DSO.Open FileName, fOpenReadOnly, dsoOptionOpenReadOnlyIfNoWriteAccess

    Set oSummProps = DSO.SummaryProperties

    outputArr(0) = oSummProps.LastSavedBy
    outputArr(1) = oSummProps.DateLastSaved
    GetExtendedProperties = outputArr
End Function

Other:

  1. Hyperlinks.Add method
QHarr
  • 83,427
  • 12
  • 54
  • 101
  • just so i understand this correctly, download the Active X programme to get additional file information, then update and run the code above? if this is the case to help with updating could i ask you to add comments in your code to allow me to edit? – DMO Sep 12 '18 at 15:04
  • thanks, i have downloaded this but i am a little confused as to how i would add this into my current code, could you help with this? – DMO Sep 13 '18 at 06:05
  • i updated the information and on line 10 i get "Subscript out of range" my information populates in column I so i updated to I – DMO Sep 13 '18 at 13:25
  • my apologies i have realised my mistake, new error i get "User-defined type not defined" on this line in the second part of the script: Dim fOpenReadOnly As Boolean, DSO As DSOFile.OleDocumentProperties – DMO Sep 13 '18 at 13:30
  • i cannot thank you enough!! it works beautifully! i ran my code first, then ran yours (after a bit of back and forth) but its works! one more thing? if i wanted to add multiple document types on this line: If FileSys.GetExtensionName(FileName) = "docx" Then 'check if .docx do i just add them in like "docx, PDF" etc. of does this have to be done differently? – DMO Sep 13 '18 at 14:09
  • thanks - i tried the OR function this didn't work could you please provide more details around the array i'm not sure i understand: array of extensions and use Match into that array and test with If Not IsError(Match(FileSys.GetExtensionName(FileName) , array,0)) – DMO Sep 13 '18 at 16:23
  • thank you, works perfectly - can the code be adjust so if the value has already been put on the spreadsheet is skips it and only adds the missing ones, currently its copying again. is that possible? – DMO Sep 14 '18 at 05:59
  • so i have added this in and i get an error "Next without For" the lines i have is: If Not IsError(Application.Match(FileSys.GetExtensionName(FileName), Array("docx", "pdf"), 0)) Then 'check if .docx If Not IsError(Application.Match(FileSys.GetExtensionName(FileName), "O:Q", 0)) Then arr = GetExtendedProperties(FileName) sorry for all the questions my VBA is not amazing but learning so much! – DMO Sep 14 '18 at 06:49
  • attached - i also tried adding in reading of PDF files by adding oSummProps.Owner but it didnt work for some reason! https://pastebin.com/AVCNAZ0V – DMO Sep 14 '18 at 06:53
  • I am not sure you can use with pdf. You didn't close your second If with an End If before the Next ObjFile. i.e. End If End If Next objFile – QHarr Sep 14 '18 at 06:53
  • No I don't though I can have a quick look and see what is written. This is getting close to what would be better managed via command line. – QHarr Sep 14 '18 at 06:59
  • Ok... so it seems it works only for files and specifically deals with Microsoft products i.e. not pdf! See here: https://support.microsoft.com/en-gb/help/224351/the-dsofile-dll-files-lets-you-edit-office-document-properties-when-yo – QHarr Sep 14 '18 at 07:01
0

In my case I could not use the DSO library from dsofile.dll (one needs to be admin to install it and register it...), so I came up with another solution to get some OLE properties of Office documents without opening them. It appears that (some of?) these Extended Properties are also accessible via the Shell:

Function GetDateLastSaved_Shell32(strFileFullPath$)

    strFolderPath$ = Left(strFileFullPath, Len(strFileFullPath) - Len(Dir(strFileFullPath)))
    strFileName$ = Dir(strFileFullPath)

    'using late binding here
    'to use early binding with Dim statements you need to reference the Microsoft Shell Controls And Automation library, usually available here:
    'C:\Windows\SysWOW64\shell32.dll
    'Example: 
    'Dim shlShell As Shell32.Shell 

    Set shlShell = CreateObject("Shell.Application") 'Variant/Object/IShellDispatch6
    'Set shlFolder = shlShell.Namespace(strFolderPath)                              'does not work when using late binding, weird...*
    Set shlFolder = shlShell.Namespace(CStr(strFolderPath))                         'works...
    'Set shlFolder = shlShell.Namespace(strFolderPath & "")                         'works...
    'Set shlFolder = shlShell.Namespace(Left$(strFolderPath, Len(strFolderPath)))   'works...

    '*also mentioned here without an explanation...
    'https://stackoverflow.com/questions/35957930/word-vba-shell-object-late-binding
   
    Set shlShellFolderItem = shlFolder.ParseName(strFileName)
    
    'all of the following returns the same thing (you have the returned Data Type indicated on the right)
    'but the first one is said by MSDN to be the more efficient way to get an extended property
    GetDateLastSaved_Shell32 = shlShellFolderItem.ExtendedProperty("{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 13")  'Date
    'GetDateLastSaved_Shell32 = shlShellFolderItem.ExtendedProperty("System.Document.DateSaved")                 'Date
    'GetDateLastSaved_Shell32 = shlShellFolderItem.ExtendedProperty("DocLastSavedTm")                            'Date      'legacy name   
    'GetDateLastSaved_Shell32 = shlFolder.GetDetailsOf(shlShellFolderItem, 154)                                  '?String?

End Function

To list all extended properties (Core, Documents, etc.), you can use this:

For i = 0 To 400
    vPropName = shlFolder.GetDetailsOf(Null, i)
    vprop = shlFolder.GetDetailsOf(shlShellFolderItem, i)
    Debug.Print i, vPropName, vprop
    If i Mod 10 = 0 Then Stop
Next

You can find more info about the "efficient way" on MSDN: ShellFolderItem.ExtendedProperty method

You can also find the list of FMTIDs and PIDSIs in propkey.h from Windows SDK or somewhere in C:\Program Files (x86)\Windows Kits\10\Include\***VERSION***\um\ if you have Visual Studio installed.

hymced
  • 570
  • 5
  • 19