Vba excel getopenfilename не работает

Обновлено: 08.07.2024

Вот декларация (ситема Win7, 64)
Declare PtrSafe Function GetOpenFileName Lib "COMDLG32" Alias "GetOpenFileNameA" (file As OPENFILENAME) As Long
Type OPENFILENAME
lStructSize As Long
hWndOwner As Long
hInstance As Long
lpstrFilter As String
lpstrCustomFilter As String
nMaxCustFilter As Long
nFilterIndex As Long
lpstrFile As String
nMaxFile As Long
lpstrFileTitle As String
nMaxFileTitle As Long
lpstrInitialDir As String
lpstrTitle As String
flags As Long
nFileOffset As Integer
nFileExtension As Integer
lpstrDefExt As String
lCustData As Long
lpfnHook As Long
lpTemplateName As String
End Type
Function BrowseForFile(sInitDir As String, Optional ByVal sFileFilters As String, Optional sTitle As String = "Open File", Optional lParentHwnd As Long) As String
Dim tFileBrowse As OPENFILENAME
Const clMaxLen As Long = 254
tFileBrowse.lStructSize = OPENFILENAME_SIZE_VERSION_400
sFileFilters = Replace(sFileFilters, "|", vbNullChar)
sFileFilters = Replace(sFileFilters, ";", vbNullChar)
If Right$(sFileFilters, 1) <> vbNullChar Then
sFileFilters = sFileFilters & vbNullChar
End If
tFileBrowse.lpstrFilter = sFileFilters & "All Files (*.*)" & vbNullChar & "*.*" & vbNullChar
tFileBrowse.lpstrFile = String(clMaxLen, " ")
tFileBrowse.nMaxFile = clMaxLen + 1
tFileBrowse.lpstrFileTitle = Space$(clMaxLen)
tFileBrowse.nMaxFileTitle = clMaxLen + 1
tFileBrowse.lpstrInitialDir = sInitDir
tFileBrowse.hWndOwner = lParentHwnd
tFileBrowse.lpstrTitle = sTitle
tFileBrowse.flags = OFN_FILEMUSTEXIST Or OFN_PATHMUSTEXIST Or OFN_HIDEREADONLY Or OFN_ALLOWMULTISELECT
If GetOpenFileName(tFileBrowse) Then
BrowseForFile = Trim$(tFileBrowse.lpstrFile)
If Right$(BrowseForFile, 1) = vbNullChar Then
BrowseForFile = Left$(BrowseForFile, Len(BrowseForFile) - 1)
End If
End If
End Function

