Office - Word, Excel und Co. 9.753 Themen, 41.598 Beiträge

access 2003 - bestimmte Datensätze zählen

Edgar Rau / 22 Antworten / Baumansicht Nickles

Hallo zusammen,

ich habe 'mal wieder eine Access-Frage:

In einer Datenbank habe ich ein CommandButton, der entweder aktiv oder inaktiv ist. Ich möchte jetzt vom Programm via VBA alle Datensätze zählen,  in denen dieser Command-Button inaktiv ist.

Ich hoffe, es findet sich ein Experte, der mir weiterhelfen kann und sage schon einmal vielen Dank!

Gruß Edgar

Wer brauchen ohne zu gebraucht, braucht brauchen gar nicht zu gebrauchen
bei Antwort benachrichtigen
mawe2 Edgar Rau „access 2003 - bestimmte Datensätze zählen“
Optionen
In einer Datenbank habe ich ein CommandButton

Wo in der Datenbank ist dieser CommandButton?

Ich möchte jetzt vom Programm via VBA alle Datensätze zählen

Zählbare Datensätze stehen z.B. in einer Tabelle. Aber dort gibt es doch keinen CommandButton??? Und warum willst Du mit VBA zählen?

Kannst Du Dein Vorhaben noch ein bisschen genauer beschreiben?

Gruß, mawe2

bei Antwort benachrichtigen
Edgar Rau mawe2 „Wo in der Datenbank ist dieser CommandButton? Zählbare ...“
Optionen

Hallo mawe2,

der CommandButton ist im Formular. Wenn sich eine pdf-Datei in einem bestimmten Ordner befindet, ist dieser aktiv (enabled = true), andernfalls inaktiv (enabled = false).

ich habe im Formular ein Textfeld erstellt und im Code unter Form_Current geschrieben:

if me.name des CmdButton.enabled=false then

me.name des Textfeldes="Nein"

else

me.name des Textfeldes="Ja"

end if

Es wird aber nur "Ja" oder "Nein" vom aktuellen Datensatz ins Textfeld geschrieben (Form_Current).

Wenn ich also das Formular öffne, müsste ich erst alle Datensätze durchgehen damit die Anzahl der vorhandenen "Ja" bzw, "Nein" korrekt ist.

Vielen dank schon 'mal für Dein Interesse

Gruß Edgar

Wer brauchen ohne zu gebraucht, braucht brauchen gar nicht zu gebrauchen
bei Antwort benachrichtigen
mawe2 Edgar Rau „Hallo mawe2, der CommandButton ist im Formular. Wenn sich ...“
Optionen
Es wird aber nur "Ja" oder "Nein" vom aktuellen Datensatz ins Textfeld geschrieben

Und in der Tabelle gibt es ein Feld, das auf die PDF-Datei referenziert?

Könnte man das nicht einfach mit einer Abfrage zählen?

bei Antwort benachrichtigen
Edgar Rau mawe2 „Und in der Tabelle gibt es ein Feld, das auf die PDF-Datei ...“
Optionen

in der Tabelle gibt es lediglich eine Textdatei, in der "Ja" oder "Nein" eingetragen wird, je nach dem ob der CommandButton inaktiv oder aktiv ist. Wenn ich also das Formular öffne und dann auf "nächster Datensatz" drücke und gedrückt halte bis zum letzten Datensatz, sind alle "Ja" oder "Nein" im Textfeld eingetragen und kann dann natürlich berechnet werden, es braucht dafür nicht einmal eine Abfrage: Ich erstelle einen Filter und mit Me.Recordset.RecordCount wird dann die Anzahl der "Nein" ausgegeben.

Das ist aber keine elegante Lösung, zumal die Datenbank nicht für mich, sondern für einen Bekannten, der ein Autohaus hat, ist.

Vielleicht fällt Dir ja noch eine einfachere und elegantere Lösung ein.

 

Gruß Edgar

Wer brauchen ohne zu gebraucht, braucht brauchen gar nicht zu gebrauchen
bei Antwort benachrichtigen
Borlander Edgar Rau „in der Tabelle gibt es lediglich eine Textdatei, in der Ja ...“
Optionen

