Żądanie potwierdzenia wykonania operacji

Czasem, przy operacjach potencjalnie niebezpiecznych, np usuwanie i nadpisywanie plików czy usuwanie danych z bazy powinniśmy dodatkowo zażądać potwierdzenia wykonania operacji, aby nie było możliwe przypadkowe jej wykonanie. Idealnym rozwiązaniem tego będzie poniższa funkcja:

Function fnBrakPotwierdzenia(Pytanie As String) As Boolean
    Dim Odp As Long
    Odp = MsgBox(Pytanie, vbYesNo + vbCritical + vbDefaultButton2, "UWAGA!")
    If Odp = vbNo Then fnBrakPotwierdzenia = True
End Function

Jej użycie będzie wyglądało np tak:

Sub Glowna()
    If fnBrakPotwierdzenia("Czy na pewno...?") Then Exit Sub
    'tu wywołanie procedury niebezpiecznej
End Sub

Zabezpieczenia makr, poziomy zabezpieczeń

Na szczęście makrowirusy nie są ostatnio bardzo popularne, ale proszę zawsze uważać, lepiej dmuchać na zimne. Poziom zabezpieczeń ustawiamy z menu – Narzędzia – Makro – Zabezpieczenia.

Nie wolno ustawiać niskiego poziomu zabezpieczeń, ponieważ wtedy każdy uruchomiony plik zawierający makro, będzie mógł je bez pytania uruchomić. W większości przypadków należy użyć średniego poziomu zabezpieczeń, który gwarantuje zadanie pytania czy włączyć makra, przy uruchamianiu pliku. Proszę się dobrze zastanowić przed odpowiedzią na to pytanie!

Nigdy nie należy włączać makr w obcym nieznanym pliku!

Zabezpieczenia wysokie i bardzo wysokie stosujemy tylko gdy mamy wykupiony certyfikat bezpieczeństwa do projektu VBA co się raczej rzadko zdarza

Jak skorzystać z kodu VBA znalezionego w Internecie

Dla początkujących może być to poważny problem. Przede wszystkim trzeba ocenić czy przypadkiem kod nie jest szkodliwy. Na szczęście w przypadku kodu VBA jest to bardzo rzadko spotykane. Po drugie trzeba rozróżnić czy jest to kod do umieszczenia w module publicznym, czy prywatnym module formularza, raportu, skoroszytu czy arkusza.

Moduł publiczny wstawiamy z menu Instert – Module (wcześniej Alt-F11 aby otworzyć edytor VBA). Tu wklejamy funkcje, które mają być dostępne z poziomu funkcji użytkownika w Excelu czy też w każdej kwerendzie, raporcie czy formularzu w Accessie (np wrzucamy tu funkcję Slownie, jeżeli chcemy aby była powszechnie dostępna w całej bazie)

Moduł prywatny zawsze związany jest z jakimś obiektem. Tylko tu możemy umieścić kod automatycznie wykonujący się z powodu zdarzeń generowanych przez użytkownika takich jak otwarcie czy zamknięcie dokumentu, lub kliknięcie w przycisk. Jeżeli widzimy kod bezpośrednio odwołujący się do kontrolek na formularzu, jak np poniższe dwie procedury:

Private Sub UserForm_Initialize()
 
    przyciskUruchom.Enabled = False
    listaFunkcji.AddItem "Funkcja1"
    listaFunkcji.AddItem "Funkcja2"
 
End Sub
 
Private Sub listaFunkcji_Click()
    przyciskUruchom.Enabled = True
End Sub

to znaczy, że aby przetestować taki kod trzeba: po pierwsze trzeba utworzyć formularz, po drugie umieścić na nim pole listy i przycisk a po trzecie odpowiednio je ponazywać (właściwość Name kontrolki). Efektem powyższych procedur jest początkowe wyłączenie przycisku i załadowanie pola listy. Następnie gdy użytkownik kliknie coś na liście, przycisk zostanie włączony.

Tworzenie i użycie własnej zmiennej obiektowej typu Excel.Range

Przykład na tworzenie własnej zmiennej typu Range i posługiwanie się właściwościami obiektu Range, typu Range:

  1. CurrentRegion
  2. Rows(W)
  3. Columns(K)
  4. Cells(W,K)
Sub WlasnaZmiennaRange()
 
    Dim Zakres As Range
    Dim LW As Long, LK As Long
 
    'sprawdzenie, czy aktywna komórka znajduje się
    'w zakresie danych, przy pomocy własnej funkcji logicznej
    If fnBrakZakresu Then Exit Sub
 
    'ustawienie referencji do obiektu
    'na podstawie właściwości "Bieżący obszar" aktywnej komórki
    Set Zakres = ActiveCell.CurrentRegion
 
    'kolorowanie zakresu poprzez własną zmienną
    Zakres.Interior.ColorIndex = 35
 
    'odczyt liczby wierszy i kolumn zakresu
    LW = Zakres.Rows.Count
    LK = Zakres.Columns.Count
 
    'wyświetlenie wartości zmiennych w oknie debuggera
    Debug.Print "lw: " & LW
    Debug.Print "lk: " & LK
 
    'kolorowanie skrajnych wierszy
    Zakres.Rows(1).Interior.ColorIndex = 34
    Zakres.Rows(LW).Interior.ColorIndex = 34
 
    'i kolumn
    Zakres.Columns(1).Interior.ColorIndex = 34
    Zakres.Columns(LK).Interior.ColorIndex = 34
 
    'kolorowanie narożników zakresu
    Zakres.Cells(1, 1).Interior.ColorIndex = 36
    Zakres.Cells(1, LK).Interior.ColorIndex = 36
    Zakres.Cells(LW, 1).Interior.ColorIndex = 36
    Zakres.Cells(LW, LK).Interior.ColorIndex = 36
 
End Sub

Na koniec funkcja logiczna, z której korzysta powyższa procedura:

Function fnBrakZakresu() As Boolean
    If Len(ActiveCell) = 0 Then
        MsgBox "Ustaw się w niepustej komórce zakresu danych!"
        fnBrakZakresu = True
    End If
End Function

Jak generować niepowtarzalne nazwy plików, tabel, arkuszy i innych obiektów

Generując automatycznie raporty w Excelu, dokumenty w Wordzie czy też tabele w Accessie, moglibyśmy niechcący nadpisać poprzednie wersje. Aby tego uniknąć nadamy im niepowtarzalne nazwy. Pomocna tu będzie znakomita funkcja Format(wyrażenie, string_formatujący). Warto poczytać o niej w helpie. Na jej podstawie zbudujemy własną funkcję:

Function fnStempelCzasowy() As String
fnStempelCzasowy = Format(Now(), "_yyyymmdd_hhmmss")
End Function

Jak załadować nazwy kwerend do listy na formularzu

Czasem chcemy aby użytkownik mógł wygodnie wskazać nazwę kwerendy, np aby użyć jej jako parametru metody transport arkusza. Aby poniższy kod zadział:

  • Na formularzu musi znajdować się kontrolka typu Pole listy.
  • Musi się nazywać ListaKwerend.
  • Procedura musi być umieszczona w module formularza.

Procedura zostanie wywołana automatycznie na starcie formularza dzięki wywołaniu jej na zdarzeniu Load formularza. Bardzo podobnie możemy załadować nazwy tabel

Private Sub Form_Load()
    LadujListeKwerend
End Sub
 
Sub LadujListeKwerend()
    Dim db As DAO.Database
    Dim kw As DAO.QueryDef
 
    ListaKwerend.RowSourceType = "Value List"
    ListaKwerend.RowSource = ""
 
    Set db = CurrentDb
    For Each kw In db.QueryDefs
        ListaKwerend.AddItem kw.Name
    Next
 
    Set db = Nothing
    Set kw = Nothing
End Sub

Jak załadować nazwy tabel do listy na formularzu

Czasem chcemy aby użytkownik mógł wygodnie wskazać nazwę tabeli, np aby użyć jej jako parametru metody transport arkusza. Aby poniższy kod zadział:

  • Na formularzu musi znajdować się kontrolka typu Pole listy.
  • Musi się nazywać ListaTabel.
  • Procedura musi być umieszczona w module formularza.

Procedura zostanie wywołana automatycznie na starcie dzięki wywołaniu jej na zdarzeniu Load formularza. Bardzo podobnie możemy załadować nazwy kwerend. Dodatkowo procedura nie wyświetla tabel systemowych (ich nazwy zaczynają się na „MSys”)

Private Sub Form_Load()
    LadujListeTabel
End Sub
 
Sub LadujListeTabel()
    Dim db As DAO.Database
    Dim tb As DAO.TableDef
 
    ListaTabel.RowSourceType = "Value List"
    ListaTabel.RowSource = ""
 
    Set db = CurrentDb
    For Each tb In db.TableDefs
        If Left(tb.Name, 4) <> "MSys" Then
            ListaTabel.AddItem tb.Name
        End If
    Next
 
    Set db = Nothing
    Set tb = Nothing
 
End Sub

Jak bezpiecznie wyłączyć komunikaty ostrzegawcze w Excelu

Z wyłączeniem komunikatów ostrzegawczych nie ma problemu. Jest to właściwość logiczna Excela. Problemem jest fakt, że pozostawienie wyłączonych komunikatów ostrzegawczych jest bardzo niebezpieczne przy późniejszej normalnej pracy użytkownika. Poniżej przykład procedury, gdzie na pewno zawsze nastąpi przywrócenie komunikatów, nawet gdy wystąpi błąd w procedurze. Jest to możliwe przy użyciu poprawnej obsługi błędów.

Private Sub UsunBiezacyArkuszBezOstrzezenia()
 
    On Error GoTo Obsluga
 
    'wyłącz komunikaty ostrzegawcze
    Application.DisplayAlerts = False 
 
    ActiveSheet.Delete
 
Czyszczenie:
    On Error Resume Next
    Application.DisplayAlerts = True 'przywróć komunikaty
    Exit Sub
 
Obsluga:
    MsgBox Err & ". " & Err.Description
    Resume Czyszczenie
 
End Sub

Co to znaczy: Wymaga referencji do Microsoft Office XX Object Library

Oznacza to, że w edytorze VBA należy uruchomić okienko do dodawania referencji do bibliotek obiektowych (Tools – References), znaleźć bibliotekę Microsoft Office XX Object Library (gdzie XX to nr Twojego Office’a, np 14.0) i wstawić przy niej ptaszek

Jak z VBA wywołać okno dialogowe Office do pobrania nazwy foldera od użytkownika

Nie możemy wymagać od użytkownika, aby poprawnie wpisywał nazwy foldera z ręki. Dużo wygodniej będzie mu użyć dobrze znanego mu okna dialogowego do wskazywania folderów. Dodatkowym bonusem jest, że można też wskazać folder właśnie utworzony w tym samym oknie. Bardzo wygodna funkcja…

'wymaga referencji do Microsoft Office XX Object Library
Function WskazFolder(TytulOkna As String, TytulPrzycisku As String) As String
    Dim Okno As FileDialog
    Dim Wybrane As String
    Set Okno = Application.FileDialog(msoFileDialogFolderPicker)
    Okno.Title = TytulOkna
    Okno.ButtonName = TytulPrzycisku
    If Okno.Show = -1 Then
        Wybrane = Okno.SelectedItems(1)
        If Right(Wybrane, 1) <> "\" Then
            WskazFolder = Wybrane & "\"
        Else
            WskazFolder = Wybrane
        End If
    End If
End Function