И проверка работы
Sub GetFile()
Debug.Print BrowseForFile("c:\", "Excel File (*.xls);*.xls", "Open Workbook")
End Sub

В результате запуска ничего не происходит. Ошибок нет. На выходе GetOpenFileName просто пустая строка. Много перечитал, решения не нашел.
Код используется в CorelDraw, поэтому штатные офисные средства (типа FileDialog не проходят) . Полагаю, остается только WinAPI.
Кстати, функция SHGetPathFromIDListA из shell32 работает отлично. Но это для папок.

В процессе выполнения этого кода VBA Excel открывается диалог с заголовком по умолчанию «Открытие файла» и возможностью выбора любого файла. При нажатии на кнопку «Открытие» полное имя выбранного файла запишется в ячейку «A1». При нажатии на кнопку «Отмена» или кнопку закрытия формы в ячейку «A1» запишется строка «Ложь».

Открытие диалога с заголовком «Выбор файла»:

Range ( "A1" ) = Application . GetOpenFilename ( , , "Выбор файла" )

Открытие диалога выбора файлов с указанием одного фильтра:

Range ( "A1" ) = Application . GetOpenFilename ( "Файлы Excel 97-2003,*.xls" , , "Выбор файла" )

Фильтр в этом коде VBA Excel представляет из себя пару: наименование фильтра и строка из знака подстановки «*» с расширением отбираемых файлов, разделенных «,». В данном случае в открытом диалоге будут видны файлы с расширением «.xls». Таких пар может быть несколько, как в следующем примере.

Открытие диалога выбора файлов с указанием трех фильтров файлов:

( "Файлы Excel 97-2003,*.xls,Текстовые файлы,*.txt,Рисунки,*.jpg" , , "Выбор файла" )

Выбрать один из фильтров можно из раскрывающегося списка диалога выбора файлов «Тип файлов».

Для справки:

Application.GetOpenFilename («Фильтры», номер, «Заголовок диалога»)

Аргумент номер — это номер по порядку фильтра в списке, отображаемого по умолчанию. Если номер отсутствует или превышает количество фильтров, то по умолчанию отображается первый в списке.

Стартовая папка диалога выбора файлов

При открытии стандартного диалога выбора файлов «Application.GetOpenFilename» по умолчанию, как стартовая, выбирается папка «Мои документы» в Windows XP, «Документы» в Windows 8, но, при желании, можно задать, как стартовую, и любую другую папку.

Для этого можно воспользоваться операторами ChDrive (смена текущего диска) и ChDir (смена текущего каталога). По умолчанию текущим является диск «С» в Windows XP, поэтому, если ваша папка находится на этом диске, то ChDrive можно пропустить.

Пример 1
Проверяем, какая папка является стартовой по умолчанию. При вызове процедуры из первого примера диалог откроется именно на этой папке. Если выбрать файл, в ячейку «A1» запишется полный путь к нему, а при отмене выбора, запишется «Ложь».

Часто при работе с файлами и написании кодов начинающие "кодить" в 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

В данном случае совершенно неважно указан ли выбор только одного файла или нескольких. Может поменяться только способ обработки полученного результата. Если параметр 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 - можно будет выбрать только один файл

Атрибут FilterIndex

  • 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 'была нажата кнопка отмены

Пример вызова диалога выбора папки:

Диалог выбора папки через Shell
Диалог Application.FileDialog(msoFileDialogFolderPicker) всем хорош и удобен, кроме одного: как я уже упоминал, он стал доступен из VBA только начиная с 2002 Excel. Поэтому дополню статью еще одним вариантом показа диалога выбора папки - с помощью объекта Shell.
Shell.BrowseForFolder([Hwnd], [sTitle], [iOptions], [vRootFolder])

Hwnd Дескриптор окна, к которому будет относится диалог. Как правило указывается 0
sTitle Поясняющий текст, который будет отображен в диалоге. Подобие заголовка окна. Может быть любым текстом, например "Выбрать папку с отчетами"
iOptions Дополнительные параметры для диалога. Рекомендуется использовать 0. Но можно попробовать и пару других вариантов. Например, если указать 20, то в диалоговом окне появится дополнительное текстовое поле, в котором будет отображено имя выбранной папки.
vRootFolder Аналогично InitialFileName в рассмотренных выше диалогах. Задает начальную папку, на которой диалог будет открыт после запуска.

Диалог выбора папки - Shell


Пример вызова диалога выбора папки через Shell:

Конечно, диалог подобный выглядит довольно убого, особенно на современных операционных системах. Но он работает в любых версиях офиса. Порой это бывает полезней красоты.

Tips_Macro_GetOpenFileFolder.xls (100,0 KiB, 3 345 скачиваний)

Диалог сохранения файла 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 у нас есть различные функции, с помощью которых мы можем открыть любой файл. Мы можем открыть файл, указав путь к файлу в коде VBA, мы даже можем записать этот процесс. Но лучше всего открыть любой файл в VBA с помощью приложения VBA GetOpenFileName . Как следует из названия, это сделано исключительно для приложения при открытии любого файла в VBA.

В других функциях или приложениях, которые работают по тому же принципу, нам может потребоваться скопировать файл файла, разделенный обратной косой чертой, сохраняя имя папки и точные пробелы между обратной косой чертой. Также нам может понадобиться ввести точное имя файла вместе с расширением, которое мы хотим открыть. Но в VBA GetOpenFileName нам просто нужно выбрать файл из местоположения. Это даст окно, из которого мы можем просмотреть файл, в котором он хранится, и расширение файла также будет исправлено.

Синтаксис GetOpenFilename в VBA

Давайте посмотрим ниже формулу для GetOpenFilename в Excel VBA.


Ниже приведен аргумент приложения VBA GetOpenFileName.

  • FileFilter - здесь мы можем определить, какой тип файла мы хотим видеть. Например, если мы упомянем «Файлы Excel, *. Xlsx», он найдет и покажет все файлы Excel в формате .xlsx. Если мы упомянем «PDF-файлы, *. Pdf», то он найдет и покажет только все pdf-файлы.
  • FilterIndex - этим мы можем разрешить пользователю ограничивать выбор типа файла. Мы можем указать количество файлов, которые нам нужно показать.
  • Заголовок - показывает выбранный файл в заголовке диалогового окна.
  • ButtonText - это только для пользователей MacBook.
  • MultiSelect - если мы выберем несколько файлов, тогда это будет ИСТИНА, иначе это будет ЛОЖЬ, которая в любом случае является значением по умолчанию.

Как открыть файл с помощью GetOpenFileName в Excel VBA?

Ниже приведены различные примеры открытия файла с помощью приложения GetOpenFileName в Excel VBA.

Вы можете скачать этот шаблон Excel VBA GetOpenFileName здесь - Шаблон Excel VBA GetOpenFileName

Excel VBA GetOpenFileName - Пример № 1

В этом примере мы увидим, как сначала открыть файл Excel. Выполните следующие шаги, чтобы использовать GetOpenFileName в Excel VBA:

Шаг 1: Перейдите в меню «Вставка» и нажмите «Модуль», чтобы открыть его.


Шаг 2: Напишите подкатегорию VBA Getopenfilename или выберите любое другое имя в соответствии с вашим выбором, чтобы определить Подкатегорию.

Код:


Шаг 3: Теперь определите переменную и присвойте ей строку, как показано ниже. Выбор строки, потому что мы будем выбирать или выбирать имя файла.

Код:


Шаг 4: Теперь в определенной переменной A используйте Application, как показано ниже.


Шаг 5: Теперь выполните поиск и выберите GetOpenFileName из активированного списка приложений, как показано ниже.


Шаг 6: Теперь используйте MsgBox, чтобы получить местоположение выбранного файла.

Код:


Шаг 7: Теперь скомпилируйте код, нажав функциональную клавишу F5, и запустите его, нажав кнопку Play. Теперь просмотрите файл, который мы хотим выбрать. Здесь мы пошли по пути и выбрали файл Excel с именем Test File, который обычно находится в формате .xlsx . Нажмите на Открыть.



Шаг 8: Теперь по синтаксису мы будем использовать Filefilter в скобках приложения GetOpenFilename. Как мы знаем, он предназначен для выбора типа файла, который мы хотим открыть. Поэтому мы поместим для этого «Файлы Excel», как показано ниже.

Код:


Шаг 9: Теперь добавьте расширение файла Excel, которое мы выбрали ранее. Это был « .xlsx », поэтому мы будем хранить его и в FileFilter.

Код:


Шаг 10: Теперь мы снова запустим полный код. В папке обзора мы получим только файлы Excel, которые доступны в той папке, которую мы просматривали ранее.


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


Excel VBA GetOpenFileName - Пример № 2

Таким же образом мы видим открытое имя файла с расширением « .pdf ». Выполните следующие шаги, чтобы использовать GetOpenFileName в Excel VBA:

Шаг 1: Теперь снова напишите код, который мы видели в примере 1.

Код:


Шаг 2: Он перенесет нас в то же окно или же перейдет в ту же папку. Теперь выберите любой из файлов PDF и нажмите «Открыть».


Это даст нам путь к выбранному файлу.


Шаг 3: Теперь, чтобы получить выбранный файл PDF, в синтаксисе FileFilter напишите «Файлы PDF» вместо «Файлы Excel» и выберите расширение PDF, которое « .pdf », как показано ниже.

Код:


Шаг 4: Снова скомпилируйте код и запустите его. Мы получим папку браузера для открытия файлов. При этом мы получим только файлы с расширением « .pdf », как показано ниже.


И если попытаться отфильтровать другие форматы файлов, то это снова позволит нам видеть только файлы PDF, как показано ниже.



Плюсы Excel VBA GetOpenFileName

  • VBA GetOpenFileName помогает нам напрямую открывать файл, не вставляя путь к этому файлу в коде VBA.
  • Нам не нужно менять путь к файлам несколько раз.
  • Просматривать и выбирать файлы так же просто, как перейти в эту папку, чтобы открыть ее.

Минусы Excel VBA GetOpenFileName

  • Нам нужно изменить расширение файла, который мы хотим открыть, если в этом есть изменение.

То, что нужно запомнить

Рекомендуемые статьи

Это руководство по VBA GetOpenFileName. Здесь мы обсудим, как открыть файл с помощью приложения GetOpenFileName в Excel, используя код VBA, а также некоторые практические примеры и загружаемый шаблон Excel. Вы также можете просмотреть наши другие предлагаемые статьи -

Читайте также: