Forum: PC-Programmierung Access-VBA - Formular aktualisieren


von Thomas S. (Gast)


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?

von Manfred S. (Firma: Manfred) (xfred343)


Lesenswert?

Hallo, ein paar Ideen:

1) gib im Formular eine Uhrzeit aus und setz das Timer-Ereignis auf 1 
sec, das sollte vielleicht das Anspringen des Bildschirmschoners 
aufhalten.


2) verwende doEvents im Programm


3) Bildschirmschoner abschalten??

LG

von Schlaumaier (Gast)


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

von Thomas S. (Gast)


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.

von Thomas S. (Gast)


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.

von Schlaumaier (Gast)


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.

von Schlaumaier (Gast)


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.

von Thomas S. (Gast)


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

von Schlaumaier (Gast)


Lesenswert?

Froit mich ;)

von Manfred S. (Firma: Manfred) (xfred343)


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

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.