Скажите VBA использовать самый последний файл в соответствии с шаблоном имени файла - PullRequest
0 голосов
/ 28 августа 2018

У меня есть папка с множеством файлов Excel, сохраненных в следующем формате:

  • 2018.01 final.xlsx
  • 2018.02 final.xlsx
  • 2018.03 final xlsx.
  • и т.д ...

Я хотел бы выполнить VLOOKUP для самого последнего файла в соответствии с шаблоном имени файла. Сегодня это будет 2018.08 final xlsx.

  • Если августовский файл еще не сохранен, я хотел бы использовать предыдущий месяц, т. Е. Июль (2018.07 final.xlsx).

У меня есть следующий код, чтобы открыть последний файл, но теперь я хотел бы адаптировать его для использования самого нового файла в соответствии с шаблоном, не открывая его.

Есть идеи, как мне это сделать в VBA? Спасибо за вашу помощь, ребята

  fromPath = Sheets("Open latest file").Range("B5")
  fromPath2 = Sheets("Open latest file").Range("B6")

  If Dir(fromPath) = "" Then

    Workbooks.Open (fromPath2)

  Else

    Workbooks.Open (fromPath)

  End If

End Sub

Ответы [ 4 ]

0 голосов
/ 28 августа 2018

Вы можете попробовать использовать регулярные выражения для сопоставления с образцом файлов в данной папке. Выполните небольшую манипуляцию со строками, чтобы сохранить только часть даты в строках, затем используйте sortedList для упорядочивания соответствующих имен файлов. Затем выберите последний элемент из упорядоченного списка как последнее имя файла.

Option Explicit
Public Sub GetLastestFile()
    Const PATH As String = "C:\Users\User\Desktop\Testing"
    Dim fso As Object, oFolder As Object, oFile As Object, list As Object, tempString As String
    Set list = CreateObject("System.Collections.SortedList")
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set oFolder = fso.GetFolder(PATH)

    For Each oFile In oFolder.Files
        If IsFound(oFile.Name) Then
            tempString = Replace$(Left$(oFile.Name, 7), ".", vbNullString)
            With list
                If Not .contains(tempString) Then
                    .Add tempString, vbNullString
                End If
            End With
        End If
    Next
     Debug.Print list.Getkey(list.Count - 1)
End Sub
Public Function IsFound(ByVal inputString As String) As Boolean
    Dim re As Object
    Set re = CreateObject("VBScript.RegExp")
    With re
        .Global = True
        .MultiLine = True
        .IgnoreCase = False
        .Pattern = "\d{4}.\d{2}\sfinal.xlsx"
        IsFound = .test(inputString) 
    End With
End Function

Вы можете попробовать регулярное выражение здесь .

Regex

Regex объяснение:

\ д {4}. \ Д {2} \ sfinal.xlsx

\ d {4} соответствует цифре (равно [0-9]) {4} Квантификатор - соответствует ровно 4 раза

. соответствует любому символу (кроме ограничителей строки)

\ d {2} соответствует цифре (равно [0-9]) {2} Квантификатор - соответствует ровно 2 раза

\ s соответствует любому пробелу (равен [\ r \ n \ t \ f \ v])

final соответствует буквам символов final (с учетом регистра) , соответствует любому символу (кроме ограничителей строки) xlsx соответствует символам xlsx буквально (с учетом регистра)


Использование класса

Еще лучше было бы реализовать класс для регулярного выражения, имеющий метод IsFound. Это позволит избежать постоянного создания и уничтожения объекта регулярных выражений. Вместо этого он будет создан с использованием экземпляра класса, а затем только методом, вызываемым как требуется.

Если вы создаете класс с именем RegexFileMatch, введите следующий код:

Option Explicit
Private re As Object
Private Sub Class_Initialize()
    Set re = CreateObject("VBScript.RegExp")
End Sub

Public Function IsFound(ByVal inputString As String) As Boolean
    With re
        .Global = True
        .MultiLine = True
        .IgnoreCase = False
        .Pattern = "\d{4}.\d{2}\sfinal.xlsx"
        IsFound = .test(inputString)
    End With
End Function

Затем измените код вызова в стандартном модуле на:

Option Explicit
Public Sub GetLastestFile()
    Const PATH As String = "C:\Users\User\Desktop\Testing"
    Dim fso As Object, oFolder As Object, oFile As Object, list As Object, tempString As String
    Set list = CreateObject("System.Collections.SortedList")
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set oFolder = fso.GetFolder(PATH)
    Dim regex As New regexFileMatch
    For Each oFile In oFolder.Files
        If regex.IsFound(oFile.Name) Then
            tempString = Replace$(Left$(oFile.Name, 7), ".", vbNullString)
            With list
                If Not .contains(tempString) Then
                    .Add tempString, vbNullString
                End If
            End With
        End If
    Next
     Debug.Print list.Getkey(list.Count - 1)
