Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[vba][excel]Zapis do pliku .xls z atrybutem tylko do odczytu

siwek62 03 Lip 2010 23:31 9649 8
  • #1 03 Lip 2010 23:31
    siwek62
    Poziom 11  

    Witam, Mam bazę danych w excelu, w jednym pliku mam dane z których kożysta makro w innym pliku. Chciałem zabezpieczyć plik z danymi przed wprowadzeniem zmian bezpośrednio przez użytkownika (nie uprawnionego). Jednocześnie makro w drugim pliku powinno mieć możliwość zapisywania zmian w pliku bazy. Z bazy może kożystać kilka osób, każda ma u siebie osobny plik z makrem. Wymyśliłem, że nadam plikowi z bazą atrybut "tylko do odczytu". Wyczytałem w sieci że nie można zmienić atrybutu w pliku który jest otworzony. Jak to rozwiązać, czy faktycznie tak jest?
    Idea jest taka,
    1. Każdy z użytkowników ma u siebie plik z makrem które kożysta ze wspólnej bazy, która domyślnie jest otwierana tylko do odczytu
    2. W momencie gdy zachodzi potrzeba dodania danych do bazy, zmieniany jest atrybut pliku na "do zapisu", następuje zapis danych i powrót do atrybutu "tylko do odczytu"
    3. Dodatkowo jeśli możliewe jest rozwiązanie pkt 1 i 2 to należałoby odświeżyć czyli np. otworzyć ponownie plik bazy aby uaktualnić dane, jeśli np. inny użytkownik w międzyczasie zapisał do bazy jakieś dane po tym jak nasze makro otworzyło plik bazy tylko do odczytu.

    Jak to można zrobić? Może inaczej należałoby podejść do zagadnienia, chętnie skorzystam z podpowiedzi.

    0 8
  • #2 03 Lip 2010 23:56
    marcinj12
    Poziom 40  

    Ja w takich sytuacjach robię bazę danych w Accessie, plik .mdb umieszczam na sieci, a użytkownicy korzystają z arkuszy Excela do pobierania / modyfikowania / zapisywania danych za pomocą zapytań SQL w makrach. Sprawdza się przy kilku użytkownikach, choć nie testowałem tego rozwiązania jeżeli dwie osoby będą chciały naprawdę jednocześnie zmodyfikować ten sam rekord.

    A jeżeli chodzi o inne możliwości to można to zrealizować przez:
    - nadawanie / zdejmowania ochrony arkusza (Sheets(1).Protect / Unprotect),
    - ukrycie arkuszy których użytkownik nie może modyfikować,
    - wpisanie makra w OnActivate arkusza - bazy, które będzie wybierało inną zakładkę uniemożliwiając przejście (łatwe do obejście, nie polecam, ale możliwość jest...)

    0
  • #3 04 Lip 2010 12:14
    siwek62
    Poziom 11  

    Z Accesem jeszcze nie pracowałem, trochę się obawiam, że musiałbym poznawać go od podstaw zanim coś w nim stworzę. Tworzę tą bazę już od dłuższego czasu i chciałbym ją wreszcie skończyć więc wolałbym się ograniczyć tylko do Excela, którego znam jako tako i lubię.
    Jestem skłonny zrezygnować z nadawania plikowi bazy atrybutu tylko do odczytu. W tej chwili próbuje rozwiązać problem następująco:
    Ponieważ makro oprócz zapisywania danych w bazie umożliwia przeglądanie, filtrowanie robienie różnych statystyk i zestawień danych więc domyślnie otwieram bazę w trybie tylko do odczytu:

    Code:
    Set ArkRoboczy = Workbooks.Open(Filename:= _
    
    ("D:\Wspolna_Baza.xls"), ReadOnly:=True)


    Następnie gdy trzeba dopisać dane do bazy, zmieniam tryb dostępu do pliku:
    Code:
    ArkRoboczy.ChangeFileAccess Mode:=xlReadWrite


    Jeżeli w tym samym momencie nikt inny nie zrobił tego samego to wszystko fajnie działa. Może się jednak zdażyć (bardzo niewielkie prawdopodobieństwo bo użytkowników tej bazy nie będzie wielu, ale jednak) że baza będzie w trybie do zapisu. Wtedy dostaję komunikat "Plik w użyciu" powiadom, otwórz Tylko do odczytu, anuluj - wiemy o co chodzi.
    Odpowiedz może być tylko jedna: "anuluj", ale makro musi wiedzieć że taka sytuacja wystąpiła. Próbowałem to rozwiązać obsługą błędów:
    Code:
    On Error GoTo Baza_zajeta
    
    ActiveWorkbook.ChangeFileAccess Mode:=xlReadWrite
    Wpisywanie:
    .............
    Baza_zajeta:
    Set ArkRoboczy = ThisWorkbook
    ArkRoboczy.Activate
    Resume Wpisywanie

    Ale makro nie generuje błędu tylko wyświetla okno komunikatu "Plik w użyciu"
    Jak to rozwiązać?

    0
  • #4 04 Lip 2010 13:49
    marcinj12
    Poziom 40  

    A próbowałeś sprawdzać stan arkusza przed zapisaniem, coś w stylu:

    Code:

    If ArkRoboczy.ReadOnly Then
        MsgBox "Baza ma atrybut tylko do odczytu"
    Else
        MsgBox "Można zapisać do bazy"
    End If

    0
  • #5 04 Lip 2010 14:17
    siwek62
    Poziom 11  

    Właśnie wpadłem na takie rozwiązanie, miałem właśnie prosić o opoinię czy jest to poprawne rozwiązanie:

    Code:
    ActiveWorkbook.ChangeFileAccess Mode:=xlReadWrite, Notify:=False
    

    If ArkRoboczy.ReadOnly = True Then
    Set ArkRoboczy = ThisWorkbook
    ArkRoboczy.Activate
    End If

    Dzięki za zainteresowanie, proszę jeszcze tylko o odpowiedz czy konieczne jest :
    Code:
    Application.DisplayAlerts = False


    no i czy z tym Notify:=False jest ok.

    Dodano po 8 [minuty]:

    Sorry jeszcze jedno (nie wiem jak edytować swojego posta),
    Nie kożystam z MsgBox bo przyjąłem taką idee, że jak nie można zapisać danych do Bazy to są one zapisywane w skoroszycie użytkownika ze znaczkiem że nie zostały zapisane w Bazie i przy najbliższej próbie zapisu jest sprawdzane czy są dane które trzeba przenieś do Bazy i jeśli tak to są przenoszone.

    0
  • #6 04 Lip 2010 15:35
    marcinj12
    Poziom 40  

    Tak też można jak zrobiłeś - najpierw próbujesz zmienić tryb dostępu, Notify:=False sprawia że użytkownik nie jest informowany o ewentualnej porażce.
    Następnie sprawdzasz czy poprzedniemu poleceniu udało się zmienić tryb dostępu.
    W tym przypadku Application.DisplayAlerts = False nie musisz wstawiać, a jeśli już to musiałbyś otoczyć nimi komendę ChangeFileAccess (przed wykonaniem ustawić na false, po wykonaniu - na true), efekt będzie taki sam.

    0
  • #7 04 Lip 2010 17:06
    siwek62
    Poziom 11  

    Dzięki, ale chyba muszę zmienić koncepcję. Jeżeli bowiem inny użytkownik po tym jak ja otworzyłem bazę do odczytu, zapiszę coś do niej, to przy próbie zmiany trybu otrzymuje komunikat że plik bazy został zmieniony bla bla bla.
    Myślę że zrobię tak: przed próbą zapisu, zamknę plik bazy i otworzę ponownie w trybie do zapisu, chyba będzie ok, jak sądzisz?
    Tak kombinuje ponieważ założyłem sobie żeby nie pojawiały się żadne monity wymagające akcji (decyzji) użytkownika. Mam przykre doświadczenia, że każdy taki komunikat powoduje nawoływanie z drugiego końca pokoju "Tomek!!! co teraz, zobacz..." itp Moi koledzy biegli w obsłudze Excela inaczej potrafią dokonać cudów, które trudno mi było sobie nawet wyobrazić. Nie to żebym się z nich naśmiewał, ale chcę żeby ta baza była jak najmniej kłopotliwa z ich punktu widzenia. Każdy jest dobry w tym w czym jest dobry i na siłę nie ma co tego zmieniać.

    0
  • #8 04 Lip 2010 18:19
    marcinj12
    Poziom 40  

    Ja swoje zdanie wyraziłem już w drugim poście :]
    Możesz dalej kombinować jak koń pod górkę z plikiem Excela zamiast skorzystasz z proponowanego sposobu z Accessem - skoro znasz VBA to "opanowanie" podstaw jego obsługi to kwestia 3-4 godzin.
    Oferuję Ci pomoc w tej kwestii - napisz na priva to pokażę Ci jak zaimportować bazę z Excela do Accessa (jedno polecenie), i w jaki sposób ją później odczytywać / zapisywać . modyfikować / usuwać - każde z tych poleceń to kilka linijek kodu.

    Plik Excela to tylko plik - jak go będziesz po kilka razy otwierał, zamykał, zmieniał ustawienia odczytu/zapisu to istnieje ryzyko że w końcu trafisz na sytuację, że coś pójdzie nie tak, komuś się komputer zawiesi kiedy miał otwarty plik, połączenie z siecią zerwie czy ubije plik, coś się namiesza i plik z bazę się zepsuje (miałeś kiedyś komunikat o odzyskiwaniu pliku przy otwarciu??) - mówiąc w skrócie całą Twoją "bazę" szlag trafi... Zastanów się czy warto ryzykować.

    Jeżeli jednak chcesz to robić w Excelu - to kombinuj z Appliaction.DispalyAlerts w miejscach gdzie program coś się pyta użytkownika...

    0
  • #9 04 Lip 2010 19:24
    siwek62
    Poziom 11  

    Dobra, przekonałeś mnie, szczególnie fragmentem o problemach w przypadku zerwania połączenia, co zdaża się u nas kilkanaście razy dziennie. Otwieram Accesa po raz pierwszy.

    0