V článku Systémové proměnné a složky jsme si povídali o tom, jak se dobrat speciálních složek operačního systému. Dnes se podíváme na to, jak složky a soubory vybírat prostřednictvím dialogů.
Excel nabízí jakýsi univerzální objekt FileDialog, který v sobě nese čtyři podtypy dialogů – pro výběr složky (Folder Picker), výběr souborů (File Picker), a pro otevření (Open), resp. uložení souboru (SaveAs).
Nejprve si ukážeme výběr složky.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | Sub DialogVyberSlozky() 'víceúčelový dialog, zde pro výběr složky With Application.FileDialog(msoFileDialogFolderPicker) 'titulek, běžně "Procházet" .Title = "Výběr složky" 'výchozí styl zobrazení, zde velké ikony 'Windows 7, 64 bit, nefunkční .InitialView = msoFileDialogViewLargeIcons 'vícenásobný výběr složek nelze použít '.AllowMultiSelect = True 'výchozí zobrazená složka, zde Temp .InitialFileName = Environ("Temp") 'popis tlačítka, běžně "OK" .ButtonName = "Vybrat" 'zobrazení dialogu .Show 'byla vybrána složka? If .SelectedItems.Count > 0 Then 'výpis do okna Immediate Debug.Print .SelectedItems(1) End If End With End Sub |
Na chvilku si odskočíme pro výběr složky do API a tak trochu se vrátíme k tématu systémových složek, abychom si nastavili výchozí složku v dialogu.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | Private Type BROWSEINFO hOwner As Long pidlRoot As Long pszDisplayName As String lpszTitle As String ulFlags As Long lpfn As Long lParam As Long iImage As Long End Type Private Const CSIDL_PERSONAL As Long = &H5 Private Declare Function SHGetPathFromIDList Lib "shell32.dll" Alias _ "SHGetPathFromIDListA" (ByVal pidl As Long, ByVal pszPath As String) As Long Private Declare Function SHBrowseForFolder Lib "shell32.dll" Alias _ "SHBrowseForFolderA" (lpBrowseInfo As BROWSEINFO) As Long Sub TestSlozkaVyber() Dim strSlozka As String strSlozka = GetDirectory() End Sub Function GetDirectory(Optional Msg) As String Dim bInfo As BROWSEINFO Dim path As String Dim r As Long, x As Long, pos As Integer 'výchozí složka 'http://www.garybeene.com/code/visual%20basic252.htm 'zde moje složka Dokumenty bInfo.pidlRoot = CSIDL_PERSONAL 'popisek dialogu If IsMissing(Msg) Then bInfo.lpszTitle = "Výběr složky" Else bInfo.lpszTitle = Msg End If 'typ složky bInfo.ulFlags = &H1 'zobrazení dialogu x = SHBrowseForFolder(bInfo) 'parsování path = Space$(512) r = SHGetPathFromIDList(ByVal x, ByVal path) If r Then pos = InStr(path, Chr$(0)) GetDirectory = Left(path, pos - 1) Else GetDirectory = "" End If End Function |
Ale teď už zpět k objektu FileDialog a možnosti výběru souborů.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | Sub DialogVyberSouboru() Dim i As Integer 'víceúčelový dialog, zde pro výběr souborů With Application.FileDialog(msoFileDialogFilePicker) 'vícenásobný výběr souborů .AllowMultiSelect = True 'výchozí zobrazená složka, zde Temp .InitialFileName = Environ("Temp") 'zobrazení dialogu .Show 'byl vybrán nějaký soubor? If .SelectedItems.Count > 0 Then 'pro každou vybranou položku For i = 1 To .SelectedItems.Count 'výpis do okna Immediate Debug.Print .SelectedItems(i) Next i End If End With End Sub |
Určitě vás bude zajímat také možnost filtrování složky podle přípony souborů.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | Sub DialogVyberSouboruFiltr() Dim i As Integer 'víceúčelový dialog, zde pro výběr souborů With Application.FileDialog(msoFileDialogFilePicker) 'vícenásobný výběr souborů .AllowMultiSelect = True 'výchozí zobrazená složka, zde složka tohoto souboru .InitialFileName = ThisWorkbook.path 'přidání dvou filtrů .Filters.Add "Vybrané typy obrázků", _ "*.gif; *.jpg; *.jpeg; *.bmp; *.png", 1 .Filters.Add "Soubory aplikace Excel", "*.xl*", 2 'výchozí druhý filtr .FilterIndex = 2 'zobrazení dialogu .Show 'byl vybrán nějaký soubor? If .SelectedItems.Count > 0 Then 'alternativně If .Show = -1 then 'pro každou vybranou položku For i = 1 To .SelectedItems.Count 'výpis do okna Immediate Debug.Print .SelectedItems(i) Next i End If End With End Sub |
Ještě se podíváme na třetí podtyp objektu FileDialog. Zatímco předchozí dialogy pouze vracely seznam vybraných položek, tento je otevírá prostřednictvím metody Execute.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | Sub DialogSouborOtevrit() Dim i As Integer 'víceúčelový dialog 'zde pro výběr a otevření souborů 'a to pouze takových, které jsou přidružené 'hostitelské aplikaci, tj. Microsoft Excel! With Application.FileDialog(msoFileDialogOpen) 'vícenásobný výběr souborů .AllowMultiSelect = False 'výchozí zobrazená složka, zde Temp .InitialFileName = ThisWorkbook.path 'zobrazení dialogu .Show 'byl vybrán nějaký soubor? If .SelectedItems.Count > 0 Then 'spuštění (lépe řečeno otevření souboru) .Execute End If End With End Sub |
Jak už napovídá komentář v kódu, není bohužel možné si kupříkladu nastavit filtr na obrázky a čekat, že je metoda Execute spustí v přidruženém grafickém programu. Ostatně podívejte se na filtry tohoto dialogu.
I zde je cítit ze strany Microsoftu schizofrenie, vždyť už dávno existuje jiný způsob…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | Sub DialogSouborOtevritAlternativa() Dim varFName As Variant Dim i As Integer 'metoda GetOpenFilename varFName = _ Application.GetOpenFilename( _ FileFilter:="Soubory aplikace Excel (*.xl*), *.xl*", _ MultiSelect:=True) If IsArray(varFName) Then For i = LBound(varFName) To UBound(varFName) 'otevření sešitů Workbooks.Open (varFName(i)) Next End If End Sub |
Různorodost a změny v dialozích typu Otevřít/Uložit jsou leckdy přínosné (tipy si ukážeme jindy), ale nezřídka i pitomé a neergonomické (viz Excel 2013 a trotlovské proklikávání se k dialogu). Peklo s nimi zažívám ve smyslu kompatibility starších programů, které jednoduše spadnou, i když by jinak fungovali naprosto normálně. Obzvláště se to týká portable aplikací.