Часто при работе с файлами и написании кодов начинающие "кодить" в VBA сталкиваются с необходимостью предоставить пользователю возможность самостоятельного выбора файлов: либо всех в указанной папке, либо каких-то отдельных. Конечно, можно жестко в коде написать нечто вроде:
- Диалог выбора файлов Applicaton.GetOpenFileName
- Диалог выбора файлов FileDialog(msoFileDialogFilePicker)
- Диалог выбора папки FileDialog(msoFileDialogFolderPicker)
- Диалог выбора папки через Shell
- Диалог сохранения файла SaveAs
Если рассматривать наиболее простые варианты, то их два. Выбрать файлы можно через Applicaton.GetOpenFileName или через Application.FileDialog. Отличия в них есть, но я заострю внимание на главном: GetOpenFileName будет работать в любой версии Excel, а класс FileDialog только начиная с Excel 2002, т.к. именно в этой версии впервые был использован класс FileDialog. Это стоит учитывать при разработке.
Параметры:
FileFilter |
Указываются типы файлов, которые будут отображаться в диалоговом окне выбора. Например, если указать "Excel files(*.xls*),*.xls*", то возможно будет выбрать только файлы Excel(с расширением, начинающимся на .xls - .xls, .xlsx, .xlsb, .xlsm и т.д.). Если указать "Text files(*.txt),*.txt", то можно будет выбрать только текстовые файлы с расширением .txt. Так же можно указать более одного типа расширений: "Excel files(*.xls*),*.xls*,Text files(*.txt),*.txt". По умолчанию тип файлов в диалоговом окне будет принадлежать первому указанному типу файлов(*.xls*). Но можно указать любой из перечисленных типов при помощи аргумента |
||
FilterIndex |
Если аргументом
|
||
Title | Текст заголовка диалогового окна. Если указать "Выбрать текстовые или Excel файлы", то именно этот текст будет в заголовке. Если не указывать, то будет текст по умолчанию(нечто вроде "Открытие документа") | ||
ButtonText | Данный аргумент доступен только для ПК под управлением Macintosh(MAC). Назначает текст для кнопки диалогового окна Открыть. Для владельцев Windows этот текст всегда будет "Открыть" | ||
MultiSelect |
Указывает, может быть выбран только один файл или несколько:
По умолчанию принимает значение False
Выбор нескольких файлов:
|
Sub ShowGetOpenDialod() Dim avFiles 'по умолчанию к выбору доступны файлы Excel(xls,xlsx,xlsm,xlsb) avFiles = Application.GetOpenFilename _ ("Excel files(*.xls*),*.xls*", 1, "Выбрать Excel файлы", , False) If VarType(avFiles) = vbBoolean Then 'была нажата кнопка отмены - выход из процедуры Exit Sub End If 'avFiles - примет тип String MsgBox "Выбран файл: '" & avFiles & "'", vbInformation, "www.excel-vba.ru" End Sub |
В данном случае совершенно неважно указан ли выбор только одного файла или нескольких. Может поменяться только способ обработки полученного результата. Если параметр
Workbooks.Open avFiles |
Если же параметр
'avFiles - примет тип Array For Each x In avFiles Workbooks.Open x Next |
В приложенном к статье файле приведены две процедуры с использованием этого типа диалога и обработкой файлов с параметром
У этого диалога тоже есть параметры и они очень схожи с таковыми в Application.GetOpenFilename:
AllowMultiSelect |
Указывает, может быть выбран только один файл или несколько:
|
||
Title | Текст заголовка диалогового окна. Если указать "Выбрать текстовые или Excel файлы", то именно этот текст будет в заголовке. Если не указывать, то будет текст по умолчанию(нечто вроде "Открытие документа") | ||
Filters |
Перечисляются типы файлов, которые будут отображаться в диалоговом окне выбора. Для добавления типа файла(расширения) необходимо использовать метод Add:
Тип файлов, который будет показан по умолчанию при вызове диалога определяется свойством Каждый новый тип файлов добавляется новым Add:
|
||
FilterIndex | Назначает тип файлов, который будет выбран по умолчанию из всех перечисленных в коллекции Filters при вызове диалога | ||
InitialFileName | Этим параметром можно задать начальную папку, на которой будет открыт диалог:
Если при этом еще добавить имя файла, то в поле диалога Имя файла будет так же отображено это имя:
Я лично не рекомендую указывать имя файла, т.к. после показа диалога этот файл автоматически будет выбран, что не всегда бывает правильным. Но все зависит от задач. Если пользователь не выберет самостоятельно ни одного файла, то ответом диалога будет именно файл с указанным именем(Книга1.xlsx). Если такого файла не окажется в папке, то диалог выдаст предупреждение, что такого файла нет. |
||
InitialView | Данный параметр определяет внешний вид и структуру окна диалога. Доступно 9 вариантов:
При использовании данного параметра следует учитывать, что на разных операционных системах могут быть доступны не все варианты. Поэтому прежде чем использовать лучше убедиться, что на конечных ПК поддерживается указанный тип. В принципе ничего страшного не произойдет - будет просто показано окно с видом по умолчанию. Но куда правильнее в разработке придерживаться однотипного вида на всех ПК. |
||
SelectedItems | Возвращает коллекцию выбранных файлов. В отличии от Application.GetOpenFilename всегда возвращается массив строк, поэтому можно всегда использовать цикл для открытия файлов, даже если параметр
Так же можно отбирать только отдельные файлы по индексам или организовать цикл иначе:
Нумерация строк в SelectedItems всегда начинается с 1 |
||
Show | Пожалуй, самый важный метод в диалоге - отвечает за показ диалога. При этом метод Show возвращает ответ в виде целого числа:
Это можно(точнее нужно!) использовать, чтобы не продолжать выполнение кода, если нажата кнопка Отмены:
|
Sub ShowFileDialog() Dim oFD As FileDialog Dim x, lf As Long 'назначаем переменной ссылку на экземпляр диалога Set oFD = Application.FileDialog(msoFileDialogFilePicker) With oFD 'используем короткое обращение к объекту 'так же можно без oFD 'With Application.FileDialog(msoFileDialogFilePicker) .AllowMultiSelect = False .Title = "Выбрать файлы отчетов" 'заголовок окна диалога .Filters.Clear 'очищаем установленные ранее типы файлов .Filters.Add "Excel files", "*.xls*;*.xla*", 1 'устанавливаем возможность выбора только файлов Excel .Filters.Add "Text files", "*.txt", 2 'добавляем возможность выбора текстовых файлов .FilterIndex = 2 'устанавливаем тип файлов по умолчанию - Text files(Текстовые файлы) .InitialFileName = "С:\Temp\Книга1.xlsx" 'назначаем папку отображения и имя файла по умолчанию .InitialView = msoFileDialogViewDetails 'вид диалогового окна(доступно 9 вариантов) If .Show = 0 Then Exit Sub 'показывает диалог 'цикл по коллекции выбранных в диалоге файлов For lf = 1 To .SelectedItems.Count x = .SelectedItems(lf) 'считываем полный путь к файлу Workbooks.Open x 'открытие книги 'можно также без х 'Workbooks.Open .SelectedItems(lf) Next End With End Sub |
Диалог выбора папки необходим в случаях, когда файлов в папке много и обработать нужно все эти файлы. Пример такой обработки я уже выкладывал в статье Просмотреть все файлы в папке. Здесь проще всего использовать появившийся в 2002 Excel диалог Application.FileDialog. Его параметры практически такие же, как у Application.FileDialog(msoFileDialogFilePicker) только их меньше доступно для применения:
Title | Текст заголовка диалогового окна. Если указать "Выбрать папку с отчетами", то именно этот текст будет в заголовке. Если не указывать, то будет текст по умолчанию(нечто вроде "Открыть папку") | |
InitialFileName | Этим параметром можно задать начальную папку, на которой будет открыт диалог:
|
|
InitialView | Данный параметр определяет внешний вид и структуру окна диалога. Доступно 9 вариантов:
При использовании данного параметра следует учитывать, что на разных операционных системах могут быть доступны не все варианты. Поэтому прежде чем использовать лучше убедиться, что на конечных ПК поддерживается указанный тип. В принципе ничего страшного не произойдет - будет просто показано окно с видом по умолчанию. Но куда правильнее в разработке придерживаться однотипного вида на всех ПК. |
|
SelectedItems | Возвращает коллекцию с одним элементом, в котором содержится путь к выбранной папке. Нумерация строк в SelectedItems всегда начинается с 1, но т.к. выбор нескольких папок невозможен, то всегда указывается 1: x = .SelectedItems(1) | |
ButtonName | Назначает текст кнопки, которой подтверждается выбор папки. Может содержать не более 51 знака(чего как правило достаточно). | |
Show | Метод, который вызывает показ диалога с выбранными параметрами. Возвращает ответ в виде целого числа:
Это можно(точнее нужно!) использовать, чтобы не продолжать выполнение кода, если нажата кнопка Отмены:
|
Sub ShowFolderDialog() Dim oFD As FileDialog Dim x, lf As Long 'назначаем переменной ссылку на экземпляр диалога Set oFD = Application.FileDialog(msoFileDialogFolderPicker) With oFD 'используем короткое обращение к объекту 'так же можно без oFD 'With Application.FileDialog(msoFileDialogFolderPicker) .Title = "Выбрать папку с отчетами" '"заголовок окна диалога .ButtonName = "Выбрать папку" .Filters.Clear 'очищаем установленные ранее типы файлов .InitialFileName = "C:\Temp\" '"назначаем первую папку отображения .InitialView = msoFileDialogViewLargeIcons 'вид диалогового окна(доступно 9 вариантов) If .Show = 0 Then Exit Sub 'показывает диалог 'цикл по коллекции выбранных в диалоге файлов x = .SelectedItems(1) 'считываем путь к папке MsgBox "Выбрана папка: '" & x & "'", vbInformation, "www.excel-vba.ru" End With End Sub |
Диалог Application.FileDialog(msoFileDialogFolderPicker) всем хорош и удобен, кроме одного: как я уже упоминал, он стал доступен из VBA только начиная с 2002 Excel. Плюс, описанные выше диалоги не работают в Outlook - он просто лишен хоть какой-либо реализации выбора папок или файлов. Поэтому дополню статью еще одним вариантом показа диалога выбора папки - с помощью объекта Shell. Этот вариант выбора папки будет работать и в Outlook и в любом другом приложении.
Hwnd | Дескриптор окна, к которому будет относится диалог. Как правило указывается 0 |
sTitle | Поясняющий текст, который будет отображен в диалоге. Подобие заголовка окна. Может быть любым текстом, например "Выбрать папку с отчетами" |
iOptions | Дополнительные параметры для диалога. Рекомендуется использовать 0. Но можно попробовать и пару других вариантов. Например, если указать 20, то в диалоговом окне появится дополнительное текстовое поле, в котором будет отображено имя выбранной папки. |
vRootFolder | Аналогично InitialFileName в рассмотренных выше диалогах. Задает начальную папку, на которой диалог будет открыт после запуска. |
Sub GetFolderDialog_Shell() On Error Resume Next Dim objShellApp As Object, objFolder As Object, ulFlags Dim x As String Set objShellApp = CreateObject("Shell.Application") 'ulFlags - числовой код, определяющий вид отображаемого окна и некоторые параметры ' ulFlags = 0 - наиболее часто применяемый. Лучше использовать всегда именно 0 ' ulFlags = 1 - не отображать Корзину ' ulFlags = 2 - не включать сетевые папки ' ulFlags = 20 - добавляется тестовое поле с отображением имени выбранной папки ' ulFlags = 16 - отображать EditBox для ввода полного пути с клавиатуры ' ulFlags = 16384 - можно так же выбирать файлы. 'Некоторые константы можно комбинировать. Например если указать 1 + 16384 - то можно будет выбирать файлы ulFlags = 0 Set objFolder = objShellApp.BrowseForFolder(0, "Выбрать папку с отчетами", ulFlags, "C:\Temp\")'" x = objFolder.Self.Path 'записываем в переменную путь к папке If Err.Number <> 0 Then MsgBox "Папка не выбрана!", vbInformation, "www.excel-vba.ru" Else MsgBox "Выбрана папка: '" & x & "'", vbInformation, "www.excel-vba.ru" End If End Sub |
Конечно, диалог подобный выглядит довольно убого, особенно на современных операционных системах. Но он работает в любых версиях офиса и в любом приложении, в том числе в Outlook. Порой это бывает полезней красоты.
Tips_Macro_GetOpenFileFolder.xls (100,0 КиБ, 4 099 скачиваний)
Еще один вид диалогового окна - запрос имени и места сохранения файла.
Параметры:
InitialFileName |
Можно указать путь и имя файла, которые будут использованы в качестве шаблона для сохранения. По умолчанию в диалоге отображается папка, которая была использована в последний раз в текущем сеансе Excel. Если диалог вызывается впервые, то будет показана для сохранения файлов по умолчанию(задается из самого Excel: Показываем диалог со стартовой папкой на той книге, в которой сам макрос, без указания имени сохраняемой книги:
Показываем диалог со стартовой папкой на той книге, в которой сам макрос и именем сохраняемой книги
|
||
FileFilter |
Указываются типы файлов, которые будут отображаться в диалоговом окне выбора. Должен совпадать с тем типом, с которым собираемся сохранять файл. Например, если указать "Excel files(*.xls*),*.xls*", то возможно будет выбрать только тип файлов Excel(с расширением, начинающимся на .xls - .xls, .xlsx, .xlsb, .xlsm и т.д.). Если указать "Text files(*.txt),*.txt", то только текстовые файлы с расширением .txt. Так же можно указать более одного типа расширений: "Excel files(*.xls*),*.xls*,Text files(*.txt),*.txt". По умолчанию тип файлов в диалоговом окне будет принадлежать первому указанному типу файлов(*.xls*). Но можно указать любой из перечисленных типов при помощи аргумента |
||
FilterIndex |
Если аргументом
|
||
Title | Текст заголовка диалогового окна. Если указать "Выбрать текстовые или Excel файлы", то именно этот текст будет в заголовке. Если не указывать, то будет текст по умолчанию(нечто вроде "Сохранение документа") | ||
ButtonText | Данный аргумент доступен только для ПК под управлением Macintosh(MAC). Назначает текст для кнопки диалогового окна Сохранить. Для владельцев Windows этот текст всегда будет "Сохранить" |
Что еще важно знать: сам по себе вызов диалога
Sub ShowGetSaveAsDialod() Dim sToSavePath sToSavePath = Application.GetSaveAsFilename( _ InitialFileName:=ThisWorkbook.Path, _ FileFilter:="Excel files(*.xls*),*.xls*,Text files(*.txt),*.txt", _ FilterIndex:=2, _ Title:="Сохранить файл") 'если нажали Отмена - завершаем процедуру ничего не сохраняя If VarType(sToSavePath) = vbBoolean Then Exit Sub End If 'непосредственно сохранение файла ThisWorkbook.SaveAs Filename:=sToSavePath, FileFormat:=ThisWorkbook.FileFormat End Sub |
Здесь тоже есть нюанс - метод
1.
2.
Константа Excel | Числовая константа | Расшифровка |
---|---|---|
xlOpenXMLWorkbookMacroEnabled | 51 | xlsm - книга Excel |
xlOpenXMLWorkbookMacroEnabled | 52 | xlsm - книга Excel с поддержкой макросов |
xlExcel12 | 50 | xlsb - двоичная книга Excel (с поддержкой макросов) |
xlOpenXMLAddIn | 55 | xlam - надстройка Excel |
xlOpenXMLTemplate | 54 | xltx - шаблон Excel |
xlOpenXMLTemplateMacroEnabled | 53 | xltm - шаблон Excel с поддержкой макросов |
xlExcel8 | 56 | xls - книга Excel(97 - 2003) |
xlAddIn | 18 | xla - надстройка Excel(97 - 2003) |
xlTemplate | 17 | xlt - шаблон Excel(97 - 2003) |
xlCurrentPlatformText | -4158 | txt - текстовый файл с разделителями табуляции |
xlUnicodeText | 42 | txt - текстовый файл в кодировке Юникод |
xlCSV | 6 | csv - CSV(разделитель запятая) |
xlCSVMSDOS | 24 | csv - CSV(MS - DOS) |
XlFileFormat | 62 | csv - CSV UTF-8(разделитель запятая) |
xlTypePDF | 0 | pdf - файл в формате PDF |
Сохраняем файл с форматом xlsm - файл с поддержкой макросов. Для этого ищем в таблице выше расширение xlsm и берем либо константу Excel либо числовую константу:
Sub ShowGetSaveAsDialod() Dim sToSavePath sToSavePath = Application.GetSaveAsFilename( _ InitialFileName:=ThisWorkbook.Path & "\Report.xlsm", _ FileFilter:="Excel files(*.xlsm),*.xlsm") 'если нажали Отмена - завершаем процедуру ничего не сохраняя If VarType(sToSavePath) = vbBoolean Then Exit Sub End If 'непосредственно сохранение файла 'используем встроенную константу Excel ThisWorkbook.SaveAs Filename:=sToSavePath, FileFormat:=xlOpenXMLWorkbookMacroEnabled 'используем числовую константу 'ThisWorkbook.SaveAs Filename:=sToSavePath, FileFormat:=52 End Sub |
Любой метод: либо числовая константа, либо встроенная работают одинаково. Вопрос лишь в том, что лично для Вас будет удобнее и нагляднее.
Так же см.:
Работа с диалогами
Как запретить сообщения?