End Sub

Это становится дешевле.

0 голосов
/ 28 августа 2018

Мне действительно нравится ответ, который дал вам Marcucciboy2, но если вы не можете поверить, что последний созданный файл на самом деле является тем файлом, который вам нужен, вы могли бы использовать (адаптировать вне) что-то вроде следующего:

Sub GetFile()

Dim YR As Long, MNTH As Long
Dim FPath As String, SearchFile As String

FPath = "U:\Test\"

For YR = Year(Now()) To 1 Step -1
    For MNTH = 12 To 1 Step -1
        If MNTH < 10 Then
            SearchFile = FPath & YR & ".0" & MNTH & " final.xlsx"
        Else
            SearchFile = FPath & YR & "." & MNTH & " final.xlsx"
        End If
        If Dir(SearchFile) <> "" Then
            Workbooks.Open (SearchFile)
            Exit Sub
        End If
    Next MNTH
Next YR

End Sub

Приветствуется дополнительная опция с этой опцией, так как не нужно будет перебирать все файлы, сохраняя некоторое время.

0 голосов
/ 28 августа 2018
Sub FileFinder() 

Dim strFile As String, strKey As String
Dim lngMax As Long, lngNumber As Long
Dim objDict As Object

Set objDictionary = CreateObject("scripting.dictionary")
intMax = 0
    strFile = Dir("C:\Users\Documents\test\*.xlsx")
    Do While Len(strFile) > 0

        intNumber = f_NumberExtractor(strFile)
        If lngMax < lngNumber Then
            lngMax = lngNumber
        End If

        If objDictionary.exists(lngNumber) = False Then
                objDictionary.Add lngNumber, strFile
         End If
        strFile = Dir
    Loop

    MsgBox objDictionary(lngMax)

End Sub

Public Function f_NumberExtractor(ByVal str As String) As Long
'Regular expression function to get rid of non-numeric signs
Dim objRegEx As Object
Dim lngResult As Long

Set objRegEx = CreateObject("VBScript.RegExp")
objRegEx.Pattern = "\D"
objRegEx.Global = True


lngResult = objRegEx.Replace(str, vbNullString) * 1
f_NumberExtractor = lngResult

End Function
0 голосов
/ 28 августа 2018

К счастью для вас, у меня уже есть функция, которую я люблю использовать, которая, по сути, делает то, что вы ищете:

Function GetMostRecentExcelFile(ByVal myDirectory As String, ByVal filePattern As String) As String

    Dim fso As Object
    Set fso = CreateObject("Scripting.FileSystemObject")

    Dim myFolder As Object
    Set myFolder = fso.getfolder(IIf(Right(myDirectory, 1) = "\", myDirectory, myDirectory & "\"))

    Dim currentDate As Date
    Dim fname As String

    Dim currentFile As Object
    For Each currentFile In myFolder.Files
        If (currentDate = CDate(0) Or currentFile.DateCreated > currentDate) And currentFile.name Like filePattern _
            And InStr(LCase$(currentFile.name), ".xlsx") > 0 And InStr(currentFile.name, "~$") = 0 Then

            currentDate = currentFile.DateCreated
            fname = currentFile.name

        End If
    Next currentFile

    GetMostRecentExcelFile = fname

End Function

Он будет циклически проходить по указанному myDirectory в поисках любых файлов, соответствующих заданному вами filePattern, и вернет файл с последним созданным файлом, который соответствует указанному шаблону.

Примечание: он не выбирает файл на основе имени файла, только на основе файла CreationDate !!


Вот как вы, скорее всего, использовали бы его для решения своей проблемы:

Sub Main()

    Dim pattern As String
    pattern = "*20##.## final*"

    Dim path As String
    path = sheets("Open latest file").Range("B5").Value2

    Dim filename As String
    filename = GetMostRecentExcelFile(path, pattern)

    If Len(filename) = 0 Or Len(Dir(filename)) = 0 Then
        path = sheets("Open latest file").Range("B6").Value2
        filename = GetMostRecentExcelFile(path, pattern)
    End If

    If Len(filename) > 0 Then
        Workbooks.Open (IIf(Right(path, 1) = "\", path, path & "\") & filename)
    Else
        MsgBox "No files found matching pattern"
    End If

End Sub
...