Kategorie szkoleń | Egzaminy | Kontakt
  • 3
  • 0
  • 1

Mam kilkanaście plików Excel w lokalizacji sieciowej. Aktualizuję dane przez menedżera tabel połączonych. Wszystko działa prawidłowo do chwili, gdy ktoś w tym samym czasie edytuje plik. Chciałbym pobrać dane z takiego pliku (oczywiście rozumiem, że dostępne będą tylko dane z ostatniego zapisu - ale to mi wystarczy). Stosując znaleziony kawałek kodu:

Dim oApp As Object

Set oApp = CreateObject("Excel.Application")
oApp.Visible = True
oApp.Workbooks.Open ("tu lokalizacja pliku")

Plik aktualnie będący w edycji otwiera się do odczytu. Jak zapisać ten plik w ACC pod określoną nazwą np. tbxPierwszy_zawart?

Każda kolejna aktualizacja nadpisuje istniejącą tabelę.

Windows 10 Pro 64, MSO 2016 Pro 32.

 

Władysław_Wiśniowiecki
  • Zapytał
  • @ Władysław_Wiśniowiecki | 18.07.2017
    • 1
    • 0
    • 2
Komentarze (3)
W zasadzie problem rozwiązałem dodając na początku Echo off . Ale jest jeszcze jeden problem. Jak zapisać tabelę do access aby zachować z excel nagłówki kolumn.
Skomentował : @ Władysław_Wiśniowiecki ,18.07.2017
  • 1
  • 0
  • 2
Nie bardzo rozumiem... Skoro excele masz podłączone jako tabele połączone, to po co chcesz zaciągać coś przez VBA, w dodatku "fizycznie" otwierając pliki?
Skomentował : @ Mirosław_Janiak ,18.07.2017
  • 1
  • 7
  • 1
Ponieważ, jeżeli plik podczas odświeżana jest edytowany przez użytkownika, dostaję komunikat, że Access nie może wykonać akcji, ponieważ plik jest otwarty. Pliki nie są zabezpieczone hasłami. Co ciekawsze takie blokady dostępu nie występują zawsze. Ale jeżeli już jakiś plik się na to "załapie", to dopóki nie przeprowadzę nowego importu nie pozwala na aktualizację z edytowanego pliku. I tak co jakiś czas. Menedżer najpierw prze długi czas kręci, a po minucie w komunikacie jest "Plik jest już otwarty przez innego użytkownika w trybie wyłączności lub trzeba mieć uprawnienia do wyświetlania jego danych.". Gdy plik nie jest edytowany nie ma tego problemu.
Skomentował : @ Władysław_Wiśniowiecki ,18.07.2017
  • 1
  • 0
  • 2

Odpowiedzi (3)

  • 1

Poradziłem sobie sam. Jeżeli komuś może się przydać, to dla moich potrzeb zastosowałem takie rozwiązanie:

Function Imp()
On Error GoTo Imp_Err
Echo off
        DoCmd.DeleteObject acTable, "tbx_Pierwsza"
        DoCmd.TransferSpreadsheet acLink, 10, "tbx_Pierwsza", "X:\Start\Baza_Pierwsza.xlsm", True, "A1:DZ250"
Imp_Exit:
    Exit Function
Imp_Err:
    MsgBox Error$
    Resume Imp_Exit
End Function

Echo off pozwala na otworzenie plików edytowanych przez użytkowników. Działanie procedury dla takich plików zdecydowanie zwalnia. Nie jestem specjalistą, ale podczas kombinowania w TransferSpreadseet po ustawieniu parametru na True, pierwszy importowany wiersz stał się wierszem nagłówkowym. Na moje potrzeby to wystarcza, zwłaszcza, że bazy lokalnych użytkowników mają tylko część wspólnych nagłówków, tak się historycznie przez lata złożyło. W związku z tym, każdy plik importuję i zapisuję osobno i na nich dopiero pracuję.

Jest jeszcze jedna rzecz, pliki edytowane przez użytkowników otwierają się w trybie do odczytu, i nie wiem jak je zamknąć z procedury, więc obecnie zamykam je ręcznie. Byłbym wdzięczny za podpowiedź.

Władysław_Wiśniowiecki
  • Odpowiedział
  • @ Władysław_Wiśniowiecki | 18.07.2017
    • 1
    • 0
    • 2
  • 0

Plik zamkniesz poleceniem:

oApp.Workbooks("Baza_Pierwsza.xlsm").Close

Otwarcie pliku możesz też powiązać z przypisaniem go do zmiennej, a na końcu zamknąć go przy jej pomocy:

Set plik = oApp.Workbooks.Open("X:\Start\Baza_Pierwsza.xlsm")
...
plik.Close

Twoją funkcję można też lekko sparametryzować, żeby obsługiwała różne bazy:

Function Import(nazwa As String)
On Error GoTo Imp_Err

Echo False
        DoCmd.DeleteObject acTable, "tbx_" & nazwa
        DoCmd.TransferSpreadsheet acLink, 10, "tbx_" & nazwa, "X:\Start\Baza_ " & nazwa & ".xlsm", True, "A1:DZ250"

Możesz ją następnie wywołać przez Import "pierwsza", Import "druga" itd. Jest to przydatne, jeśli powtarzasz tę samą akcję na różnych plikach.

 

PS: Uważaj na to Echo off. Przede wszystkim prawidłowa składnia to Echo False (w Twoim przykładzie "off" jest po prostu pustą zmienną, która traktowana jest przy wykonywaniu kodu właśnie jako Fałsz), a po drugie jeśli makro wyłoży się w trakcie wykonywania, to brak odświeżania ekranu może wprowadzić konsternację u mniej zaawansowanego użytkownika bazy.

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

Jak w Imp_Exit: zapiszesz Echo True, to nie będzie problemu. Nawet po błędzie ta opcja pozostanie włączona.

 

Tomasz_Kasprzycki
  • Odpowiedział
  • @ Tomasz_Kasprzycki | 20.07.2017
    • 2
    • 4
    • 8