Per SQL lässt sich das leicht ermitteln:

SELECT COUNT(*) AS Anzahl_Ja FROM tabelle WHERE feld = "Ja";

Grundsätlich würde ich hier dann auch noch drüber nachdenken einen mit dem feld beginnenden Index zu verwenden um einen aufwändigen FullTableScan zu vermeiden. Wobei ich mich auch noch frage warum das ein Textfeld ist und kein BOOLEAN, oder zumindest ENUM. Und kann man das nicht vielleicht auch direkt per CheckBox darstellen? Das wäre IMHO ein besseres Interfacedesign…

Gruß
Borlander

bei Antwort benachrichtigen
Edgar Rau Borlander „Per SQL lässt sich das leicht ermitteln: SELECT COUNT AS ...“
Optionen

Hallo Borlander,

das eigentliche Problem ist nicht die Abfrage des Textfeldes, das kann leicht mit einem Filter realisiert werden. Die Ja oder Nein müssen erst im Textfeld eingetragen werden. Entweder manuell (zu aufwendig) oder eben wie ich es gemacht habe. Automatisch wird es aber nur vom aktuellen DS eingetragen; ich müsste also, wie bereits geschrieben, das Formular öffnen und auf "nächster Datensatz" drücken und  bis zum letzten Datensatz gedrückt halten.

Ich könnte auch ein Kombinationsfeld mit den Werten Ja und Nein nehmen und dann nach Nein filtern. Es gibt mehrere Lösungen.

Das Problem ist der CommandButton, der allerdings schon ein paar Jahre besteht und von den Anwendern auch so genutzt wurde, daran möchte ich eigentlich nichts ändern.

Vielleicht könnte man auch ein Recordset öffnen und die Datensätze automatisch durchlaufen lassen, damit kenne ich mich aber nicht aus.

Vielen Dank jedoch für Dein Interesse.

Gruß Edgar

Wer brauchen ohne zu gebraucht, braucht brauchen gar nicht zu gebrauchen
bei Antwort benachrichtigen
Borlander Edgar Rau „Hallo Borlander, das eigentliche Problem ist nicht die ...“
Optionen
Die Ja oder Nein müssen erst im Textfeld eingetragen werden.

Was hat das aber nun mit dem Zählen von Datensätzen zu tun?

DS

?

ich müsste also, wie bereits geschrieben, das Formular öffnen und auf "nächster Datensatz" drücken und  bis zum letzten Datensatz gedrückt halten.

Das sollte sich doch auch automatisieren lassen.

Wobei mir allerdings nicht klar ist, warum Du nicht einfach über alle Datensätze iterierst und jeweils einmal die Funktion zum Bestimmten des Wertes aufrufst und diesen dann einträgst.

Irgendwo muss der Wert doch herkommen.

Wobei Du bei der beschriebenen Lösung (Datenbank enthält einen Wert, der von externen Umständen abhängt die außerhalb der Kontrolle des Datenbanksystems liegen) grundsätzlich mit dem Risiko von Änderungsanomalien leben musst…

bei Antwort benachrichtigen
Edgar Rau Borlander „Was hat das aber nun mit dem Zählen von Datensätzen zu ...“
Optionen

Hallo Borlander,

ich werde 'mal versuchen Dir den Hintergrund zu schildern.

In der Datenbank, die ich für einen Bekannten vor einigen Jahren erstellt hatte, sind gebrauchte PKWs eingetragen; jeder Datensatz (DS) ein PKW.

Zu jedem DS gehört eine interne Nummer. Wenn ein neuer PKW gekauft wurde, wird er in der Datenbank eingetragen (Hubraum, Kw u.s.w.). Es wird auch eine Durchsicht ausgedruckt, darauf sind sämtliche Daten des PKW und Fehlermöglichkeiten (Ölstand, Licht, Bremse u.s.w.). Diese Durchsicht erhält die Werkstatt und überprüft den PKW anhand dieser Durchsicht. Sämtliche Punkte werden abgehakt und eventuell repariert. Wenn die Durchsicht fertig ist wird sie unterschrieben, eingescannt und als PDF in einem bestimmten Ordner unter der "internen Nummer.pdf" abgespeichert.

Die Datenbank fragt nun bei jedem DS, ob in dem bestimmten Ordner eine Datei mit dem Namen "interneNummer.pdf" existiert. Der CommandButton wird, wenn eine solche Datei existiert, auf "enabled=true" gesetzt, ansonsten "=false".

Ich kann also in der Datenbank sehen, ob der gerade aktuelle PKW bereits von der Werkstatt durchgesehen und eventuell repariert wurde. Ich kann auf den CommandButton klicken wenn er aktiv ist und die PDF-Datei wird aufgerufen. Dies ist sinnvoll, wenn sich ein Kunde für einen PKW interessiert und nach etwaigen Mängel fragt. Dann wird, falls vorhanden, die Durchsicht (PDF-Datei) aufgerufen und der Kunde kann sehen, welche Mängel erkannt und behoben wurden.

Damit nicht die komplette Datenbank durchgeblättert werden muss, um festzustellen, wieviel PKWs noch durchgesehen werden müssen, wäre es hilfreich, wenn diese gefiltert werden könnten.

Ich hoffe, ich konnte es einigermaßen erklären.

Das sollte sich doch auch automatisieren lassen.

Ja, das habe ich schon geschaft.

Gruß Edgar

Wer brauchen ohne zu gebraucht, braucht brauchen gar nicht zu gebrauchen
bei Antwort benachrichtigen
Borlander Edgar Rau „Hallo Borlander, ich werde mal versuchen Dir den Hintergrund ...“
Optionen

Also hast Du nun inzwischen ein entsprechendes gefülltes Feld in der Datenbank oder nicht?

Damit nicht die komplette Datenbank durchgeblättert werden muss, um festzustellen, wieviel PKWs noch durchgesehen werden müssen, wäre es hilfreich, wenn diese gefiltert werden könnten.

Ich würde das wie folgt machen:

  1. DATETIME-Feld (gibt es das in Access?) pruefbericht_timestamp hinzufügen. In diesem wird der Änderungszeitpunkt der Datei hinterlegen sofern diese existiert, sonst NULL.
  2. Funktion  implementieren die zu einem gegebenen Datensatz (die interne Nummer ist vermutlich der Primärschlüssel?) prüft ob die Datei Datei existiert und wenn ja das Feld aus 1 entprechend setzt. Nice2Have: Am besten auch gleich noch die Datei als Schreibgeschützt markieren um späteres Ändern zu verhindern.
  3. Funktion implementieren, die die Funktion aus 2 für alle Datensätze einmal ausführt die im Feld aus 1 den Wert NULL haben. Das sollte relativ schnell gehen - zumindest unter der Voraussetzung, dass die Anzahl der ungeprüften Datensätze nicht beliebig wachsen kann (d.h. jedes Fahrzeug geprüft wird)
  4. Vor jedem Anzeigen eines Datensatzes die Funktion aus 2 aufrufen sofern das Feld auf 1 den Wert NULL hat.
  5. Funktion implementieren die eine Liste der noch durchzuschauenden PKWs ausgibt. Diese sollte zunächst die Funktion aus 3 aufrufen und anschließend alle Datensätze anzeigen die im Feld aus 1 noch NULL stehen haben.
  6. Nice2Have: Funktion zur Konsistenzprüfung implementieren. Für alle Datensätze mit einem nicht-NULL-Wert im Feld aus 1 prüfen ob der Zeitstempel korrekt gesetzt ist.

Gruß
Borlander

bei Antwort benachrichtigen
Edgar Rau Borlander „Also hast Du nun inzwischen ein entsprechendes gefülltes ...“
Optionen
Also hast Du nun inzwischen ein entsprechendes gefülltes Feld in der Datenbank oder nicht?

Ich habe ein gebundenes Textfeld im Formular eingebaut. Bei jedem aktuellen Datensatz (Form_Current) wird bei inaktivem CommanButton der Wert "Nein" geschrieben, bei aktiv "Ja".

Ich habe es jetzt so "gelöst": Bei Klick auf einen neuen Button wird die Datenbank automatisch  durchlaufen (das hast Du ja schon angemerkt). Die Werte werden von allen Datensätzen in die Textdatei geschrieben. danach erfolgt automatisch ein Filter; die datensätze mit "Nein" im Textfeld werden gefiltert und angezeigt.

Das ist zwar keine besonders elegante Lösung aber es funktioniert wenigstens. Vielen Dank jedoch für Dein Interesse und die Denkanstöße.

Gruß Edgar

Wer brauchen ohne zu gebraucht, braucht brauchen gar nicht zu gebrauchen
bei Antwort benachrichtigen
Borlander Edgar Rau „Ich habe ein gebundenes Textfeld im Formular eingebaut. Bei ...“
Optionen
Die Werte werden von allen Datensätzen in die Textdatei geschrieben. danach erfolgt automatisch ein Filter

Warum schreibst Du die erst in eine Datei und filterst danach? Das scheint mir in der Tat recht aufwändig.

Gruß
Borlander

bei Antwort benachrichtigen
Edgar Rau Borlander „Warum schreibst Du die erst in eine Datei und filterst ...“
Optionen

Ich habe bereits im Anfangsposting mitgeteilt:

Ich möchte jetzt vom Programm via VBA alle Datensätze zählen,  in denen dieser Command-Button inaktiv ist.

Da mir dies aber nicht möglich war, lies ich alle Datensätze durchlaufen und bei jedem Datensatz wurde in einem Textfeld "Ja" bei aktivem und "Nein" bei inaktivem Commandbutton geschrieben. Dann konnte ich das Textfeld filtern.

Die Datensätze werden automatisch durchlaufen (ca. 10 sec.), allerdings sieht der Anwender dies auf dem Bildschirm.

Ich habe ein Recordset geöffnet und in einer Schleife bis EOF den Befehl movenext eingebaut, ohne Ergebnis. Dann habe ich statt "movenext" "DoCmd.GoToRecord , , acNext" verwendet und nun werden alle Datensätze durchlaufen, allerdings mit dem Makel, dass der Anwender es sieht.

Gibt es eine Möglichkeit, die Datensätze durchlaufen zu lassen, ohne das es der Anwender sieht oder ist es überhaupt möglich, inaktive Commandbuttons zu zählen bzw. zu filtern?

Gruß Edgar

Wer brauchen ohne zu gebraucht, braucht brauchen gar nicht zu gebrauchen
bei Antwort benachrichtigen
Borlander Edgar Rau „Ich habe bereits im Anfangsposting mitgeteilt: Da mir dies ...“
Optionen

Ich verstehe nur immer noch nicht, warum Du da den Umweg über den Button gehst. Der Button-Status muss doch auch irgendwie gesetzt werden.

Die Datensätze werden automatisch durchlaufen (ca. 10 sec.), allerdings sieht der Anwender dies auf dem Bildschirm.

In Excel würde man dafür Application.ScreenUpdating auf False setzen. In Access scheint das über Application.Echo False zu laufen. Siehe z.B. http://bytes.com/topic/access/answers/648171-disable-screen-update-access und http://www.office-loesung.de/ftopic215491_0_0_asc.php

nun werden alle Datensätze durchlaufen

Nur wenn sichergestellt ist, dass Du beim ersten Datensatz beginnst.

Gruß
Borlander

bei Antwort benachrichtigen
Edgar Rau Borlander „Ich verstehe nur immer noch nicht, warum Du da den Umweg ...“
Optionen
Ich verstehe nur immer noch nicht, warum Du da den Umweg über den Button gehst. Der Button-Status muss doch auch irgendwie gesetzt werden.

Das Ziel war seinerzeit, dem User "mitzuteilen" , ob ein bestimmtes Dokument vorhanden ist. Danach sollte er, falls so ein Dokument vorhanden ist, dieses auch ansehen können. Da bot sich natürlich ein CommandButton an.

Der Button-Status wird gesetzt, wie bereits mehrfach geschrieben, durch:

if me,button.enabled = true then

me.textfeld="Ja"

else

me.textfeld="Nein"

end if

unter Form_Current.

Vor einigen Tagen fragte man mich, ob es möglich sei, sämtliche PKWs, die keine Durchsicht haben, anzuzeigen. Da es sich mir nicht erschloss, wie Datensätze mit inaktivem CommandButton gefiltert werden können, nahm ich diesen Umweg über ein Textfeld; jetzt können diese Datensätze (PKWs) gefiltert werden.

 

In einer Datenbank habe ich ein CommandButton, der entweder aktiv oder inaktiv ist. Ich möchte jetzt vom Programm via VBA alle Datensätze zählen,  in denen dieser Command-Button inaktiv ist.

Das war meine Anfangsfrage; ich vergaß lediglich nach "zählen" noch "filtern" zu schreiben.

 

PS Application.Echo False funtioniert bei mir nicht

     

Nur wenn sichergestellt ist, dass Du beim ersten Datensatz beginnst.

    Selbstverständlich wird beim ersten DS begonnen ("DoCmd.GoToRecord , , acfirst")

 

Gruß Edgar

Wer brauchen ohne zu gebraucht, braucht brauchen gar nicht zu gebrauchen
bei Antwort benachrichtigen
Borlander Edgar Rau „Das Ziel war seinerzeit, dem User mitzuteilen , ob ein ...“
Optionen
Der Button-Status wird gesetzt, wie bereits mehrfach geschrieben, durch:
if me,button.enabled = true then me.textfeld="Ja" else me.textfeld="Nein" end if

Ne. Da wird der Button-Status nur ausgelesen und dem Textfeld in abhängigkeit davon ein Wert zugewiesen. Entscheidend wäre wie der Button-Status gesetzt wird. Das müsste bislang irgendwie davon abhängen ob eine Datei mit ensprechendem Benennungsschema existiert.

bei Antwort benachrichtigen
Edgar Rau Borlander „Ne. Da wird der Button-Status nur ausgelesen und dem ...“
Optionen

OK, im zweitem Posting habe ich geschrieben:

der CommandButton ist im Formular. Wenn sich eine pdf-Datei in einem bestimmten Ordner befindet, ist dieser aktiv (enabled = true), andernfalls inaktiv (enabled = false).

Ich habe mit der FileExists-Methode herausfinden lassen, ob sich eine Durchsicht (PDF-Datei) in einem bestimmten Ordner befindet. Wenn Ja dann enabled=true; ansonsten enabled=false. Ich denke, dadurch wird der Button-Status gesetzt.

Wer brauchen ohne zu gebraucht, braucht brauchen gar nicht zu gebrauchen
bei Antwort benachrichtigen
Borlander Edgar Rau „OK, im zweitem Posting habe ich geschrieben: Ich habe mit ...“
Optionen
Ich habe mit der FileExists-Methode herausfinden lassen, ob sich eine Durchsicht (PDF-Datei) in einem bestimmten Ordner befindet.

Um das auf diesem Wege herauszufinden muss man nun aber nicht das Formular anzeigen lassen. Das wäre das was ich mir oben unter 2 vorstellen würde.

Gruß
Borlander

bei Antwort benachrichtigen
Edgar Rau Borlander „Um das auf diesem Wege herauszufinden muss man nun aber ...“
Optionen

Ja, das scheint natürlich auch zu funktionieren und ist sicherlich eleganter, allerdings kenne ich diese Funktion nicht.

Aber ist meine Methode so schlecht und sollte ersetzt werden?

Ich habe jetzt nur noch ein kleines Problem; der User sieht, wenn er die Anzahl der Durchsichten aktualisiert, den Durchlauf der DS, dies möchte ich gerne verhindern. Mit Application.Echo False funktioniert es leider nicht.

Gruß Edgar

 

Wer brauchen ohne zu gebraucht, braucht brauchen gar nicht zu gebrauchen
bei Antwort benachrichtigen
Borlander Edgar Rau „Ja, das scheint natürlich auch zu funktionieren und ist ...“
Optionen
allerdings kenne ich diese Funktion nicht.

Die steckt aber doch bereits in der Anwendung drin?

Aber ist meine Methode so schlecht und sollte ersetzt werden?

Das ist eine ziemlich wackelige Bastelei und damit leider in guter schlechter Gesellschaft von in der Wildniss zu beobachtenden VBA-Anwendungen :-(

Ich würde mich insbesondere auch nicht drauf verlassen, dass es überhaupt noch funktioniert wenn Du die Anzeige abschaltest.

Zumal der Ansatz (jedes mal alle Datensätze anfassen und für jeden Datensatz ein Dateisystemzugriff) schlecht skaliert. Wenn das ein paar Jahr genutzt wird, dann dauert es irgendwann nicht mehr 10 Sekunden, sondern 10 Minuten. Außerdem ist da da auch nicht möglich einfach mal über die noch ungeprüften Datensätze zu navigieren, oder ohne zusätzlichen Implementierungsaufwand eine Liste der noch zu prüfenden KFZs als Report auszugeben.

Gruß
Borlander

bei Antwort benachrichtigen
Edgar Rau Borlander „Die steckt aber doch bereits in der Anwendung drin? Das ist ...“
Optionen
Das ist eine ziemlich wackelige Bastelei und damit leider in guter schlechter Gesellschaft von in der Wildniss zu beobachtenden VBA-Anwendungen :-(

Ja, da hast Du sicherlich recht, aber meine Kenntnisse in VBA und Access reichen zwar aus, um eine Datenbank mit vielen Funktionen zu erstellen, aber es scheint wirklich nur eine Bastelei zu sein, zumal ich mit vielen "IF THEN ELSE" arbeite.

Ich wäre Dir dankbar, wenn Du mir den obigen 2. Punkt erklären würdest.

Gruß Edgar

Wer brauchen ohne zu gebraucht, braucht brauchen gar nicht zu gebrauchen
bei Antwort benachrichtigen
Borlander Edgar Rau „Ja, da hast Du sicherlich recht, aber meine Kenntnisse in ...“
Optionen
zumal ich mit vielen "IF THEN ELSE" arbeite.

Das ist kein geeignetes Maß für Softwarequalität. Vertzweigungen hast Du immer. Die sind höchstens beim Einsatz von Booleans teilweise recht sperrig, aber u.U. auch wieder besser lesbar. Bastelig sind vor allem Implementierungen die einzig und allein auf der UI basieren und weniger auf einem sauberen Datenmodell.

Ich wäre Dir dankbar, wenn Du mir den obigen 2. Punkt erklären würdest.

Was genau willst Du denn noch wissen? Ich habe zwar eine recht genaue konzeptionelle Vorstellung davon wie man Deinen Anwendungsfall sauber umsetzen kann, zu konkreten Implementierung in Access kann ich spontan allerdings nichts genaueres sagen. Mangels Nutzung von Access müsste ich da die Details auch allesamt nachschlagen.

In Pseudocode würde das ganze halt so aussehen:

#2
function update_pruefbericht($id)
  filename = "pfad/$id.pdf"
  if file_exists(filename) then
    timestamp = file_modifiedtime(filename)
    sql("UPDATE tabelle SET pruefbericht_timestamp = $timestamp WHERE id=$id");
  endif
end;

#3
foreach $id in sql(SELECT id FROM table WHERE pruefbericht_timestamp IS NULL) do
  update_pruefbericht($id)
end;

Gruß
Borlander

bei Antwort benachrichtigen
neanderix Borlander „Per SQL lässt sich das leicht ermitteln: SELECT COUNT AS ...“
Optionen

ACK.

 

Feldtyp Boolean und Checkbox oder Radiobutton-Gruppe wäre hier definitiv die bessere lösung.

Computers are like airconditioners - they stop working properly when you open Windows Ich bin unschuldig, ich habe sie nicht gewählt!
bei Antwort benachrichtigen