jak automatycznie otworzyć kolejny plik accessa, po zakończeniu aklualizacji obecnie otwartego.

Odpowiedz Nowy wątek
2019-06-05 10:17
0

Pytanie jak w tytule, a sprawa wygląda następująco. Muszę codziennie aktualizować pliki/bazy access-owe, które ze względu na wielkość są podzielone na kilka plików. Każdy plik musi się aktualizować w odpowiedniej kolejności. Do tej pory mam to ustawione w harmonogramie w godzinach nocnych, kiedy sieć nie jest mocno obciążona i każdy plik ma szytwno ustawioną godzinę. Każdy plik posiada autoexec, który uruchamia makro, utworzone poprzez wybranie akcji z listy, a nie VBA. Dzięki temu forum wiem już, że można takie makro konwertować na VBA, które dla przykładowego pliku wygląda jak poniżej.

Function aktualizacja()
On Error GoTo aktualizacja_Err

    DoCmd.SetWarnings False
    DoCmd.OpenQuery "00_czysci tabela_moje_kody", acViewNormal, acEdit
    DoCmd.OpenQuery "00_aktualizuje tabela_moje_kody", acViewNormal, acEdit
    DoCmd.OpenQuery "00_czysci tabela_sprzed_dzienna_30", acViewNormal, acEdit
    DoCmd.OpenQuery "00_aktualizuje tabela_sprzed_dzienna_30", acViewNormal, acEdit
    DoCmd.OpenQuery "00_tworzy tabela_regulacji_mag_surowe", acViewNormal, acEdit
    DoCmd.OpenQuery "00_czysci tabela_MEA_teraz", acViewNormal, acEdit
    DoCmd.OpenQuery "00_nowe_aktualizuje tabela_MEA_teraz", acViewNormal, acEdit
    DoCmd.OpenQuery "00_czysci tabela_MEA", acViewNormal, acEdit
    DoCmd.OpenQuery "00_nowe_dodaje tabela_MEA_his", acViewNormal, acEdit
    DoCmd.OpenQuery "00_nowe_dodaje tabela_MEA_teraz", acViewNormal, acEdit
    DoCmd.OpenQuery "00_nowe_czysci tabela_sprzed_surowe_teraz", acViewNormal, acEdit
    DoCmd.OpenQuery "00_nowe_aktualizuje tabela_sprzed_surowe_teraz", acViewNormal, acEdit
    DoCmd.OpenQuery "00_nowe_czysci tabela_sprzed_surowe", acViewNormal, acEdit
    DoCmd.OpenQuery "00_nowe_dodaje sprzed_surowe_his", acViewNormal, acEdit
    DoCmd.OpenQuery "00_nowe_dodaje sprzed_surowe_teraz", acViewNormal, acEdit
    DoCmd.SetWarnings True
    DoCmd.Quit acSave

aktualizacja_Exit:
    Exit Function

aktualizacja_Err:
    MsgBox Error$
    Resume aktualizacja_Exit

End Function

Jest sposób na zmodyfikowanie takiego kodu, żeby po zakończeniu aktualizacji otwierał kolejny plik, który powinien być aktualizowany w następnej kolejności?

edytowany 2x, ostatnio: malay, 2019-06-05 10:19

Pozostało 580 znaków

2019-06-05 11:26
1

Użyj zewnętrznego pliku (Acess) powiedzmy nazwijmy go "Scheduler". Tak po krótce w Scheduler robisz funkcję która będzie najpierw sprawdzała status zadania i w zależności od niego będzie odpała kolejną bazę. Czyli będzie działać to na zasadzie:

1) Odpal plik1
2) Plik1 - robi co tam ma robić z autoexec + na koniec jak wszystko poszło wstawia status "Plik1- done" do Schedulera z datą.
3) Odpal plik2
4) Plik2 - autoexec + najpierw sprawdza czy poprzedni plik skończył poprawnie (po statusie) [no chyba, że tego nie potrzebujesz] i odpala resztę zadań
5) Odpal plik3
...

Przykładowy kod w Schedulerze:

Public Function Run()

Dim accessApp

Set accessApp = Nothing
Set accessApp = CreateObject("Access.Application")
accessApp.OpenCurrentDatabase ("D:\Plik1.accdb") 'Odpala Plik1
Set accessApp = Nothing
Set accessApp = CreateObject("Access.Application")
accessApp.OpenCurrentDatabase ("D:\Plik2.accdb") 'odpala Plik 2
Set accessApp = Nothing
Set accessApp = CreateObject("Access.Application")
accessApp.OpenCurrentDatabase ("D:\Plik3.accdb") 'Odpala plik 3
Set accessApp = Nothing

DoCmd.RunCommand acCmdExit
End Function

Pozostało 580 znaków

2019-06-05 11:42
0
BlackBad napisał(a):

Użyj zewnętrznego pliku (Acess) powiedzmy nazwijmy go "Scheduler". Tak po krótce w Scheduler robisz funkcję która będzie najpierw sprawdzała status zadania i w zależności od niego będzie odpała kolejną bazę. Czyli będzie działać to na zasadzie:

1) Odpal plik1
2) Plik1 - robi co tam ma robić z autoexec + na koniec jak wszystko poszło wstawia status "Plik1- done" do Schedulera z datą.
3) Odpal plik2
4) Plik2 - autoexec + najpierw sprawdza czy poprzedni plik skończył poprawnie (po statusie) [no chyba, że tego nie potrzebujesz] i odpala resztę zadań
5) Odpal plik3
...

Przykładowy kod w Schedulerze:

Public Function Run()

Dim accessApp

Set accessApp = Nothing
Set accessApp = CreateObject("Access.Application")
accessApp.OpenCurrentDatabase ("D:\Plik1.accdb") 'Odpala Plik1
Set accessApp = Nothing
Set accessApp = CreateObject("Access.Application")
accessApp.OpenCurrentDatabase ("D:\Plik2.accdb") 'odpala Plik 2
Set accessApp = Nothing
Set accessApp = CreateObject("Access.Application")
accessApp.OpenCurrentDatabase ("D:\Plik3.accdb") 'Odpala plik 3
Set accessApp = Nothing

DoCmd.RunCommand acCmdExit
End Function

instrukcja zapisująca raport "done" do pliku powinna być umieszczona w pliku, który kończy działanie i dodatkowo przez DoCmd.SetWarnings True i DoCmd.Quit acSave jak na grafice poniżej

instrukcja.png

edytowany 1x, ostatnio: malay, 2019-06-05 11:45

Pozostało 580 znaków

2019-06-05 12:01
0

np coś takiego (przy założeniu że w bazie Plik1 wcześniej dodałeś Linked table do Schedulera i dodałeś tablice TblLog):

sql = "INSERT INTO TblLog ( LogDate, LogTime, Application ) SELECT Date() AS Expr1, Time() AS Expr3, 'File1 - Done' AS Expr2 FROM TblLog"
DoCmd.RunSQL sql
edytowany 1x, ostatnio: BlackBad, 2019-06-05 12:03

Pozostało 580 znaków

2019-06-05 12:22
1

@BlackBad: ma dobry pomysł, tylko ja bym to zrobił inaczej, nie potrzebujesz otwierać bazy danych by robic/wywoływac na nich zapytania, powiem więcej nie musisz do tego używać access'a, wystarczy użyć nieśmiertelego vbcsripta do tego i napisać skrypt:

connStr = "Provider=Microsoft.ACE.OLEDB.12.0; Data Source="
Set objConn = CreateObject("ADODB.Connection")

'AKTUALIZACJA DANYCH W PLIKU #1

plik = "c:\roboczy\baza1.accdb"
'Open Connection
objConn.open connStr & plik

with objConn
    .Execute "00_czysci tabela_moje_kody"
    .Execute "00_aktualizuje tabela_moje_kody"
    .Execute "00_czysci tabela_sprzed_dzienna_30"
    .Execute "00_aktualizuje tabela_sprzed_dzienna_30"
    .Execute "00_tworzy tabela_regulacji_mag_surowe"
    .Execute "00_czysci tabela_MEA_teraz"
    .Execute "00_nowe_aktualizuje tabela_MEA_teraz"
    .Execute "00_czysci tabela_MEA"
    .Execute "00_nowe_dodaje tabela_MEA_his"
    .Execute "00_nowe_dodaje tabela_MEA_teraz"
    .Execute "00_nowe_czysci tabela_sprzed_surowe_teraz"
    .Execute "00_nowe_aktualizuje tabela_sprzed_surowe_teraz"
    .Execute "00_nowe_czysci tabela_sprzed_surowe"
    .Execute "00_nowe_dodaje sprzed_surowe_his"
    .Execute "00_nowe_dodaje sprzed_surowe_teraz"
end with

objConn.Close

'AKTUALIZACJA DANYCH W PLIKU #2

plik = "c:\roboczy\baza2.accdb"
'Open Connection
objConn.open connStr & plik

with objConn
    .Execute "zapytanie do bazy 2"

end with

objConn.Close

'AKTUALIZACJA DANYCH W PLIKU #3

plik = "c:\roboczy\baza3.accdb"
'Open Connection
objConn.open connStr & plik

with objConn
    .Execute "zapytanie do bazy 3"

end with

objConn.Close

Oczywiście może być wymaganae zainstalowanie Microsoft Access Database Engine 2010 Redistributable i wywołanie w odpowiedniej bitowości (takiej jak engine): dla 32 bitów:

%windir%\SysWoW64\wscript.exe c:\roboczy\scheduler.vbs

Pozostało 580 znaków

2019-06-05 12:37
0

Panczo, rozumiem, że kwerendy będą pracowały, ale plik nie zostanie otwarty. Tylko pliki są duże na granicy dostępnych rozmiarów, Przy każdym zamknięciu się kompaktują. czy przy rozwiązaniu ze skryptem, pliki nie będą "puchnąć"?

Pozostało 580 znaków

2019-06-05 13:12
1

Generalnie jezeli pracujesz na granicy rozmiaru to warto przejśc na inny silnik.

Pliki będa puchnąć, ale nic nie stoi na przeszkodzie aby z poziomu vbscriptu zrobić kompktowanie bazy:

connStr = "Provider=Microsoft.ACE.OLEDB.12.0; Data Source="
Set objConn = CreateObject("ADODB.Connection")

'AKTUALIZACJA DANYCH W PLIKU #1

plik = "c:\roboczy\baza1.accdb"
'Open Connection
objConn.open connStr & plik

with objConn
    .Execute "00_czysci tabela_moje_kody"
    .Execute "00_aktualizuje tabela_moje_kody"
    .Execute "00_czysci tabela_sprzed_dzienna_30"
    .Execute "00_aktualizuje tabela_sprzed_dzienna_30"
    .Execute "00_tworzy tabela_regulacji_mag_surowe"
    .Execute "00_czysci tabela_MEA_teraz"
    .Execute "00_nowe_aktualizuje tabela_MEA_teraz"
    .Execute "00_czysci tabela_MEA"
    .Execute "00_nowe_dodaje tabela_MEA_his"
    .Execute "00_nowe_dodaje tabela_MEA_teraz"
    .Execute "00_nowe_czysci tabela_sprzed_surowe_teraz"
    .Execute "00_nowe_aktualizuje tabela_sprzed_surowe_teraz"
    .Execute "00_nowe_czysci tabela_sprzed_surowe"
    .Execute "00_nowe_dodaje sprzed_surowe_his"
    .Execute "00_nowe_dodaje sprzed_surowe_teraz"
end with

objConn.Close
compactACCDB plik
'AKTUALIZACJA DANYCH W PLIKU #2

plik = "c:\roboczy\baza2.accdb"
'Open Connection
objConn.open connStr & plik

with objConn
    .Execute "zapytanie do bazy 2"

end with

objConn.Close
compactACCDB plik
'AKTUALIZACJA DANYCH W PLIKU #3

plik = "c:\roboczy\baza3.accdb"
'Open Connection
objConn.open connStr & plik

with objConn
    .Execute "zapytanie do bazy 3"

end with

objConn.Close
compactACCDB plik

Sub compactACCDB (p)
Dim objFSO
Dim objEngine
Dim strLckFile
Dim strSrcName
Dim strDstName

strLckFile =  Replace(p,".accdb",".laccdb")
strSrcName =  p
strDstName =  Replace(p,".accdb","_compacted.accdb")
strBackup =  Replace(p,".accdb","_backup.accdb")

Set objEngine = CreateObject("DAO.DBEngine.120")

Set objFSO = CreateObject("Scripting.FileSystemObject")
If Not (objFSO.FileExists(strLckFile)) Then
    If (objFSO.FileExists(strBackup)) Then
        objFSO.DeleteFile strBackup
    End If
    If (objFSO.FileExists(strDstName)) Then
        objFSO.DeleteFile strDstName
    End If
    objFSO.CopyFile strSrcName, strBackup

    ''dbVersion120 = 128 
    objEngine.CompactDatabase strSrcName, strDstName, , 128

    objFSO.DeleteFile strSrcName
    objFSO.MoveFile strDstName, strSrcName
End If 'LckFile
end Sub

Na podstawie: https://stackoverflow.com/que[...]ao-dbengine-36-using-vbscript

edytowany 2x, ostatnio: Panczo, 2019-06-05 13:14

Pozostało 580 znaków

2019-06-05 15:15
0

Niestety to będzie trudniejsze niż myślałem. Próby ze skryptem dały błąd jak poniżej. Linia 11 znak 5 zaczyna się od

.Execute "01_czysci tabela_moje_kody"

komunikat_vbs.png

Pozostało 580 znaków

2019-06-05 15:28

Problemem jest spacja w nazwie 01_czysci tabela_moje_kody zmień na 01_czysci_tabela_moje_kody w kodzie i pliku accdb nazwę obiektu

Pozostało 580 znaków

2019-06-05 15:52
0

działa, niestety dzisiaj nie przetestuje całości, dokończę w piątek. Na tą chwilę dziękuję

Pozostało 580 znaków

2019-06-07 15:26
0

rozwiązanie z wykorzystaniem skryptu nie radzi sobie w sytuacji, kiedy uruchamiam kwerendę, która ma utworzyć nową tabelę, a ta tabela już wcześniej była utworzona. Access w takiej sytuacji informuję, że uruchomienie kwerendy spowoduję usuniecie poprzedniej tabeli i czeka na potwierdzenie. Niestety z poziomo skryptu wywala błąd. Jeżeli wcześniej ręcznie usunę tą tabelę to przejdzie bez problemu. Jest sposób na uruchomienie Modułu w którym będę miał kod jak poniżej?

DoCmd.DeleteObject acTable, "02_prognoza_fin"

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0