Стоит следующая задача. В папке у коллег собираются подпапки, в которых хранятся файлы, содержающие формы опросники. Уровней подпапок может быть от 1 до 5. Файлы опросники представляют собой стандартизированную форму, в которую респонденты вносят данные. Т.е. сам вид и структура форм не меняется. Но меняется порядок листов в книге и само название "Форма №" (см файлы вложения) сдвигается в рамках первой строки и 4го и 7го столбца.
Стоит задача написать макрос, который бы спрашивал, из какой корневой папки производить поиск файлов (в том числе в подпапках), идентифицировать в каждом файле (Файле-источнике) какой лист является какой формой (форма 1 или форма 2, ...), изымать данные (целый столбец) из соответствующего листа по порядку и вставлять транспонированно в файл-конечный.
Примеры файлов-источников и результат свода в приложении.
Нашел функцию, возвращающую путь к выбранной в диалоговом окне папке
Function GetFolderPath(OptionalByVal Title AsString = "Выберите папку", _ OptionalByVal InitialPath AsString = "c:\") AsString ' функция выводит диалоговое окно выбора папки с заголовком Title, ' начиная обзор диска с папки InitialPath ' возвращает полный путь к выбранной папке, или пустую строку в случае отказа от выбора Dim PS AsString: PS = Application.PathSeparator With Application.FileDialog(msoFileDialogFolderPicker) IfNotRight$(InitialPath, 1) = PS Then InitialPath = InitialPath & PS
.ButtonName = "Выбрать": .Title = Title: .InitialFileName = InitialPath If .Show <> -1ThenExitFunction
GetFolderPath = .SelectedItems(1) IfNotRight$(GetFolderPath, 1) = PS Then GetFolderPath = GetFolderPath & PS EndWith EndFunction
Ее результат использую для подмодуля
Sub GetAllFileNamesDict(FolderPath$, ByVal SearchDeep%, FSO, oDict1, oDict2) Dim oFile, oCurFolder, oSubFolder OnErrorResumeNext Set oCurFolder = FSO.GetFolder(FolderPath) IfNot oCurFolder IsNothingThen'чтобы не зациклилось при рекурсивном вызове, когда нет подпапок и oSubFolder=Nothing
Application.StatusBar = "Поиск в папке: " & FolderPath ' вывод пути к просматриваемой в текущий момент папке в строку состояния Excel For Each oFile In oCurFolder.Files ' перебираем все файлы в папке FolderPath With oFile
oDict1.Item(oDict1.count + 1) = .Path
oDict2.Item(oDict2.count + 1) = .Name EndWith Next oFile
SearchDeep = SearchDeep - 1' один уровень поиска прошли If SearchDeep Then' если надо искать в подпапках глубже For Each oSubFolder In oCurFolder.SubFolders ' перебираем все подпапки в папке FolderPath
GetAllFileNamesDict oSubFolder.Path, SearchDeep, FSO, oDict1, oDict2 Next oSubFolder EndIf EndIf Set oFile = Nothing: Set oCurFolder = Nothing: Set oSubFolder = Nothing DoEvents' чтобы можно было прервать слишком длинную рекурсию EndSub
Под модуль возвращает два словаря. В одном массив путей к файлам, во втором - имена. Пути затем использую для открытия в цикле файла, его название - для изъятия данных. Понимаю, что можно оптимизировать процесс, поэтому буду рад предложениям. Застрял на проблеме транспонирования. Решил вставлять поячеечно, но это очень замедляет процесс.
При оформлении постов используйте тэги!
Добрый день, форумчане.
Стоит следующая задача. В папке у коллег собираются подпапки, в которых хранятся файлы, содержающие формы опросники. Уровней подпапок может быть от 1 до 5. Файлы опросники представляют собой стандартизированную форму, в которую респонденты вносят данные. Т.е. сам вид и структура форм не меняется. Но меняется порядок листов в книге и само название "Форма №" (см файлы вложения) сдвигается в рамках первой строки и 4го и 7го столбца.
Стоит задача написать макрос, который бы спрашивал, из какой корневой папки производить поиск файлов (в том числе в подпапках), идентифицировать в каждом файле (Файле-источнике) какой лист является какой формой (форма 1 или форма 2, ...), изымать данные (целый столбец) из соответствующего листа по порядку и вставлять транспонированно в файл-конечный.
Примеры файлов-источников и результат свода в приложении.
Нашел функцию, возвращающую путь к выбранной в диалоговом окне папке
Function GetFolderPath(OptionalByVal Title AsString = "Выберите папку", _ OptionalByVal InitialPath AsString = "c:\") AsString ' функция выводит диалоговое окно выбора папки с заголовком Title, ' начиная обзор диска с папки InitialPath ' возвращает полный путь к выбранной папке, или пустую строку в случае отказа от выбора Dim PS AsString: PS = Application.PathSeparator With Application.FileDialog(msoFileDialogFolderPicker) IfNotRight$(InitialPath, 1) = PS Then InitialPath = InitialPath & PS
.ButtonName = "Выбрать": .Title = Title: .InitialFileName = InitialPath If .Show <> -1ThenExitFunction
GetFolderPath = .SelectedItems(1) IfNotRight$(GetFolderPath, 1) = PS Then GetFolderPath = GetFolderPath & PS EndWith EndFunction
Ее результат использую для подмодуля
Sub GetAllFileNamesDict(FolderPath$, ByVal SearchDeep%, FSO, oDict1, oDict2) Dim oFile, oCurFolder, oSubFolder OnErrorResumeNext Set oCurFolder = FSO.GetFolder(FolderPath) IfNot oCurFolder IsNothingThen'чтобы не зациклилось при рекурсивном вызове, когда нет подпапок и oSubFolder=Nothing
Application.StatusBar = "Поиск в папке: " & FolderPath ' вывод пути к просматриваемой в текущий момент папке в строку состояния Excel For Each oFile In oCurFolder.Files ' перебираем все файлы в папке FolderPath With oFile
oDict1.Item(oDict1.count + 1) = .Path
oDict2.Item(oDict2.count + 1) = .Name EndWith Next oFile
SearchDeep = SearchDeep - 1' один уровень поиска прошли If SearchDeep Then' если надо искать в подпапках глубже For Each oSubFolder In oCurFolder.SubFolders ' перебираем все подпапки в папке FolderPath
GetAllFileNamesDict oSubFolder.Path, SearchDeep, FSO, oDict1, oDict2 Next oSubFolder EndIf EndIf Set oFile = Nothing: Set oCurFolder = Nothing: Set oSubFolder = Nothing DoEvents' чтобы можно было прервать слишком длинную рекурсию EndSub
Под модуль возвращает два словаря. В одном массив путей к файлам, во втором - имена. Пути затем использую для открытия в цикле файла, его название - для изъятия данных. Понимаю, что можно оптимизировать процесс, поэтому буду рад предложениям. Застрял на проблеме транспонирования. Решил вставлять поячеечно, но это очень замедляет процесс.
Спасибо за ответ. Я тоже так думал. И тут у меня возникли проблемы. Первый раз скопировать данные через диапазон и вставить транспонированно получилось. Потом что-то пошло не так, как говорится. Транспонировать перестало получаться. Были мысли, что проблема в наличии пароля в файлах источниках. Но я их предварительно снимаю командой workbooks(...).unprotect
Спасибо за ответ. Я тоже так думал. И тут у меня возникли проблемы. Первый раз скопировать данные через диапазон и вставить транспонированно получилось. Потом что-то пошло не так, как говорится. Транспонировать перестало получаться. Были мысли, что проблема в наличии пароля в файлах источниках. Но я их предварительно снимаю командой workbooks(...).unprotect