Kategorie szkoleń | Egzaminy | Kontakt
  • 7
  • 1
  • 1

Cześć.

Mam bazę danych (podzieloną), z której korzysta kilka osób (poprzez pliki klienta). Czasami muszę coś w tabelach zmienić i w związku z tym potrzebuję, aby nikt w tym czasie nie korzystał z bazy. No i jeśli ktoś korzysta, to chciałbym wiedzieć kto, żeby go poprosić o jej zamknięcie. Wszyscy pracujemy w tej samej domenie i login pobieramy poprzez Environ("username").

Czy jest jakaś komenda, która potrafi podać, który z użytkowników korzysta z bazy?

Pozdrawiam.
Tomek.

Tomasz_Kasprzycki
  • Zapytał
  • @ Tomasz_Kasprzycki | 16.06.2017
    • 2
    • 4
    • 8

Odpowiedzi (7)

  • 1

Szukałem kiedyś informacji na ten temat. O ile dobrze pamiętam, nie znalazłem takiej funkcji. Obejściem było stworzenie osobnej tabeli, do której dopisywał się rekord z czasem i loginem w momencie otwarcia i zamknięcia formularza u usera.

 

Mirosław_Janiak
  • Odpowiedział
  • @ Mirosław_Janiak | 16.06.2017
    • 1
    • 7
    • 1
Komentarze
No to chyba faktycznie jedyna szansa, chyba że moderator coś podpowie :)

Dzięki
Skomentował : @ Tomasz_Kasprzycki ,19.06.2017
  • 2
  • 4
  • 8
  • 0

A czy można napisać jakąś funkcję, która by podawała czas przy rozpoczęciu pracy (w momencie otwarcia pliku) oraz w momencie jego zamknięcia?

Bo mam plik z kilkoma formularzami i nie chciałbym, aby w każdym formularzu trzeba było wpisywać akcje przy otwarciu i zamknięciu, tylko żeby pojawiała się data otwarcia i zamknięcia pliku.

Tomasz_Kasprzycki
  • Odpowiedział
  • @ Tomasz_Kasprzycki | 21.06.2017
    • 2
    • 4
    • 8
  • 0

Jako "Źródło rekordów" dla pola z datą możesz ustawić funkcję =Date(), która uzupełni je bieżącą datą. Jeśli zakładasz jednak, że plik będzie otwarty przez kilka dni i potrzebujesz tej pierwotnej, to można pokombinować tak:

1) W jakimkolwiek module (to ważne: musi to być moduł) deklarujesz zmienną publiczną oraz wprowadzasz funkcję zwracającą datę:

Public data_startu As Date

Function data_st()

data_st = data_startu

End Function

2) Do zdarzenia "Form_Open" formularza, który user otwiera jako pierwszy, dodajesz wiersz:

If data_startu = 0 Then data_startu = Date

Zmienna "data_startu" powinna przechowywać datę przypisaną jej przy otwarciu formularza, aż do zamknięcia pliku, możesz pozyskać ją w wybranym polu, wpisując =data_st() jako jego wartość domyślną.

Mirosław_Janiak
  • Odpowiedział
  • @ Mirosław_Janiak | 21.06.2017
    • 1
    • 7
    • 1
  • 0

Tak, ale jak formularz startu jest otwierany kilka razy (bo uruchamia inne formularze, z których użytkownik korzysta), to kilka razy pojawia się data startu.
Chodzi mi o to, czy da się taką funkcję napisać, która nie byłaby "przypięta" do formularza, tylko do aplikacji (pliku klienta).
Ja zastosowałem takie rozwiązanie:

Mam tabelę z polami:

1. PracownikID

2. Od

3. Do

4. OtwartyFormularz

No i w każdym formularzu jest:

Form_open:

Dim rs As ADODB.Recordset

Set rs = New ADODB.Recordset

With rs
    .ActiveConnection = CurrentProject.Connection
    .Source = "tbl_kto_pracuje"
    .LockType = adLockPessimistic
    .CursorType = adOpenDynamic
    .Open
End With

rs.AddNew
rs!PracownikID = Pracownik()
rs!od = Now()
rs!OtwartyFormularz = "1"
rs.Update
rs.Close

Set rs = Nothing




Form_close:

Dim mSQL As String

DoCmd.SetWarnings False
mSQL = "UPDATE tbl_Kto_pracuje SET tbl_Kto_pracuje.Do = Now() " _
& "WHERE tbl_Kto_pracuje.Identyfikator In (SELECT Last(tbl_Kto_pracuje.Identyfikator) AS OstatniOfIdentyfikator " _
& "FROM tbl_Kto_pracuje " _
& "WHERE tbl_Kto_pracuje.PracownikID='" & Pracownik() & "' AND tbl_kto_pracuje.Od IS NOT NULL AND tbl_Kto_pracuje.Do IS NULL)"

DoCmd.RunSQL mSQL


Teoretycznie wiem: kto, kiedy i na jakim formularzu pracuje i jeśli mam rekord, w którym jest wartość w polu OD, a nie ma w polu DO, to znaczy, że ktoś właśnie pracuje.

Wolałbym jednak prostszą metodę: aplikacja włączona lub wyłączona, ale rozumiem, że takiej opcji nie ma.

Tomasz_Kasprzycki
  • Odpowiedział
  • @ Tomasz_Kasprzycki | 22.06.2017
    • 2
    • 4
    • 8
  • 1

1) Polecenie If data_startu = 0 Then data_startu = Date przypisze bieżącą datę tylko wtedy, kiedy zmienna jest równa zeru, czyli w momencie jej inicjacji przy starcie Accessa. Po pierwszym przebiegu jej wartość się zmieni, ergo nie będzie się więcej nadpisywać. :)

2) Świeże odkrycie: jeśli stworzysz makro (ale przez Tworzenie -> Makro, nie chodzi o VBA) i nazwiesz je "autoexec", będzie uruchamiało się przy starcie Accessa. Możesz potem odpalić z niego wszystko czego potrzebujesz, oprócz zdarzenia wyjścia z pliku.

3) Może dobrym rozwiązaniem będzie odpalenie w tle pustego, niewidocznego formularza, do którego zdarzeń Form_Load i Form_Unload przypiszesz swoje skrypty?

Mirosław_Janiak
  • Odpowiedział
  • @ Mirosław_Janiak | 22.06.2017
    • 1
    • 7
    • 1
  • 0

Autoexec to ciekawe rozwiązanie! Na bank się przyda na przyszłość. Teraz pozostanę przy swoim rozwiązaniu, bo daje mi w sumie to co chcę, ale kiedyś wrócę do tematu.

Bo faktycznie w Autoexecu można dać - uruchom funkcję i wpisać datę rozpoczęcia pracy i login pracownika, a trzeba by jeszcze pokombinować jak dodawać datę zakończenia pracy. Nie zawsze zakończenie pracy byłoby w formularzu startowym, więc trzeba by sprawdzać, czy zamykamy aplikację, czy tylko przechodzimy do innego formularza. Ale to już kiedy indziej. :)

Dzięki za pomoc i poradę. :)

Tomasz_Kasprzycki
  • Odpowiedział
  • @ Tomasz_Kasprzycki | 22.06.2017
    • 2
    • 4
    • 8
  • 1

Moje propozycje. :)

1) Zamiast monitować każdy formularz z osobna, może zrób tak, jak pisałem: w Autoexecu otwarcie jednego (pustego), który będzie niewidoczny i odpalony w tle przez całą sesję. Do jego zdarzeń "open" i "unload" (ten powinien odpalić się zawsze przy zamykaniu bazy) wrzuć skrypty logujące.

2) Po co Ci tyle kodu w ADO, skoro wystarczą dwie (i to tylko ze względu na przejrzystość, bo wystarczy jedna) linijki SQL-a? :)

SQL = "insert into tbl_kto_pracuje (PracownikID, od, OtwartyFormularz) VALUES (pracownik(), Now, '1');"

CurrentDb.Execute SQL, dbFailOnError

3) Jeśli już wolisz bawić się recordsetem, to proponuję do tbl_kto_pracuje dodać kolumnę z autonumeracją (np "LP") i wstawić dodatkową linijkę między odświeżeniem, a zamknięciem połączenia, która odczyta wartość autonumeracji ze wstawionego wiersza:

rs.Update
log_row = rs.Fields("LP").Value
rs.Close

 Zadeklaruj log_row jako zmienną globalną (będzie przechowywana przez całą sesję) i odwołaj się do niej w skrypcie zamykającym:

SQL = "UPDATE tbl_kto_pracuje SET do = Now() WHERE (LP=" & log_row & ");"

CurrentDb.Execute SQL, dbFailOnError

Mirosław_Janiak
  • Odpowiedział
  • @ Mirosław_Janiak | 24.06.2017
    • 1
    • 7
    • 1
Komentarze
Dzięki.

Co do 1) to mam złe doświadczenia z sytuacją, w której mam więcej niż 1 aktywny formularz. Nie wiem czemu pojawiają mi się wtedy problemy z przechodzeniem pomiędzy rekordami (za pomocą DoCmd.GoToRecord , , acGoTo, NrRekordu). Ten numer rekordu jest wyliczany z funkcji DFirst.

Co do 2) to tej komendy nie znałem (CurrentDb.Execute) popróbuję :)

3) A trójka - przy aktualnym rozwiązaniu - będzie aktualizować tylko pierwszy rekord (z otwarcia pierwszego formularza) a nie ostatni rekord danego pracownika. To rozwiązanie musiałoby być stosowane tylko przy założeniu, że mam ten pusty, ukryty formularz. Wtedy kolumna "OtwartyFormularz" w tbl_kto_pracuje będzie niepotrzebny, bo nie będzie monitoringu, który formularz jest otwarty. Spoko, ale jak w pkt 1) :)
Skomentował : @ Tomasz_Kasprzycki ,26.06.2017
  • 2
  • 4
  • 8
.Execute działa znakomicie i faktycznie mniej pisania :)
Skomentował : @ Tomasz_Kasprzycki ,26.06.2017
  • 2
  • 4
  • 8