Access-VBA - Formular aktualisieren

Gast #6473327
Lesenswert?

Hallo Forengemeine,
habe mir unter Access 2000 eine DB gebaut, wo alle Tempwerte meiner 
Sensoren DS18B20 gespeichert werden. Diese werden über ein VBA-Modul aus 
den generierten csv-File eingelesen. Über ein Formular starte ich nun in 
dem Modul den Einlesevorgang. Im Formular wird die Zeilennummer, die 
Datenzeile, und der Fortschritt immer wieder angezeigt. Soweit okay.

Das Problem entsteht, wenn der Bildschirmschoner aktiv wird. Ab dann 
findet keine Aktualisierung im Einlese-Formular mehr statt. Somit weiß 
ich dann nicht mehr, wie weit die Routinen denn schon ist. Der 
Einlesevorgang selbst läuft aber weiter. Und wenn dann fertig, wird auch 
das Formular wieder aktualisiert. Dann steht auch z.B. 'fertig mit 
einlesen'.

Bei einer Datei mit ein paar 100 Zeilen kein Problem. Aber es kommt vor, 
dass ich zig Dateien mit mehreren Tausend Zeilen einlese, und dann würde 
ich schon gerne wissen, wie lange es noch dauert.

Ein Ausschnitt:
           ' den aktuellen Dateinamen im Fenster anzeigen
           Forms!frm_Einlesestatus!Aktuelle_Datei = Dateiname
           DoCmd.RepaintObject

           ' die bereits eingelesenen Dateien aufzählen
           Forms!frm_Einlesestatus!gelesene_Dateien = tmp
           DoCmd.RepaintObject

Funktioniert solange, wie der Bilschirmschoner nicht aktiv wird.
Was vergess ich, damit dies auch nach dem re-aktivieren wieder 
aktualisiert wird?
Gast #6475044
Lesenswert?

Das Problem hat mit den Bildschirmschoner nicht wirklich was zu tun.

Es tritt IMMER auf, wenn die Form den Focus verloren hat, also irgend 
ein anderes Fenster/Programm aktiv ist.

Du kannst es nur Zwingen sich zu aktualisieren wenn der Job in einer 
Schleife läuft.

Unter richtigen VB geht das so.

Lauf = true
do while lauf = true
 i = i + 1
 Textbox1.text = i
 My.Application.DoEvents  '<- Wenn er auf diese Zeile trifft wird die 
Form neu gezeichnet und aktualisiert
loop
Gast #6475312
Lesenswert?

Schlaumaier schrieb:
> Es tritt IMMER auf, wenn die Form den Focus verloren hat, also irgend
> ein anderes Fenster/Programm aktiv ist.

Da wüsste ich jetzt aber nicht, wo der Fokus verloren geht. Es kann dann 
nur sein, dass doch der Bildschirmschoner, wenn er beendet wird, und 
dass dann das Access-Hauptfenster aktiv wird. Also noch bevor mein 
Formular wieder aktualisiert ist. Das ist ja genau die Frage. Ich 
vermute ja dies auch eigentlich. Aber wie stelle ich in meiner 
VBA-Routine fest, das mein Ausgabefenster nicht mehr aktiv ist? um 
darauf zu reagieren.

Ein Auszug, was in dieser Haupschleife stattfindet.
1
    Do While Not EOF(1)
2
       zaehler = zaehler + 1
3
       'Debug.Print zaehler
4
       zeile = ""
5
           
6
       ' den aktuellen Dateinamen im Fenster anzeigen
7
       Forms!frm_Einlesestatus!Zeile_aktuell = zaehler
8
       DoCmd.RepaintObject
9
        'Me.RepaintObject
10
       .....

dies wird alle ms (geschätz] durchlaufen.
irgend was war mit :  'Me.RepaintObject
weshalb ich dieses dann deaktiviert hatte, und dafür DoCmd. genomen 
habe.
Gast #6475381
Lesenswert?

Es reicht auch aus, wenn eine andere Anwendung, Mozilla, Excel, 
sonstiges den Fokus hat, und ich dann wieder zurück gehe auf die 
Anwendung. Dann sehe ich eine schöne Sanduhr, aber mehr nicht. Es 
scheint, das hier das Winwows-Fenster-Handle verloren geht. Ist er dann 
fertig, rückt die gesamte Access-DB mit allen Fenstern 'on Top'. und 
alles ist gut. Nur eben ich weiß nicht wie lange das Einlesen dauert, ob 
er irgendwo hängt, oder ob Schrott eingelesen wird.
Gast #6475441
Lesenswert?

Thomas S. schrieb:
> Da wüsste ich jetzt aber nicht, wo der Fokus verloren geht.

Der Focus (auf dein Programm) geht automatisch verloren, wenn ein 
anderes Prg. in deinen Fall der Bildschirmschoner sich in den 
Vordergrund stellt.

Unter Windows kann nur EIN Fenster aktiv sein. Und das fast immer das 
Fenster was im Vordergrund ist. Ergo dein Bildschirmschoner.

Das hat NIX mit VB(A), Access oder sonst was direkt zu tun. Das ist 
Grundlage der Windows-GDI.

Und unter VB(a) gibt es noch ein 2. Effekt. Nach einiger (kurzen) Zeit 
steht in der Form (schneller wenn sie nicht aktiv ist) "Keine 
Rückmeldung". Das bedeutet nix anderes wie das das Programm keine 
Rückmeldung an die GDI gibt, und die Form (das Fenster) nicht 
aktualisiert ist.

DOEVENTS sagt den Programm, melde dich bei der System-GDI und 
aktualisiere alle Anzeigen.
Gast #6475445
Lesenswert?

Nachtrag :

https://support.microsoft.com/de-de/office/doevents-funktion-7af41eca-88e0-470d-adaf-0b3d4c2575b0

Da ist Doevents erklärt

Zitat :
DoEvents ist für einfache Vorgänge besonders hilfreich, beispielsweise 
um dem Benutzer das Abbrechen eines Prozesses nach dessen Start zu 
ermöglichen (z. B. eine Dateisuche).


Leider hat doevent den Nachteil das das Programm ca. 20% langsamer läuft 
ich schreibe deshalb ein 3 Zeiler der das Prg. nur weniger % langsamer 
laufen lässt.

X = 0
Lauf = true
do while Lauf = true
  x = x +1
  if x > 100 then
    x= 0
    My.Application.DoEvents  '<- Wenn er auf diese Zeile trifft wird die
    Form neu gezeichnet und aktualisiert
  end if
loop

Das bedeutet :
mache 100 x was du machen sollst, und zeichne dann den Bildschirm neu.
Wenn ich die Zahl der Läufe kenne oder relativ genau einschätzen kann, 
teile ich die Zahl durch 100 und machen ein Ablaufbalken, der pro % das 
Prozent übergeben bekommt mit ein Doevents dahinter.

Das sieht dann sogar edel aus.
Gast #6475478
Lesenswert?

Ich habe es dann hier eingebaut
1
               'MsgBox "Datensatz nicht erfasst! "
2
            'End If ' DeviceTb.NoMatch
3
       Else
4
           Einlesefehler = Einlesefehler + 1
5

6
       End If 'laenge > 17 And Mid(zeile, 18, 1) = "," And ...
7
       'DoCmd.RepaintObject
8
       DoEvents
9
    Loop

und es funktioniert. i am so happy

Danke
(Firma: Manfred) #6477805
Lesenswert?

Schlaumaier schrieb:

> Lauf = true
> do while Lauf = true
Lauf = true ist ein bisserl unschön doppelt

do while Lauf 'reicht auch!
do while true 'wenn Variable Lauf nicht benötigt wird

> Das bedeutet :
> mache 100 x was du machen sollst, und zeichne dann den Bildschirm neu.
> Wenn ich die Zahl der Läufe kenne oder relativ genau einschätzen kann,
> teile ich die Zahl durch 100 und machen ein Ablaufbalken, der pro % das
> Prozent übergeben bekommt mit ein Doevents dahinter.
>
> Das sieht dann sogar edel aus.

Selbiges gilt auch für andere Bildschirmausgaben, z.B. Statusbar
Man nimmt einen Counter, der je Schleifendurchlauf erhöht ist und mit
if counter%100=0 then..
   doevents 'in VBA Office generell
   'In Excel z.B. application.statusbar=counter % " Durchläufe.."
end if

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren