VBA: список путей к папкам, возврат списка путей к файлам Excel, затем редактирование. - PullRequest
0 голосов
/ 04 июня 2018

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

Iзнаю, что это не элегантно, потому что в конечном итоге я хочу, чтобы мой список путей просматривался по одному, через каждую папку и подпапку, чтобы найти и перечислить файлы Excel.Но был вопрос как этот, и он был снят.Затем вопрос был передан к другому вопросу & 1006 *, который я не понимал, который имел отношение к отдельным ИМЕНАМ ФАЙЛА, напечатанным в одной ячейке, а не в диапазоне или в качестве пути.Я говорю по-русски, в котором был какой-то его код, и до сих пор не мог понять, что его код имел в виду и имел в виду, и когда я попробовал его, он продолжал говорить, что GetData не определен?поэтому я попытался задать другой, но похожий вопрос в надежде, что кто-то сможет объяснить мне, что мне нужно сделать, поскольку я сделал все возможное и попытался адаптировать оба кода по ссылкам в этом посте.а также многие другие.У меня есть несколько модулей со сломанным кодом, который не работает, и самый близкий, который я пришел, является кодом ниже.На этом этапе я бы просто выбрал способ перечисления имен файлов Excel из списка путей.

Option Explicit
Dim i As Long, j As Long
Dim searchfolders As Variant
Dim FileSystemObject

Sub ListOfFolders77()
Dim LookInTheFolder As String
'Dim ws As Worksheet: Set ws = Sheets("Output4")
Dim ws2 As Worksheet: Set ws2 = Sheets("Output3")
Dim rng As Range: Set rng = ws2.Range("A1:A" & Rows.Count).End(xlUp)
Dim mypath As Range
'Dim Region As Range: Set Region = ws.Range("A2")
'Dim district As Range: Set district = ws.Range("B2")
'Dim city As Range: Set city = ws.Range("C2")
'Dim atlas As Range: Set atlas = ws.Range("D2")

i = 1
For Each mypath In rng
    LookInTheFolder = mypath.Value
    Set FileSystemObject = CreateObject("Scripting.FileSystemObject")
    For Each searchfolders In FileSystemObject.GetFolder(LookInTheFolder).subfolders
        Sheets("Subfolders").Cells(i, 1) = searchfolders
        i = i + 1
        SearchWithin searchfolders
    Next searchfolders
Next mypath

End Sub

Sub SearchWithin(searchfolders)
On Error GoTo exits
For Each searchfolders In FileSystemObject.GetFolder(searchfolders).subfolders
j = UBound(Split(searchfolders, "\"))
Cells(i, j) = searchfolders
i = i + 1
SearchWithin searchfolders
Next searchfolders
exits:
End Sub

В идеале я хочу получить все файлы Excel в папках и подпапках и скопировать и вставитьданные на первом листе объединены в один длинный список, но я все еще на шаге 1. На прошлой неделе я разместил более подробное объяснение здесь и пока не получил никаких отзывов или потенциальных советов.

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

Ответы [ 2 ]

0 голосов
/ 06 июня 2018

Если я правильно понимаю, ваши требования следующие:

  • Начните с набора корневых путей
  • Итерируйте рекурсивно по всем файлам в каждом корневом пути
  • Для каждого файла в результирующей коллекции, если это файл Excel, добавьте в окончательный список для дальнейшей обработки

Давайте начнем с первых двух пунктов.Я хотел бы предложить следующий код (обязательно добавьте ссылку на Microsoft Scripting Runtime через Инструменты -> Ссылки ... в меню редактора VBA):

Public Function GetFiles(ByVal roots As Variant) As Collection
    Select Case TypeName(roots)
        Case "String", "Folder"
            roots = Array(roots)
    End Select

    Dim results As New Collection
    Dim fso As New Scripting.FileSystemObject

    Dim root As Variant
    For Each root In roots
        AddFilesFromFolder fso.GetFolder(root), results
    Next

    Set GetFiles = results
End Function

Private Sub AddFilesFromFolder(folder As Scripting.folder, results As Collection)
    Dim file As Scripting.file
    For Each file In folder.Files
        results.Add file
    Next

    Dim subfolder As Scripting.folder
    For Each subfolder In folder.SubFolders
        AddFilesFromFolder subfolder, results
    Next
End Sub

Функцию GetFiles можно вызвать, передав одну строку (или Folder):

Debug.Print GetFiles("c:\users\win8\documents").Count

или все, что можно повторить с помощью For Each- массив, коллекция, Dictionary или даже объект Excel Range:

Dim allFiles As Collection
Set allFiles = GetFiles(ws2.Range("A1:A" & Rows.Count).End(xlUp)) 'from question

GetFiles в том виде, как он есть, является гибким для многих случаев использования и не используетлюбые специфичные для Excel объекты.Чтобы ограничить результаты только файлами Excel, вы можете создать новую коллекцию и добавить только файлы Excel в новую коллекцию:

'You could filter by the File object's Type property
Sub GetExcelFilesByType()
    Dim allFiles As Collection
    Set allFiles = GetFiles(ws2.Range("A1:A" & Rows.Count).End(xlUp)) 'from question

    Dim excelFiles As New Collection
    Dim file As Scripting.File
    For Each file In allFiles
        If file.Type = "Microsoft Excel Worksheet" Then excelFiles.Add file
    Next
End Sub

' Or you could filter by extension, using the FileSystemObject.GetExtensionName method
Sub GetExcelFilesByExtensionName()
    Dim allFiles As Collection
    Set allFiles = GetFiles(ws2.Range("A1:A" & Rows.Count).End(xlUp)) 'from question

    Dim excelFiles As New Collection
    Dim fso As New Scripting.FileSystemObject
    Dim file As Scripting.File
    For Each file In allFiles
        Select Case fso.GetExtensionName(file.path)
            Case "xls", "xlsb", "xlsm"
                excelFiles.Add file
        End Select
    Next
End Sub

Либо вы получите Collection из Fileобъекты, только файлы Excel, из набора корневых папок.


Примечания

  • Этот код рекурсивно добавляет все файлы (не толькоФайлы Excel) в одну коллекцию (в GetFiles), а затем отфильтровывать файлы не из Excel в новую коллекцию.Это может быть менее производительным, чем добавление только файлов Excel в исходную коллекцию, но это ограничит GetFiles только этим сценарием.
  • Если вы хотите вставить результаты в лист ExcelВы можете перебирать excelFiles и вставлять каждый путь в лист.Кроме того, вы можете преобразовать excelFiles в массив и использовать свойство Value объекта Excel Range, чтобы установить все значения из массива, без использования For Each.

Ссылки

Среда выполнения сценариев Microsoft

VBA

0 голосов
/ 04 июня 2018

Вот быстрый способ, слегка адаптированный из этого ответа .

Просто добавьте расположение вашей папки в список path() = ..., и он должен работать для вас.Он выводит в текущем листе Excel пути всех файлов Excel в предоставленных вами папках.

Оттуда вы можете делать то, что вам нравится.(Возможно, добавьте пути к файлам в массив, так что у вас есть массив файлов, которые вы хотите открыть. Оттуда вы можете копировать данные).

'Force the explicit delcaration of variables
Option Explicit

Sub ListFiles()
'http://www.xl-central.com/list-the-files-in-a-folder-and-subfolders.html
'Set a reference to Microsoft Scripting Runtime by using
'Tools > References in the Visual Basic Editor (Alt+F11)

'Declare the variables
Dim objFSO  As Scripting.FileSystemObject
Dim objTopFolder As Scripting.Folder
Dim strTopFolderName As String

Dim path()  As Variant ' EDIT THE BELOW PATH LIST FOR WHATEVER YOU NEED!
path() = Array("C:\Users\USERNAME\Desktop\Stuff\New folder", "C:\Users\USERNAME\Desktop\Other Stuff\")

'Insert the headers for Columns
Range("A1").Value = "File Name"
Range("D1").Value = "File Path"

Dim i       As Long
For i = LBound(path) To UBound(path)
    strTopFolderName = path(i)
    'Create an instance of the FileSystemObject
    Set objFSO = CreateObject("Scripting.FileSystemObject")
    'Get the top folder
    Set objTopFolder = objFSO.GetFolder(strTopFolderName)
    'Call the RecursiveFolder routine
    Call RecursiveFolder(objTopFolder, True)
    'Change the width of the columns to achieve the best fit
    Columns.AutoFit
Next i
End Sub

Sub RecursiveFolder(objFolder As Scripting.Folder, _
                    IncludeSubFolders As Boolean)

'Declare the variables
Dim objFile As Scripting.File
Dim objSubFolder As Scripting.Folder
Dim NextRow As Long

'Find the next available row
NextRow = Cells(Rows.Count, "A").End(xlUp).Row + 1

'Loop through each file in the folder
For Each objFile In objFolder.Files
    Debug.Print (objFile)
    If objFile.Type = "Microsoft Excel Worksheet" Then
        Cells(NextRow, "A").Value = objFile.Name
        Cells(NextRow, "D").Value = objFile.path
        NextRow = NextRow + 1
    End If
Next objFile

'Loop through files in the subfolders
If IncludeSubFolders Then
    For Each objSubFolder In objFolder.SubFolders
        Call RecursiveFolder(objSubFolder, True)
    Next objSubFolder
End If

End Sub
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...