Excel vba диалог сохранения файла
Несомненно каждый разработчик делает работу простого пользователя хоть немного, но проще. И конечно, порой просто необходима обратная связь от пользователя при выполнении некоторых программ. О ней и хочу сегодня рассказать.
Что я имею ввиду: есть ситуации, когда необходимо:
- сообщить пользователю о выполнении кода;
- получить от пользователя подтверждение на выполнение того или иного действия;
- запросить какие-то данные(число, текст для поиска, диапазон поиска и т.п.).
Простейшие запросы и подтверждения можно сделать при помощи уже встроенных диалоговых окон.
Из основных можно выделить три типа:
MsgBox - окно информирования пользователя с возможностью запроса действия (Да, Нет, Отмена и т.п.);
InputBox - окно запроса текстовой информации от пользователя (текст для поиска, дата, число и т.п.);
Application.InputBox - чуть более расширенная версия InputBox с возможностью указания не только текста и чисел, но и выделения диапазона ячеек (например для указания ячеек, в которых осуществлять поиск значения или которые необходимо закрасить).
MsgBox "Обработка завершена"
Все остальные параметры указывать не обязательно, но их использование несколько расширяет возможности данного диалогового окна.
Buttons - указывается тип выводимых кнопок и стиль окна. По умолчанию применяется vbOKOnly - одна только кнопка Ок:
Константы Buttons могут быть объединены между собой. Ниже приведен код, который показывает диалоговое окно с возможностью выбора одного из трех вариантов - Прервать, Повтор, Пропустить:
'--------------------------------------------------------------------------------------- ' Procedure : test ' DateTime : 19.10.2014 19:24 ' Author : The_Prist(Щербаков Дмитрий) ' WebMoney - R298726502453; Яндекс.Деньги - 41001332272872 ' http://www.excel-vba.ru ' Purpose : Процедура показывает диалоговое окно с возможностью выбора одного из трех вариантов: ' Прервать, Повтор, Пропустить ' По умолчанию выделена кнопка Прервать, т.к. иное не указано '--------------------------------------------------------------------------------------- Sub test() Dim lRetVal As Long 'для получения выбранного значения Retry_: lRetVal = MsgBox("Обработка завершена", vbAbortRetryIgnore + vbQuestion) Select Case lRetVal Case vbAbort '3/Прервать/Abort Exit Sub 'выходим из процедуры Case vbRetry '4/Повтор/Retry GoTo Retry_ 'переход на метку Retry_ Case vbIgnore '5/Пропустить/Ignore End Select End Sub
Следующий код показывает то же окно, но по умолчанию выделяет кнопку Пропустить
'--------------------------------------------------------------------------------------- ' Procedure : test ' DateTime : 19.10.2014 19:24 ' Author : The_Prist(Щербаков Дмитрий) ' WebMoney - R298726502453; Яндекс.Деньги - 41001332272872 ' http://www.excel-vba.ru ' Purpose : Процедура показывает диалоговое окно с возможностью выбора одного из трех вариантов: ' Прервать, Повтор, Пропустить ' По умолчанию выделена кнопка Пропустить(3-я по счету - значит vbDefaultButton3) '--------------------------------------------------------------------------------------- Sub test() Dim lRetVal As Long 'для получения выбранного значения Retry_: lRetVal = MsgBox("Обработка завершена", vbAbortRetryIgnore + vbQuestion + vbDefaultButton3) Select Case lRetVal Case vbAbort '3/Прервать/Abort Exit Sub 'выходим из процедуры Case vbRetry '4/Повтор/Retry GoTo Retry_ 'переход на метку Retry_ Case vbIgnore '5/Пропустить/Ignore End Select End Sub
Вместо текстового представления констант можно применить их числовые значения:
Sub test() Dim lRetVal As Long 'для получения выбранного значения Retry_: lRetVal = MsgBox("Обработка завершена", 2 + 32 + 512) Select Case lRetVal Case 3 'vbAbort Exit Sub 'выходим из процедуры Case 4 'vbRetry GoTo Retry_ 'переход на метку Retry_ Case 5 'vbIgnore End Select End Sub
Нетрудно после этого предположить, что можно указать просто сумму данных чисел:
MsgBox "Обработка завершена", 546
Доступные константы значений возврата:
Константа | Значение | Нажатая кнопка |
---|---|---|
vboK | 1 | ОК |
vbCancel | 2 | Отмена |
vbAbort | 3 | Прервать |
vbRetry | 4 | Повтор |
vblgnore | 5 | Пропустить |
vbYes | 6 | Да |
vbNo | 7 | Нет |
Title - указывается текст заголовка окна. Например, можно указать либо что это ошибка, либо имя своего приложения:
MsgBox "Обработка завершена", vbOKOnly, "Мое приложение"
HelpFile - указывается имя файла-справки в формате .HLP. Применяется, если параметр Buttons указан как vbMsgBoxHelpButton. Файл справки должен существовать.
Context - целое число. Указывается индекс страницы файла-справки, которую необходимо открыть. Указывается только если указан параметр HelpFile.
Небольшой практический пример применения простого диалогового окна MsgBox.
Цель процедуры(макроса): очистить все ячейки листа.
Согласитесь, что неплохо бы перед этим запросить у пользователя решение - он согласен с этим и это является обдуманным решением или случайностью?
'--------------------------------------------------------------------------------------- ' Procedure : ClearRange ' DateTime : 19.10.2014 20:06 ' Author : The_Prist(Щербаков Дмитрий) ' WebMoney - R298726502453; Яндекс.Деньги - 41001332272872 ' http://www.excel-vba.ru ' Purpose : '--------------------------------------------------------------------------------------- Sub ClearRange() Dim lRetVal As Long 'для получения выбранного значения lRetVal = MsgBox("Все данные выделенных ячеек будут удалены." & _ Chr(10) & "Действительно хотите продолжить?", _ vbYesNo + vbQuestion, "Запрос на выполнение") If lRetVal = vbNo Then Exit Sub 'выходим из процедуры без выполнения End If Selection.Clear End Sub
Так же на странице Полезные программы для Excel и VBA можно найти программу MsgBox Generator, которая просто и наглядно формирует коды показа MsgBox.
MsgBox, автоматически закрываемый по истечении указанного времени
Диалог MsgBox удобен, если надо проинформировать пользователя о каких-то событиях или предоставить ему выбор Да или Нет. Но в тоже время есть один недостаток: этот диалог не закроется, пока пользователь не нажмет хоть какую-то кнопку. Но бывает необходимо просто проинформировать и закрыть окно независимо от реакции пользователя. Показали окно, подождали секунд 5-7 и даже если пользователь ничего не нажал - закрыли окно и продолжили выполнение кода. Стандартно такой опции в MsgBox нет. Однако можно использовать функции API(это встроенные в ОС Windows функции, которые можно вызывать из любого языка программирования).
Код такого диалога:
Declare Function MessageBoxTimeOut Lib "User32" Alias "MessageBoxTimeoutA" (ByVal hwnd As Long, ByVal lpText As String, ByVal lpCaption As String, ByVal uType As VbMsgBoxStyle, ByVal wLanguageId As Long, ByVal dwMilliseconds As Long) As Long Sub AutoCloseMsgBox() Const lSeconds As Long = 5 MessageBoxTimeOut 0, "Отчет сформирован. Это окно закроется автоматически через 5 секунд", "www.excel-vba.ru", _ vbInformation + vbOKOnly, 0&, lSeconds * 1000 End Sub
Основную роль здесь играет строка:
Declare Function MessageBoxTimeOut Lib "User32" Alias "MessageBoxTimeoutA" (ByVal hwnd As Long, ByVal lpText As String, ByVal lpCaption As String, ByVal uType As VbMsgBoxStyle, ByVal wLanguageId As Long, ByVal dwMilliseconds As Long) As Long
Sub AutoCloseMsgBox() Const lSeconds As Long = 10 Dim retval retval = MessageBoxTimeOut(0, "Файлы обработаны. Вывести список?" & vbNewLine & _ "Если действие не будет выбрано окно закроется через 10 секунд", "www.excel-vba.ru", _ vbInformation + vbYesNo, 0&, lSeconds * 1000) If retval = 6 Then 'была нажата кнопка Да(Yes) 'выводим отчет Else 'была нажата кнопка Нет(No) или окно закрылось само 'другое действие End If End Sub
ДИАЛОГ ВВОДА ИНФОРМАЦИИ ПОЛЬЗОВАТЕЛЕМ - INPUTBOX
InputBox позволяет запросить от пользователя любую текстовую информацию.
InputBox Promt, [Title], [DefaultValue], [XPos], [YPos], [HelpFile], [Context]
Так же как и с MsgBox обязательным аргументом для указания является только Promt - это тот текст, который будет расположен непосредственно на самой форме диалога. Как правило это пояснение, что должен ввести пользователь.
Dim vRetVal 'для получения выбранного значения vRetVal = InputBox("Укажите значение для поиска:", "Запрос данных", "") If vRetVal = "" Then Exit Sub 'завершаем процедуру, если строка пуста
Title - текст, отображаемый в заголовке окна. В приведенном выше примере это "Запрос данных".
DefaultValue - значение, которое будет показано в поле ввода до указания значения пользователем. Как правило оно указывается в случаях, когда требуемое значение изменяется редко по запросу пользователя, но возможность такую оставить все же требуется. Пример: необходимо по нажатию кнопки удалять всегда столбец 5. Но иногда столбец в отчете смещается и требуется запрашивать у пользователя реальный номер столбца:
Sub DelCols() Dim vRetVal 'для получения выбранного значения vRetVal = InputBox("Укажите номер столбца для удаления(целое число):", "Запрос данных", 5) 'используем Val для преобразования текста vRetVal в число 'Val() преобразует число как текст в число. 'Если указан текст(например "третий") - он будет преобразован в 0 vRetVal = Val(vRetVal) If Val(vRetVal) = 0 Then MsgBox "Номер столбца должен быть целым числом больше нуля!", vbCritical, "DelCols" Exit Sub End If Columns(vRetVal).Delete End Sub
Важно знать: InputBox всегда возвращает только текст. Даже если указать - 5 - он вернет "5". В некоторых случаях это может привести к ошибке типов данных, поэтому я привел выше один из примеров преобразования типов данных к нужному.
Так же по прошествии какого-то времени появится вопрос, как отследить нажатие кнопки Отмена. Ведь ориентир на vRetVal = "" не всегда верен, иногда надо принять пустое значение(в случаях, скажем, замены значений) и отследить именно нажатие Отмена. Сделать это можно так:
vRetVal = InputBox("Укажите номер столбца для удаления(целое число):", "Запрос данных", "") If StrPtr(vRetVal) = 0 Then MsgBox "Нажата кнопка Отмена. Процедура прервана", vbCritical, "DelCols" Exit Sub End If
Больше всего вопросов здесь явно вызовет StrPtr . Эта специальная функция VBA, которая указывает, что переданы некие строковые данные. Если никаких данных не передавалось(а в случае с нажатием кнопки Отмена так и есть) указатель вернет 0. Если какие-то данные были переданы или нажата кнопка Ок(автоматом будет передана строка нулевой длины) - указатель StrPtr вернет значение отличное от нуля.
XPos - положение окна InputBox в твипах по горизонтали относительно левого края экрана. Следует учитывать, что именно относительно экрана, а не окна Excel.
YPos - положение окна InputBox в твипах по вертикали относительно верхнего края экрана.
HelpFile - указывается имя файла-справки в формате .HLP. В отличие от MsgBox указание файла допускается при любых значениях. При этом к уже имеющимся в InputBox кнопкам добавляется еще одна - Help, которая и отвечает за вызов справки.
Context - целое число. Указывается индекс страницы файла-справки, которую необходимо открыть при нажатии кнопки Help. Указывается только если указан параметр HelpFile.
В дополнение приведу классический пример применения InputBox - выполнение процедуры только после введения пароля:
Sub ClearAllCells() Dim vRetVal vRetVal = InputBox("Введите пароль:", "Авторизация", "") If StrPtr(vRetVal) = 0 Then 'Нажата кнопка Отмена Exit Sub End If 'если пароль неверный - завершаем процедуру без выполнения действий If vRetVal <> "1234" Then MsgBox "Введенный пароль неверный", vbCritical, "ClearAllCells" Exit Sub End If 'будет выполнено только если введен правильный пароль - 1234 'полная очистка всех ячеек активного листа ActiveSheet.Cells.Clear End Sub
Private Sub Workbook_Open() 'ThisWorkbook - Обращение к книге с кодом 'Но из модуля самой книги можно обращаться и проще - Me ThisWorkbook.Visible = False Dim user As String, lastrow As Long 'цикл, пока не будут указаны данные пользователя Do While user = "" user = InputBox("Введите имя пользователя:", "Авторизация", "") If StrPtr(user) = 0 Then MsgBox "Приложение будет закрыто", vbCritical, "Авторизация" ThisWorkbook.Close Exit Sub End If If user = "" Then MsgBox "Не указано имя пользователя!", vbCritical, "Авторизация" End If Loop With ThisWorkbook.Worksheets("LOG") 'получаем последнюю заполненную ячейку на листе "LOG" lastrow = .Cells(.Rows.Count, 1).End(xlUp).Row 'записываем имя пользователя .Cells(lastrow + 1, 1) = user 'записываем время входа .Cells(lastrow + 1, 2) = Now End With End Sub
Что важно: этот код записывается в модуль ЭтаКнига(ThisWorkbook) и тогда при любом открытии книги будет появляться запрос на имя пользователя.
Так же некоторые примеры применения InputBox можно найти в статьях на сайте. Например:
Как удалить строки по условию?
Как массово изменить гиперссылки?
ДИАЛОГ ВВОДА ИНФОРМАЦИИ ПОЛЬЗОВАТЕЛЕМ - APPLICATION.INPUTBOX
В общем-то данный диалог мало отличается от обычного InputBox, за исключением типов возвращаемых данных. У данного диалога намного богаче функционал определения типов данных.
InputBox Promt, [Title], [DefaultValue], [Left], [Top], [HelpFile], [HelpContextID], [Type]
почти все параметры аналогичны таким же параметрам в InputBox.
Promt - текст, отображаемый на самой форме. Иначе говоря - сама суть показа диалога.
Title - текст, отображаемый в заголовке окна. В приведенном выше примере это "Запрос данных".
DefaultValue - значение, которое будет показано в поле ввода до указания значения пользователем.
Left - положение окна InputBox в поинтах по горизонтали относительно левого края экрана. В отличие от простого InputBox положение определяется на основании расположения самого окна Excel, а не экрана.
Top - положение окна InputBox в твипах по вертикали относительно верхнего края экрана.
HelpFile - указывается имя файла-справки в формате .HLP. В отличие от MsgBox указание файла допускается при любых значениях. При этом к уже имеющимся в InputBox кнопкам добавляется еще одна - Help, которая и отвечает за вызов справки. Сам вызов справки осуществляется путем нажатия на иконку со знаком вопроса в заголовке диалога.
HelpContextID - целое число. Указывается индекс страницы файла-справки, которую необходимо открыть при нажатии кнопки Help. Указывается только если указан параметр HelpFile.
Type - целое число. Указывается одно из предустановленных значений, указывающих диалогу Application.InputBox тип данных, которые предполагается получить от пользователя. Ниже приведен листинг кода, демонстрирующий запрос данных всех типов с описанием ограничений и нюансов.
Конечно, чаще всего используют Type:=8 , т.к. это избавляет от необходимости рисования своих форм и прочих заморочек для запроса указания диапазона от пользователя. Еще раз обращаю внимание, что для Type:=8 необходим ключевой оператор присвоения Set , т.к. в результате необходимо получить именно диапазон(т.е. объект). Ниже приведена процедура, которая запрашивает диапазон для очистки и корректно обрабатывает ситуацию при нажатии кнопки Отмена(т.е. не показывает никаких ошибок пользователю, а просто не выполняется). Стандартно при нажатии Отмена процедура завершается с ошибкой VBA вида Type Mismatch , что не очень грамотно с точки зрения взаимодействия с пользователем - он не должен видеть внутренние ошибки:
'--------------------------------------------------------------------------------------- ' Procedure : ClearCells ' DateTime : 19.10.2014 22:53 ' Author : The_Prist(Щербаков Дмитрий) ' WebMoney - R298726502453; Яндекс.Деньги - 41001332272872 ' http://www.excel-vba.ru ' Purpose : ' Запрашиваем диапазон ячеек для очистки. ' По умолчанию заносится диапазон выделенных на момент запуска ячеек '--------------------------------------------------------------------------------------- Sub ClearCells() Dim vRetVal 'для получения выбранного значения On Error Resume Next Set vRetVal = Application.InputBox("Укажите диапазон для очистки ячеек:", "Запрос данных", Selection.Address, Type:=8) If vRetVal Is Nothing Then 'нажата кнопка Отмена - диапазон не выбран MsgBox "Отмена выполнения", vbCritical, "Нет данных" Exit Sub 'завершаем процедуру, т.к. ячейки не выбраны End If 'диапазон выбран - очищаем ячейки vRetVal.Clear End Sub
Конечно, можно еще много чего, наверное, рассказать - но я на данном этапе завершу. Если будут еще мысли - обязательно дополню статью.
Отображает стандартное диалоговое окно Сохранить как и получает у пользователя имя файла без фактического сохранения файлов.
Синтаксис
выражение.GetSaveAsFilename (InitialFilename, FileFilter, FilterIndex, Title, ButtonText)
выражение: переменная, представляющая объект Application.
Параметры
Имя | Обязательный или необязательный | Тип данных | Описание |
---|---|---|---|
InitialFilename | Необязательный | Variant | Указывает предлагаемое имя файла. Если этот аргумент пропущен, Microsoft Excel использует имя активной книги. |
FileFilter | Необязательный | Variant | Строка, указывающая условия фильтрации файлов. Максимальная длина составляет 255 символов, в противном случае метод возвращает ошибку 2015. |
FilterIndex | Необязательный | Variant | Указывает значение индекса условий фильтрации файлов по умолчанию — от 1 до количества фильтров, указанных в FileFilter. Если этот аргумент пропущен или его значение превышает число имеющихся фильтров, используется первый фильтр файлов. |
Title | Необязательный | Variant | Указывает заголовок диалогового окна. Если этот аргумент пропущен, используется заголовок по умолчанию. |
ButtonText | Необязательный | Variant | Только для Macintosh. |
Возвращаемое значение
Примечания
Эта строка, передаваемая в аргументе FileFilter, состоит из пар строк фильтра файлов, после которых идет спецификация фильтра файлов MS-DOS с подстановочным знаком, где каждая часть и каждая пара разделяются запятыми. Каждая отдельная пара указана в раскрывающемся списке Тип файлов. Например, следующая строка определяет два фильтра файлов — текстовые и для надстроек:
"Text Files (*.txt), *.txt, Add-In Files (*.xla), *.xla"
Чтобы использовать разные выражения с подстановочными знаками MS-DOS для одного типа фильтра файлов, разделяйте выражения с подстановочными знаками точкой с запятой. Пример: "Visual Basic Files (*.bas; *.txt), *.bas;*.txt" .
Этот метод возвращает выбранное имя файла или имя, введенное пользователем. Возвращаемое имя может содержать путь. Возвращается значение False, если пользователь отменяет использование диалогового окна.
Этот метод может менять текущий диск или папку.
При использовании InitialFilename с расширением и применении фильтра это расширение должно соответствовать расширению фильтра, в противном случае действующее значение InitialFilename, отображенное в диалоговом окне, является пустой строкой.
Пример
Поддержка и обратная связь
Есть вопросы или отзывы, касающиеся Office VBA или этой статьи? Руководство по другим способам получения поддержки и отправки отзывов см. в статье Поддержка Office VBA и обратная связь.
Displays the standard Save As dialog box and gets a file name from the user without actually saving any files.
Syntax
expression.GetSaveAsFilename (InitialFilename, FileFilter, FilterIndex, Title, ButtonText)
expression A variable that represents an Application object.
Parameters
Name | Required/Optional | Data type | Description |
---|---|---|---|
InitialFilename | Optional | Variant | Specifies the suggested file name. If this argument is omitted, Microsoft Excel uses the active workbook's name. |
FileFilter | Optional | Variant | A string specifying file filtering criteria. Max length is 255 characters, otherwise the method returns Error 2015. |
FilterIndex | Optional | Variant | Specifies the index number of the default file filtering criteria, from 1 to the number of filters specified in FileFilter. If this argument is omitted or greater than the number of filters present, the first file filter is used. |
Title | Optional | Variant | Specifies the title of the dialog box. If this argument is omitted, the default title is used. |
ButtonText | Optional | Variant | Macintosh only. |
Return value
Remarks
This string passed in the FileFilter argument consists of pairs of file filter strings followed by the MS-DOS wildcard file filter specification, with each part and each pair separated by commas. Each separate pair is listed in the Files of type drop-down list box. For example, the following string specifies two file filters—text and addin:
"Text Files (*.txt), *.txt, Add-In Files (*.xla), *.xla"
To use multiple MS-DOS wildcard expressions for a single file filter type, separate the wildcard expressions with semicolons; for example, "Visual Basic Files (*.bas; *.txt), *.bas;*.txt" .
This method returns the selected file name or the name entered by the user. The returned name may include a path specification. Returns False if the user cancels the dialog box.
This method may change the current drive or folder.
When InitialFilename is used with an extension and a filter is applied, this extension must match the filter extension, otherwise the effective InitialFilename displayed in the dialog box will be an empty string.
Example
This example displays the Save As dialog box, with the file filter set to text files. If the user chooses a file name, the example displays that file name in a message box.
Support and feedback
Have questions or feedback about Office VBA or this documentation? Please see Office VBA support and feedback for guidance about the ways you can receive support and provide feedback.
Часто при работе с файлами и написании кодов начинающие "кодить" в VBA сталкиваются с необходимостью предоставить пользователю возможность самостоятельного выбора файлов: либо всех в указанной папке, либо каких-то отдельных. Конечно, можно жестко в коде написать нечто вроде: "C:\Documents\Files\Книга1.xls" , но это требует не только наличия именно диска С, но и полной структуры папок и имен файлов. Это очень неудобно в большинстве случаев и куда чаще необходимо дать пользователю возможность самому указать имя файла. Записывать в ячейку листа полный путь и имя весьма непрактично и часто для неискушенного пользователя вызывает только "отторжение" от программы. В статье Просмотреть все файлы в папке я приводил пример кода, который просматривает все файлы в указанной папке и папка при этом выбирается сами пользователем из привычного по работе с Windows диалога. Там используется диалог выбора папок. Именно на этом я и хочу сделать акцент в этой статье - рассказать про некоторые способы вызова подобных диалогов для выбора файлов или папки. Так же обращу внимание на некоторые вещи, которые следует учитывать при использовании того или иного типа диалогов.
Диалог выбора файлов Applicaton.GetOpenFileName
Параметры:
Application.GetOpenFilename([FileFilter], [FilterIndex], [Title], [ButtonText], [MultiSelect])
По сути я часто использую именно его, т.к. это универсальный метод и в нем есть все, что лично мне необходимо: выбрать определенные типы файлов позволяет, возможность запрета выбора нескольких файлов сразу есть.
avFiles = Application.GetOpenFilename _ ("Excel files(*.xls*),*.xls*,Text files(*.txt),*.txt", 2, _ "Выбрать текстовые или Excel файлы", , True)
- True - можно будет выбрать более одного файла для обработки(через Shift или Ctrl или простым выделением мышью внутри окна)
- False - можно будет выбрать только один файл
По умолчанию принимает значение False
Выбора только одного файла:
avFiles = Application.GetOpenFilename _ ("Excel files(*.xls*),*.xls*,Text files(*.txt),*.txt", 2, _ "Выбрать текстовые или Excel файлы", , False)
Выбор нескольких файлов:
avFiles = Application.GetOpenFilename _ ("Excel files(*.xls*),*.xls*,Text files(*.txt),*.txt", 2, _ "Выбрать текстовые или Excel файлы", , True)
Пример применения диалога Application.GetOpenFilename
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
В данном случае совершенно неважно указан ли выбор только одного файла или нескольких. Может поменяться только способ обработки полученного результата. Если параметр MultiSelect установлен в False, то переменная avFiles примет тип String, т.е. это будет одна строка. Предположим, что была выбрана книга Excel. Тогда открыть её можно будет как обычно это делается при использовании переменной:
Если же параметр MultiSelect установлен в True, то переменная avFiles примет тип Array - массив строк, в котором будут записаны все пути и имена выбранных файлов. Обрабатывать в таком случае следует циклом:
'avFiles - примет тип Array For Each x In avFiles Workbooks.Open x Next
В приложенном к статье файле приведены две процедуры с использованием этого типа диалога и обработкой файлов с параметром MultiSelect , установленным в True и False.
Диалог выбора файлов FileDialog(msoFileDialogFilePicker)
У этого диалога тоже есть параметры и они очень схожи с таковыми в Application.GetOpenFilename:
Ниже в статье примера кода с применением всех описанных параметров
- True - можно будет выбрать более одного файла для обработки(через Shift или Ctrl или простым выделением мышью внутри окна)
- False - можно будет выбрать только один файл
- Description - описание типа файлов. Произвольный текст, указывающий тип файлов. Например "Рисунки" или "Файлы Excel".
- Extensions - расширения файлов. Непосредственно перед расширением обязательно должна стоять звездочка и точка: *.xls . Иначе диалог выдаст ошибку. Для перечисления нескольких расширений используется разделитель в виде точки-с-запятой: "*.xls*;*.xla*" или "*.xls;*.xlsx;*.xlsm" . Звездочка после расширения заменяет любой набор символов или ни одного. Например, при указании "*.xls*" будет возможным выбрать любые файлы, расширение которых начинается на .xls: .xls,.xlsx,.xlsm,.xlsb и т.д. , но нельзя будет выбрать файлы с расширением .xla,.xlam и тем более .doc или .txt . Если необходимо осуществить выбор любого типа файлов, то необходимо просто очистить фильтр и не добавлять никакие типы: .Filters.Clear
- Position - указывает, каким по счету в списке будет тип файлов. На рисунке ниже первым идет тип "Excel files", а вторым "Text files":
Каждый новый тип файлов добавляется новым Add:
.Filters.Add "Excel files", "*.xls*;*.xla*", 1 'добавляем возможность выбора файлов Excel .Filters.Add "Text files", "*.txt", 2 'добавляем возможность выбора текстовых файлов
Если при этом еще добавить имя файла, то в поле диалога Имя файла будет так же отображено это имя:
- msoFileDialogViewDetails
- msoFileDialogViewLargeIcons
- msoFileDialogViewList
- msoFileDialogViewPreview
- msoFileDialogViewProperties
- msoFileDialogViewSmallIcons
- msoFileDialogViewThumbnail
- msoFileDialogViewTiles
- msoFileDialogViewWebView
For Each x In .SelectedItems Workbooks.Open x Next
Так же можно отбирать только отдельные файлы по индексам или организовать цикл иначе:
For lf = 1 to .SelectedItems.Count x = .SelectedItems(lf) Workbooks.Open x Next
- -1 - выбор файлов был сделан и нажата кнопка Открыть
- 0 - была нажата кнопка отмены
Это можно(точнее нужно!) использовать, чтобы не продолжать выполнение кода, если нажата кнопка Отмены:
If .Show = 0 Then Exit Sub 'была нажата кнопка отмены
Пример вызова диалога выбора файлов:
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 oFD.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) только их меньше доступно для применения:
- msoFileDialogViewDetails
- msoFileDialogViewLargeIcons
- msoFileDialogViewList
- msoFileDialogViewPreview
- msoFileDialogViewProperties
- msoFileDialogViewSmallIcons
- msoFileDialogViewThumbnail
- msoFileDialogViewTiles
- msoFileDialogViewWebView
- -1 - папка выбрана и нажата кнопка Открыть
- 0 - была нажата кнопка отмены
Это можно(точнее нужно!) использовать, чтобы не продолжать выполнение кода, если нажата кнопка Отмены:
If .Show = 0 Then Exit Sub 'была нажата кнопка отмены
Пример вызова диалога выбора папки:
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 oFD.Show = 0 Then Exit Sub 'показывает диалог 'цикл по коллекции выбранных в диалоге файлов x = .SelectedItems(1) 'считываем путь к папке MsgBox "Выбрана папка: '" & x & "'", vbInformation, "www.excel-vba.ru" End With End Sub
Диалог выбора папки через Shell
Диалог Application.FileDialog(msoFileDialogFolderPicker) всем хорош и удобен, кроме одного: как я уже упоминал, он стал доступен из VBA только начиная с 2002 Excel. Плюс, описанные выше диалоги не работают в Outlook - он просто лишен хоть какой-либо реализации выбора папок или файлов. Поэтому дополню статью еще одним вариантом показа диалога выбора папки - с помощью объекта Shell. Этот вариант выбора папки будет работать и в Outlook и в любом другом приложении.
Shell.BrowseForFolder([Hwnd], [sTitle], [iOptions], [vRootFolder])
Hwnd | Дескриптор окна, к которому будет относится диалог. Как правило указывается 0 |
sTitle | Поясняющий текст, который будет отображен в диалоге. Подобие заголовка окна. Может быть любым текстом, например "Выбрать папку с отчетами" |
iOptions | Дополнительные параметры для диалога. Рекомендуется использовать 0. Но можно попробовать и пару других вариантов. Например, если указать 20, то в диалоговом окне появится дополнительное текстовое поле, в котором будет отображено имя выбранной папки. |
vRootFolder | Аналогично InitialFileName в рассмотренных выше диалогах. Задает начальную папку, на которой диалог будет открыт после запуска. |
Пример вызова диалога выбора папки через Shell:
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 KiB, 3 529 скачиваний)
Диалог сохранения файла SaveAs
Еще один вид диалогового окна - запрос имени и места сохранения файла.
Параметры:
Application.GetSaveAsFilename([InitialFileName], [FileFilter], [FilterIndex], [Title], [ButtonText])
Универсальный диалог, работающий во всех версиях Excel, начиная с 2000
Показываем диалог со стартовой папкой на той книге, в которой сам макрос и именем сохраняемой книги "SaveAs.xlsm" :
sToSavePath = Application.GetSaveAsFilename(InitialFileName:="SaveAs.xlsm", FileFilter:="Excel files (*.xlsm), *.xlsm")
avFiles = Application.GetSaveAsFilename _ (InitialFileName:=ThisWorkbook.Path, FileFilter:="Excel files(*.xls*),*.xls*,Text files(*.txt),*.txt", FilterIndex:=2)
Что еще важно знать: сам по себе вызов диалога GetSaveAsFilename ничего не сохраняет - он только создает путь для сохраняемого файла. Сохранять придется принудительно после выбора места и имени.
Пример применения диалога Application.GetSaveAsFilename
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
Здесь тоже есть нюанс - метод SaveAs имеет два важных аргумента:
1. Filename - путь и имя сохраняемого файла. Здесь должно быть все понятно. Указываем то, что выбрали в диалоге.
2. FileFormat - формат сохраняемого файла. При этом не текстовое представление(как в диалоге "xls" или "txt"), а одна из предустановленных констант формата файла. Вот основные константы:
Пример использования констант в диалогах Application.GetSaveAsFilename
Сохраняем файл с форматом 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
Любой метод: либо числовая константа, либо встроенная работают одинаково. Вопрос лишь в том, что лично для Вас будет удобнее и нагляднее.
VBA Save File Dialog, FileDialog(msoFileDialogSaveAs)
There may be times when you need to ask the user to select a location to save a file. This can be done using the save file dialog. Keep in mind that the save file dialogs doesn’t actually save anything. It only returns the full path the user has selected to save the file.
The method for creating the save file dialog explained in this article uses the command FileDialog(msoFileDialogSaveAs). It has only one problem. You can’t apply file type filters. If file type filters are essential, there are 2 things you could do:
- If you are using VBA for Excel, you could use the method described in the article, Excel VBA Save File Dialog, GetSaveAsFilename()
- If you are not using VBA for Excel you will have to use windows API, please see MSDN, Microsoft Display Open and Save As Dialog Boxes in Access with API Functions.
You can download the file and code related to this article here.
Example:
In this example a dialog will open asking the user to select a location to save the file. The path selected will be displayed in a message box:
Sub Example1()
Dim intChoice As Integer
Dim strPath As String
'make the file dialog visible to the user
intChoice = Application.FileDialog(msoFileDialogSaveAs).Show
'determine what choice the user made
If intChoice <> 0 Then
'get the file path selected by the user
strPath = _
Application.FileDialog(msoFileDialogSaveAs).SelectedItems(1)
'displays the result in a message box
Call MsgBox(strPath, vbInformation, "Save Path")
End If
End Sub
The following details were selected to save the file:
- File Name: “Test”
- File Path: “D:Temp”
- File Type: Excel Workbook (*.xlsx)
The resulting path is displayed in a message box:
Custom Title:
By default the title of the Save File Dialog is “File Save”:
Using the .Title property you can set a custom title for the dialog. In the example below the title “Random Title For Dialog” will be used:
Sub Example2()
Dim intChoice As Integer
'change the display name of the save file dialog
Application.FileDialog(msoFileDialogSaveAs).Title = _
"Random Title For Dialog"
'make the file dialog visible to the user
intChoice = Application.FileDialog(msoFileDialogSaveAs).Show
'determine what choice the user made
If intChoice <> 0 Then
'your code here
End If
End Sub
Start Folder Path, InitialFileName:
Lets say there is a specific folder we would want the dialog to start in. This could be set by the InitialFileName property. In the example below the save file dialog will start in the directory “D:TempFolder to Start”:
Sub Example3()
Dim intChoice As Integer
'Select the start folder
Application.FileDialog(msoFileDialogSaveAs).InitialFileName _
= "D:TempFolder to Start"
'make the file dialog visible to the user
intChoice = Application.FileDialog(msoFileDialogSaveAs).Show
'determine what choice the user made
If intChoice <> 0 Then
'your code here
End If
End Sub
Filter File Types, Filters:
Unlike the Open File Dialog where you could change the file type filters, the save file dialog will generate an error if you try to modify the file type filters. As explained at the start of this article if file filters are essential, there are 2 options you could consider:
Читайте также: