Closing the window

Alapvető fájlműveletek – 3. rész: fájlok bezárása … és ami utána van … vagy előtte

Az első bejegyzés-sorozat záró részeként eredetileg a fájlok lezárásáról terveztem írni. Természetesen ez nem marad el, azonban a fájlbezárás önmagában nem egy bonyolult és érdekfeszítő téma. Ellenben vannak műveletek, amiket tipikusan bezárás előtt szoktunk megejteni, így ezekről is szó lesz a mai bejegyzésben. Másrészt az Excel fájlok élete általában nem ér véget azzal, hogy mi bezárjuk őket. Valaki más megnézi, ellenőrzi, dolgozik vele vagy adatokat használ fel belőle; az illetőt mi értesítjük, hogy elkészültünk, esetleg továbbküldjük neki a fájlt. A munkafolyamatok (workflow-k) automatizálása megér egy külön bejegyzést – ha nem többet –, de a fájlok bezárása kapcsán szeretnék felvillantani néhány további érdekességet is.

Fájlok bezárása

Egy Excel munkafüzetet bezárni  a Workbook objektumon végzett Close metódussal tudunk. Például:

ThisWorkbook.Close                'a makrót tartalmazó munkafüzetet zárja be
ActiveWorkbook.Close              'az aktív munkafüzetet zárja be
Workbooks(Workbooks.Count).Close  'a legutoljára megnyitott munkafüzetet zárja be
Workbooks(“Minta.xlsx”).Close     'a "Minta.xlsx" nevű munkafüzetet zárja be

Amennyiben nem adunk meg a parancshoz semmilyen paramétert, akkor az eredmény hasonló lesz, mintha menüből vagy ikonnal kezdeményeztük volna a fájl bezárását: ha előzőleg elmentettük a munkafüzetet, akkor simán bezáródik, ha pedig még nem mentettük vagy módosítottunk a legutóbbi mentés óta, akkor az Excel rákérdez, hogy kívánjuk-e előbb menteni a fájlt.

Lássuk tehát, milyen paraméterek megadására van lehetőségünk. Az egyik lehetséges argumentum a SaveChanges, amivel hasonló eredményt lehet elérni, mint az előző bejegyzésemben említett Save metódussal: létező fájl esetén az Excel bezárás előtt elmenti a munkafüzetet, új fájl esetén pedig rákérdez, hogy milyen néven mentse. Amennyiben el szeretnénk kerülni, hogy ez utóbbi rákérdezéssel megakassza a folyamatot, lehetőségünk van a Filename argumentummal a fájl nevét is előre meghatároznunk. Például egy új fájl esetén így néz ki az utasítás:

ActiveWorkbook.Close _
    SaveChanges:=True, _
    Filename:="C:/Users/Felhasznalonev/Documents/Fajlnev.xlsx"

Egy munkafüzet mentés nélküli bezárása nem csak a SaveChanges attribútum False-ra állításával lehetséges. Ugyanezt érhetjük el, ha a munkafüzet Saved tulajdonságát True-ra állítjuk, majd ezután bezárjuk a munkafüzetet:

ActiveWorkbook.Saved = True
ActiveWorkbook.Close

Amikor elmentünk egy munkafüzetet, a Saved tulajdonság magától True-ra változik, viszont ha bármit is módosítunk benne, az ismét False értéket vesz fel. Ebbe a tulajdonságba tudunk a fenti utasítással belenyúlni, ami után ha bármilyen esemény vagy utasítás azt vizsgálná, hogy történt-e változás az utolsó mentés óta, akkor azt a “választ” kapja, hogy nem történt (egészen addig, amíg nem módosítunk ismét a munkafüzeten).

Ami bezárás előtt érdekes lehet…

A teljesség igénye nélkül, a következőkben összegyűjtöttünk néhány eljárást és tulajdonságot, amit a fájl bezárása előtt érdemes lehet beállítani.

Írásvédelem

Ha a véletlen módosítás ellen védeni szeretnénk a fájlunkat, érdemes lehet azt írásvédetté tenni.

Az egyik – legkézenfekvőbb – módszerről a mentésről szóló bejegyzésben már értekeztünk: a SaveAs metódus WriteResPassword paraméterével beállíthatjuk, hogy csak jelszó megadásával lehessen a munkafüzetet módosítani, minden egyéb esetben Read-only módban nyílik meg.

Attributes - Read-only

Egy másik módszer, ha magának a fájlnak az attribútumát változtatjuk Read-only állapotra. Ez esetben a fájl kérdés nélkül csak olvasható módon nyílik meg, viszont a védelem gyengébb az előbbi megoldásnál, hiszen a lenti módszerrel bárki vissza is tudja kapcsolni az írhatóságot.

Ennek kézi beállítása így történik:

Fájlon jobb klikk –> Properties –> a megnyíló ablak General lapjának alján található a Read-only checkbox.

Ugyanezt a hatást a SetAttr függvénnyel lehet automatizálni (ügyeljünk a sorrendre! 1. mentés; 2. írásvédelem; 3. lezárás mentés nélkül):

Sub Irasvedelem ()

dim Munkafuzet     as Workbook
dim MunkafuzetNev  as String
set Munkafuzet = ActiveWorkbook    
    Fajlnev = Munkafuzet.Fullname

    Munkafuzet.Save
    SetAttr MunkafuzetNev, vbReadOnly
    Munkafuzet.Close Savechanges:=False

End Sub

Egy harmadik módszerrel is lehetőségünk van egy fájlt írásvédetté tenni, bár ennek működési logikája kissé eltér a fentiektől. A ChangeFileAccess metódussal írásvédetté tehetjük a munkafüzetet, de csak annak bezárásáig. Ezért ezt a megoldást jellemzően a fájl megnyitásakor szokták alkalmazni, leggyakrabban a Workbook_Open esemény kapcsán, vagyis azon makró részeként, ami a fájl megnyitásakor automatikusan lefut.

A példa kedvéért tegyük fel, hogy a munkafüzetünk megnyitásakor ellenőriztetni szeretnénk, hogy ki nyitja meg a fájlt. Amennyiben mi magunk nyitjuk meg – és ennek ellenőrzésére a Windows felhasználónevet figyeljük –, írási joggal nyíljon meg a fájl, minden egyéb esetben csak olvasási joggal.

Lássuk, ez hogyan programozható le (az eljárást a ThisWorkbook objektummodulba kell beilleszteni):

Sub Workbook_Open ()

Dim Felhasznalonev As String
    Felhasznalonev = Environ("USERNAME")  'aktuális felhasználónév eltárolása

    'felhasználónév megvizsgálása
    Select Case Felhasznalonev

    Case "sajatfelhasznalonev" 'írás-olvasási jog
        'ha éppen read-only, akkor változtatunk, amúgy marad
        If ActiveWorkbook.ReadOnly = True Then
            ActiveWorkbook.ChangeFileAccess Mode:=xlReadWrite
        End If

    Case Else 'csak olvasási jog
        'ha éppen NEM read-only, akkor változtatunk, amúgy marad
        If ActiveWorkbook.ReadOnly = False Then
            ActiveWorkbook.ChangeFileAccess Mode:=xlReadOnly
        End If

    End Select

End Sub

Mark workbook as FinalÍrásvédelmet adhatunk a fájlunknak úgy is, ha a státuszát véglegesre (Final) állítjuk. Ezt megtehetjük menüből a Mark as Final opciót választva, de természetesen automatizálhatjuk is: ennek ki-be kapcsolására szolgál a Workbook.Final tulajdonság. Amikor véglegesre állítunk egy munkafüzetet, több figyelmeztetést is kapunk az Exceltől, ezeket a már ismert Application.DisplayAlerts paranccsal tudjuk kikapcsolni.

Application.DisplayAlerts = False
ActiveWorkbook.Final = True
Application.DisplayAlerts = True
Bezárás előtti események

Amennyiben a munkafüzet bezárása egy hosszabb eljárás része, akkor nincsen gond, hiszen minden, amit a Workbook.Close metódus elé írunk, az végrehajtódik a bezárás előtt. De mi van akkor, ha a fájl bezárása nem egy automata folyamat része, hanem a felhasználó kezdeményezi, viszont mi azt szeretnénk, hogy ez esetben fusson le egy makró – például azért, hogy bizonyos ellenőrzési lépéseket elvégezzen?

Erre szolgál a Workbook_BeforeClose esemény, ami akkor fut le, amikor a felhasználó kezdeményezi a munkafüzet bezárását, és az eseménybe írt program akár meg is szakíthatja a bezárás folyamatát. Itt jegyezném meg, hogy ez a makró NEM fut le automatikusan, ha a munkafüzet bezárását egy másik makrón belüli Workbook.Close metódussal kezdeményeztük. Amennyiben azt szeretnénk, hogy ez esetben is lefusson a makrónk, akkor a Close metódus ELŐTT engedélyeznünk kell az automata esemény lefutását:

With ThisWorkbook
    .RunAutoMacros xlAutoClose
    .Close
End With

Tegyük fel, hogy – például egy havi zárás részeként – a fájlt addig nem engedjük bezárni, amíg az első lapon az A1-es cellában lévő dátumot nem frissítette a felhasználó a folyó hónapot megelőző hónap utolsó napjára.

Private Sub Workbook_BeforeClose(Cancel As Boolean)

Dim FigyeltCella As Range
Set FigyeltCella = ThisWorkbook.Worksheets("Sheet1").Range("A1")

    If FigyeltCella.Value2<>DateSerial(Year(Date), Month(Date), 0) Then
        MsgBox _
            Prompt:="Bezárás nem lehetséges:"&Chr(13)&"A dátum nem lett frissítve!", _
            Buttons:=vbCritical
        Cancel = True
    End If

End Sub

 

… és ami utána következik

Ahogyan a bevezetőben említésre került, az Office lehetőséget kínál arra, hogy az elkészült munkafüzeteink utóéletét is automatizáljuk. Íme néhány érdekesség.

Levélküldés

Ha a munkafüzetet csatolmányként el szeretnénk küldeni valakinek, akkor ennek legegyszerűbb módja a Workbook.SendMail metódus használata. Ennek előnye az egyszerűsége: az alapértelmezett levelezőrendszert használja, így nem kell foglalkozni a levelezőrendszer vezérlésével; hátránya, hogy alig van lehetőségünk a testreszabásra (a levelezőrendszer – például Outlook – közvetlen vezérlésével bármilyen műveletet elvégezhetünk a levelezőrendszeren, amit amúgy manuálisan elvégeznénk). A beállítható paraméterek:

  • Recipients – a címzettek nevét vagy email címeiket adhatjuk meg szöveges formában, több címzett esetében tömbként megadva
  • Subject – a tárgymezőt adhatjuk meg ezzel, ha kihagyjuk, akkor a fájl neve lesz az alapértelmezett
  • ReturnReceipt – olvasási jelentést kérhetünk (alapértelmezett értéke False)
ThisWorkbook.SendMail _
    Recipients:=Array("example1@example.com", "example2@example.com"), _
    Subject:="Ellenőrzésre", _
    ReturnReceipt:=True
Közös munka előkészítése

Azzal bizonyára tisztában van a kedves Olvasó, hogy egy munkafüzet megosztásával (Share Workbook) megnyitjuk annak lehetőségét, hogy egy időben többen is dolgozzanak ugyanazon munkafüzetben. A közös munkafüzet azonban további lehetőségeket is biztosít a közös munkához, akkor is, ha nem dolgozik egyszerre több ember ugyanazon fájlon.

Egy munkafüzet megosztásával megnyílik annak lehetősége, hogy – a Wordhöz hasonlóan – Track Changes-zel nyomon kövessük, hogy ki, mikor, mit módosított a munkafüzeten, illetve lehetőségünk van minden egyes változást külön-külön elfogadni, vagy elvetni. Az ezzel kapcsolatos beállításokat megtehetjük kézzel a Track Changes menüpontban, vagy automatizálhatjuk makró segítségével. Íme a kapcsolódó metódusok és tulajdonságok:

  • MultiUserEditing – Ezzel a tulajdonsággal lekérdezhetjük, hogy a kérdéses munkafüzet meg van-e osztva. A lekérdezést azért érdemes elvégezni, mert a további parancsok hibát eredményeznek, amennyiben egy nem megosztott munkafüzetre próbáljuk meg alkalmazni. Fontos, hogy státuszt csak lekérdezni tudunk vele, módosítani, vagyis nem megosztott munkafüzetet megosztani nem: arra a SaveAs metódus AccesMode paramétere szolgál.
  • AutoUpdateFrequency – Ezzel a tulajdonsággal azt kérdezhetjük le / adhatjuk meg 5 és 1440 közötti intervallumban, hogy az Excel hány percenként frissíti / frissítse a munkafüzetet a többi felhasználó változtatásaival.
  • KeepChangeHistory – Ezzel a tulajdonsággal azt kérdezhetjük le / adhatjuk meg, hogy az Excel tárolja-e a változtatásokat, vagy sem. Gyakorlatilag ezzel ki-be kapcsolhatjuk a Track Changes-t.
  • ChangeHistoryDuration – Ezzel a tulajdonsággal azt kérdezhetjük le / adhatjuk meg, hogy hány napig tárolja az Excel a változtatási előzményeket.
  • Excel Track Changes Highlight Changes on ScreenHighlightChangesOnScreen – Ezzel a tulajdonsággal azt kérdezhetjük le / adhatjuk meg, hogy az Excel a munkalapokon kiemeli / kiemelje-e a módosításokat.
  • HighlightChangesOptions – Ezzel a metódussal azt állíthatjuk be, hogy kinek milyen változtatását szeretnénk látni. Paraméterei:
    • When (mikori változtatások): megadhatunk konkrét dátumot – ebben az esetben az ez utáni változásokat fogjuk eredményül kapni – vagy a következő konstansokat: xlAllChanges (összes), xlSinceMyLastSave (utolsó mentésem óta),  xlNotYetReviewed (Accept/Reject Changes menüpontban még nem ellenőrzött változások)
    • Who (ki általi változtatások): itt megadhatunk konkrét felhasználónevet, vagy a következő konstansokat: “Everyone” (mindenki) “Everyone but Me” (rajtam kívül mindenki)
    • Where (melyik mezők): ezzel Range-ként megadhatjuk a figyelni kívánt mezőket, vagy ki is hagyhatjuk – ez esetben a teljes munkafüzetet figyeli
  • ListChangesOnNewSheet – Ezzel a tulajdonsággal azt kérdezhetjük le / adhatjuk meg, hogy a változtatásokat táblázatos formában egy külön lapon megjeleníti / megjelenítse-e.
  • ShowConflictHistory – Ezzel a tulajdonsággal azt kérdezhetjük le / adhatjuk meg, hogy a párhuzamos változtatások közötti konfliktusokat táblázatos formában egy külön lapon megjeleníti / megjelenítse-e.

A fentiek egy példába összegyúrva:

If ActiveWorkbook.MultiUserEditing = False Then
    Exit Sub
End If
 
With ActiveWorkbook
    .AutoUpdateFrequency = 6
    .HighlightChangesOnScreen = True
    .KeepChangeHistory = True
    .ChangeHistoryDuration = 30
    .HighlightChangesOptions _
        When:=xlAllChanges, _
        Who:="Everyone", _
        Where:="A1:C10"
    .ListChangesOnNewSheet = True
    .ShowConflictHistory = True
 End With

 

2 thoughts on “Alapvető fájlműveletek – 3. rész: fájlok bezárása … és ami utána van … vagy előtte

  1. Google-n keresztül jutottam el az oldalra, és köszönöm a sok hasznos segítséget 🙂

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé.