Juni 15, 2021, 20:56:20

Neuigkeiten:

Ist euer Problem gelöst, dann bitte den Knopf "Thema gelöst" drücken!


Datenerfassung in Access

Begonnen von Marcus Hahn, März 04, 2021, 08:57:37

⏪ vorheriges - nächstes ⏩

Marcus Hahn

Hallo zusammen
Vorweg: ich bin wirklich unerfahren mit Access, deshalb wende ich mich mal an Euch.

Was ich machen möchte:
An einigen vorher festgelegten Tagen (tblProbenabend) finden Übungen statt. Teilnahme der aktiven Mitglieder (tblKontakte) ist freiwillig, muss aber dokumentiert werden.

Wie ich mir das vorstelle: ich wähle den Termin und clicke mich auf einer Seite durch die Mitgliederliste (gefiltert nach "aktive") und clicke "ja".

Nach Ablauf des Jahres brauche ich eine Liste der Aktiven mit der Anzahl der wahrgenommenen Proben.

ich habe viel herumprobiert und gelesen, bin bislang nicht wirklich vorwärtsgekommen, vermutlich weil ich den Lösungsweg nicht verstehe. Kann mir jemand auf die Sprünge helfen?

crystal

Hallo Marcus,

ganz so einfach ist das nicht...

Zunächst Mal brauchst du eine weitere Tabelle tblTeilnahme. Hier müsste gespeichert werden, wer an welchen Proben teilgenommen hat. Diese Tabelle würde also aus folgenden Feldern bestehen müssen:
TNAuto - AutoId
TNProbenRef - Referenz auf tblProbenabend
TNKontaktRef - Referenz auf tblKontakte
TNTeilgenommen - Ja/Nein-Feld, eigentlich überflüssig, könnte aber hilfreich sein, wenn jemand dann doch nicht teilgenommen hat oder früher gegangen ist.

Anm.: diese Tabelle könnte dann auch noch um weitere Felder erweitert werden, z. B. Schulnote, Bemerkung usw.

Aber wie jetzt die Felder befüllen?

Am einfachsten wäre es mit einem Listenfeld und etwas VBA.

Als Datenquelle für das Listenfeld dient die Auswahl der aktiven Kontakte:
select KontaktID, KontaktName from tblKontakte where KontaktStatus = 'aktiv'
Wichtig: Multiselect und erweiterte Auswahl auf Ja stellen.

Nun könntest du dieses ungebundene Listenfeld in einem Formular darstellen und oben ein Feld Probendatum (Referenz auf tblProbenRef) sowie einen Button "Jetzt speichern".

Der Anwender würde also das Formular aufrufen und das ungebundene Probendatum auswählen (Kombobox). Im Listenfeld werden alle aktiven Kontakte angezeigt. Der Anwender kann nun die Teilnehmer markieren. Bei Klicken des Buttons "Jetzt speichern" müsste dann per VBA in tblTeilnahme für jeden markierten Kontakt ein neuer Datensatz angelegt werden, in dem jeweils die Referenz auf die Probe und die Referenz auf den Kontakt gespeichert wird (ggf. auch noch Teilgenommen: Ja).
Die Referenzfelder kann man sich dabei aus einer jeweils 0cm breiten Spalte der Kombobox bzw. des Listenfelds holen (s.o. Feld KontaktID).

Am Ende des Jahres kannst du dann diese Tabelle auswerten (da müsste evtl. noch ein Feld "TNProbenDatum" dazu - oder was im Sinne der Normalisierung besser wäre: du holst das Datum per JOIN aus der Proben-Tabelle.

Nicht ganz einfach für einen Beginner. Mal sehen, vielleicht bastel ich dir ein Beispiel...

Es sei denn, jemand hat eine bessere Idee.

Gruß,
crystal
Wer Fehler in meinen Antworten findet, darf sie behalten, muss sie aber kommentieren. ;-)
Dies ist keineswegs arrogant gemeint, sondern soll nur unterstreichen, dass meine Antworten - natürlich - nicht immer fehlerfrei sind und sein können.
Devise: bitte immer erst selbst probieren!

Aus gesundheitlichen Gründen nur noch selten dabei...

Beaker s.a.

Hallo,
Och, so schwierig ist das nicht.
Anbei ein abstraktes Beispiel. Es müssen nur die Namen der Tabellen
geändert werden (N = Abende, M = Teilnehmer). Die Formulare haben
als Datensatzquelle keine Abfrage sondern direkten Zugriff auf die
jeweilige Tabelle. Muss also auch nur geändert werden (wenn's die
Autokorrektur es nicht macht).
Natürlich müssen auch noch die benötigten Felder angelegt (siehe
"weitere Felder") in den Tabellen, und auf den Formularen eingefügt
werden.
Die einzige Abfrage im Beispiel ist die DS-Herkunft des Listfeldes im
Form "frmEntitaeten_N".
Das Listfeld mit Mehrfachauswahl und der daneben platzierte Button
ermöglichen eine schnelle Erfassung der Teilnehmer zu einem Abend.

gruss ekkehard
--
Beaker s.a., der lieber an seinem eigenen Projekt arbeiten würde/sollte, aber irgendwie immer gerne seinen Senf dazu gibt ;-)
S.M.I².L.E.

crystal

Hallo,
eine sehr schöne Lösung, Ekkehard!

Inzwischen habe ich meine Quick-And-Dirty-Demo auch fertig. Ist vielleicht noch einfacher zu verstehen...

Beim Basteln sind mir noch folgende Dinge eingefallen:
1. Wenn die Listbox Überschriften enthält, ändert sich der Index der selektierten Zeilen. Daher die Korrektur mit dem Feld intOffset.
2a. Man könnte das Formular frmTeilnahmen ja mehrfach aufrufen und weitere Datensätze erzeugen, obwohl die vielleicht schon existieren. Um die Zeilen in qryTeilnahmen dann nicht mehrfach zu finden, habe ich DISTINCT zugefügt.
2b. Alternativ müsste man beim Speichern prüfen, ob ein entsprechender Datensatz schon existiert.
3. qryTeilnahmen kann dann als Abfrage für einen Bericht dienen, der die Anzahlen der Einträge darstellt. Dazu fehlt dann noch ein GROUP BY...
4. Ein Kontakt könnte ja im Laufe des Jahres inaktiv werden. Deshalb wird der Status in qryTeilnahmen nicht geprüft, sondern nur dargestellt.
5. Formulare für die Erfassung von Proben und Kontakten habe ich nicht gebaut. Demo-Daten kann man ja einfach direkt in die Tabellen schreiben.
6. Da Name und Vorname nicht zwingend eindeutig sein müssen, habe ich in qryTeilnahmen die KontaktId zugefügt. Ein anderes Unterscheidungs-Merkmal könnte z. B. das Geburtsdatum sein.
7. qryTeilnahmen müsste um die Eingabe des gewünschten Jahres erweitert werden...

Verbesserungen sind durchaus erwünscht!

Viel Spaß,
crystal
Wer Fehler in meinen Antworten findet, darf sie behalten, muss sie aber kommentieren. ;-)
Dies ist keineswegs arrogant gemeint, sondern soll nur unterstreichen, dass meine Antworten - natürlich - nicht immer fehlerfrei sind und sein können.
Devise: bitte immer erst selbst probieren!

Aus gesundheitlichen Gründen nur noch selten dabei...

Marcus Hahn

Erstmal vielen Dank für die Mühe.
Ich habe echt Mühe, das nachzuvollziehen, weil ich die Syntax nicht kenne.
Ich bekomme "Datentypenkonflikte" bei "SELECT [tblKontakte].[Personal-ID], [tblKontakte].[Vorname], [tblKontakte].[Nachname] FROM tblKontakte WHERE tblKontakte.[Abteilung] = 'Aktive'; "
und weiß nicht warum.
Bei mir steht allerdings auch keine Checkbox "ja" sondern der Wert "Aktive" als Abteilungsname den ich filtern möchte, ich hab noch die Jugend- und Altersabteilung in der Mitgliederliste.

Die Datenerfassung hab ich nicht verstanden, muss ich zugeben: wenn ich die Beispieldatei öffne, stehen in dem Formular immer die 3 gleichen Namen. Auch wenn ich noch eine Probe hinzufüge, ist "Ja" bereits eingefügt....
Ich denke ich sollte mal das teilen, was ich bislang gebastelt habe...Sie dürfen in diesem Board keine Dateianhänge sehen.

crystal

März 05, 2021, 10:53:21 #5 Letzte Bearbeitung: März 05, 2021, 11:15:20 von crystal
Hallo Marcus,
dein Fehler liegt darin, dass im Feld "Abteilung" NICHT der Klartext, sondern der betreffende Schlüssel aus der tblAbteilung gespeichert wird (Datenfeld-Typ: Zahl!). Du hast in diesem Feld eine Nachschlage definiert, was man dringend vermeiden sollte!!! Das "Nachschlagen" kannst du an der Oberfläche, also im Formular machen - NIE in der Tabelle selbst!!!

Also müsstest du auch nach dieser Zahl selektieren oder - wenn es denn der Klartext sein soll - tblAbteilung mit einbinden:
Sie dürfen in diesem Board keine Dateianhänge sehen.

Entsprechend auch in der Abfrage des Listenfelds.

Die Datenerfassung hab ich nicht verstanden, muss ich zugeben: wenn ich die Beispieldatei öffne, stehen in dem Formular immer die 3 gleichen Namen. Auch wenn ich noch eine Probe hinzufüge, ist "Ja" bereits eingefügt....

Ist doch klar: es werden im Listenfeld nur die aktiven Leute angezeigt. Das sind ja in meiner Demo-DB genau 3. das "Ja" steht für Aktiv, NICHT für Teilnahme.
Die Teilnahme wird erst  durch den Button "Jetzt speichern" gespeichert und zwar für alle Kontakte, die im Listenfeld markiert werden. das fehlt aber in deinem Formular!
Das Feld "Teilgenommen" in deiner Tabelle tblÜbungsteilnahme kannst du dir sparen. Teilgenommen haben alle kontakte, die für das betr. Probendatum in der Tabelle existieren!

Dein Beziehungsfenster ist falsch, da es einige Verknüpfungen nicht aufweist und Abfragen enthält.

BITTE: verwende in deinen Namen keine Sonderzeichen, auch keine Umlaute, keine Minuszeichen und keine Leerzeichen!!! Dieser Hinweis findet sich allein in diesem Forum gefühlt 2-Tausend mal!
Wer Fehler in meinen Antworten findet, darf sie behalten, muss sie aber kommentieren. ;-)
Dies ist keineswegs arrogant gemeint, sondern soll nur unterstreichen, dass meine Antworten - natürlich - nicht immer fehlerfrei sind und sein können.
Devise: bitte immer erst selbst probieren!

Aus gesundheitlichen Gründen nur noch selten dabei...

Marcus Hahn

Vielen Dank für die flotte Unterstützung - auch wenn ich nicht wirklich sicher bin, ob ich das alles verstanden habe - wie gesagt, ich hab mich ein wenig eingelesen und rumprobiert, aber ich bin halt echt Neuling in Access, bin ja schon stolz, daß da überhaupt was funktioniert. Ich werde die Namen ändern - Daß Bindestriche nicht erlaubt sind und Leerzeichen war mir nicht bewusst, sorry. Ich gelobe Besserung.  :-[  Wenn ich das geändert habe, würde ich mich gerne noch mal melden, wenn ich darf...

crystal

Zitat von: undefinedWenn ich das geändert habe, würde ich mich gerne noch mal melden, wenn ich darf...

Aber immer! Schau dir mal in meiner Demo an, was beim Button "Jetzt speichern" passiert (im Entwurfsmodus auf Ereignis klicken und den Code anschauen).
Wer Fehler in meinen Antworten findet, darf sie behalten, muss sie aber kommentieren. ;-)
Dies ist keineswegs arrogant gemeint, sondern soll nur unterstreichen, dass meine Antworten - natürlich - nicht immer fehlerfrei sind und sein können.
Devise: bitte immer erst selbst probieren!

Aus gesundheitlichen Gründen nur noch selten dabei...

Beaker s.a.

@crystal
Da hast du dich aber nicht sehr angestrengt bei deinem Beispiel.
1. Deine Beziehungen halte ich für fragwürdig. Bei mir gibt es LEFT/RIGHT-Joins
nur in Abfragen.
2. Dem Kombi fehlt der Code zum Navigieren.
3. Dein Listfeld zeigt nur die aktiven Kontakte, schliesst die bereits zugeordneten
aber nicht aus. Da es in tblTeilnahmen auch keinen Mehrfelderindex auf die FKs
gibt, sind doppelte Zuordnungen möglich.
4. Deinen Code zum Speichern in die n:m finde ich ziemlich umständlich. Hast du
es dir bei mir angeschaut. Das ganze Offset-Gedöhns ist doch völlig überflüssig.
Die Auflistung ".ItemsSelected" brauchst du doch nicht über den Zeilenindex durch
zu gehen, die gibt autom. die gebundene Spalte zurück.

gruss ekkehard
--
Beaker s.a., der lieber an seinem eigenen Projekt arbeiten würde/sollte, aber irgendwie immer gerne seinen Senf dazu gibt ;-)
S.M.I².L.E.

crystal

@Beaker s.a.
Ja - du hast Recht. Ist ja auch nur eine Quick-and-dirty-Demo.

zu 1. Was spricht dagegen, die Joins schon im Beziehungsfenster komplett zu definieren? Wieso wird diese Option im Beziehungsfenster angeboten?

zu 2. Was soll das für Code sein? Falls du damit meinst, nach Änderung der Kombobox auf einen anderen DS zu wechseln: ist ja nicht vorgesehen.
Mein Formular ist ungebunden, also quasi nur als eine Eingabehilfe gedacht. Es ist nicht dazu gedacht, einmal getroffene Teilnahmen im Nachhinein zu sichten oder zu ändern. Dabei würden übrigens auch andere Probleme auftauchen (Kontakt gehört inzwischen zu einer anderen Abteilung, neuer Kontakt). Hier war der Threadstarter vielleicht auch etwas zu ungenau in seiner Vorgabe (s. a. Titel: DatenERFASSUNG).

zu 3. Das hatte ich bereits erwähnt (s. Post #3, 2a und b).

zu 4. Ja, aber über .column(x,y) kann eben auch auf andere Spalten der Liste zugreifen; Offset-Gedöns: Macht der Gewohnheit, weil ich öfter ganze Listen betrachten muss und falls irgendwann doch Überschriften dargestellt werden...
Übrigens gehe ich ja genau die .ItemsSelected-Auflistung durch, nicht die ganze Liste.


Wenn man anders vorgehen würde, also zu einer Probe in einem UFo alle "Aktiv"-Kontakte markieren, die teilgenommen haben, müsste man das Ufo erst mit allen "Aktiv"-Kontakten füllen (per VBA) oder sie einzeln per Kombobox selektieren (unhandlich, fehleranfällig), um dann z. B. Häkchen bei "Teilgenommen" setzen. Auch dabei kann es dann zu Schwierigkeiten kommen (wie werden Kontakte hinzugefügt, die erst später eingegeben oder schlicht vergessen wurden; was, wenn sich die "Abteilung" ändert; darf es möglich sein, die Teilnahme nachträglich zu ändern -> Dokumentationspflicht?). Außerdem würde die Tabelle dann für jede Probe auch mit all den "Aktiv"-Kontakten gefüllt werden, die nicht teilgenommen haben.

Ist vielleicht zu viel verlangt, aber du kannst meine Demo natürlich gern korrigieren und erweitern. Dann hätten andere auch was davon.

Gruß,
crystal

ps:
"Wer sich über Kritik ärgert, gibt zu, dass sie verdient war." (Tacitus) Ich freue mich über deine Kritik, behaupte aber nicht, dass sie völlig unberechtigt ist; würde mir nur etwas detailliertere Angaben wünschen.
Wer Fehler in meinen Antworten findet, darf sie behalten, muss sie aber kommentieren. ;-)
Dies ist keineswegs arrogant gemeint, sondern soll nur unterstreichen, dass meine Antworten - natürlich - nicht immer fehlerfrei sind und sein können.
Devise: bitte immer erst selbst probieren!

Aus gesundheitlichen Gründen nur noch selten dabei...

Beaker s.a.

@crystal
zu 1. Datenbanktechnisch kann ich das leider auch nicht erklären, da müsste
ein Profi ran. Ich habe es jedenfalls sonst noch nie gesehen, geschweige denn
selber gemacht. Ich will ja nicht behaupten, dass es nicht vielleicht Fälle gibt,
wo es Sinn macht, - aber hier?

zu 2. O.K., dir ging es nur darum den FK fest zu halten. Ich versuche in meinen
Beispielen möglichst auch schon die einfachsten Funktionalitäten darzustellen.
Dies war allerdings auch nicht auf die Schnelle zusammengeklickt, sondern war
schon "vorbereitet".

zu. 3. Hatte ich nicht mehr im Auge, - ansonsten siehe 2.

zu 4. Andere Spalten brauchst du hier aber nicht. Aber O.K., wenn du das so zu
sagen immer als Vorlage benutzt, wieso nicht.

zum Rest: Wieso UFo? Ein UFo auf Basis der n:m dient hier doch der Anzeige
der Teilnehmer einer ausgewählten Probe, und u.U. der Erfassung einzelner
Teilnehmer, die
Zitaterst später eingegeben oder schlicht vergessen wurden
Ansonsten übernimmt das doch (in "Masse") das Listfeld und der Button.
Wo da jetzt eine "Abteilung" herkommt erschliesst mir nicht.

Wenn in einer Anwendung zwischen "aktiv/inaktiv" unterschieden werden muss,
verwende ich eine gespeicherte Abfrage auf die jeweilige Tabelle und beziehe
mich in allen anderen Abfragen nur auf diese
SELECT * FROM Tabelle WHERE aktiv = True("*" hier erlaubt)

Mich an deinem Beispiel zu vergreifen fehlt mir die Zeit. I.Ü. bin ich der
Meinung, sorry wenn ich das mal so behaupte, die bessere Lösung gezeigt zu
haben.

gruss ekkehard
--
Beaker s.a., der lieber an seinem eigenen Projekt arbeiten würde/sollte, aber irgendwie immer gerne seinen Senf dazu gibt ;-)
S.M.I².L.E.

crystal

@Beaker s.a.
In Marcus' Beispiel steht im Feld Abteilung z. B. "Aktive" als Referenz auf die Tabelle tblAbteilung...
Wie du hatte ich beim Lesen von "Aktiv" zunächst auch an ein J/N-Feld gedacht...

Naja - genaues Lesen bildet nicht nur, sondern kann auch Fehler vermeiden.

Gruß,
crystal
Wer Fehler in meinen Antworten findet, darf sie behalten, muss sie aber kommentieren. ;-)
Dies ist keineswegs arrogant gemeint, sondern soll nur unterstreichen, dass meine Antworten - natürlich - nicht immer fehlerfrei sind und sein können.
Devise: bitte immer erst selbst probieren!

Aus gesundheitlichen Gründen nur noch selten dabei...

ebs17

März 07, 2021, 14:45:48 #12 Letzte Bearbeitung: März 07, 2021, 15:50:17 von ebs17
ZitatWas spricht dagegen, die Joins schon im Beziehungsfenster komplett zu definieren?
Das Beziehungsfelder stellt Beziehungen (=> Relations) dar. Beziehungen sind Datenbankobjekte mit klaren Eigenschaften (=> Primärschlüssel - Fremdschlüssel). Von links/rechts ist da keine Rede.
In der Demo: Sekundärtabelle/Fremdschlüssel LEFT JOIN Primärtabelle/Primärschlüssel - was genau soll damit definiert werden??
Mit Einstellung der referentiellen Integrität, die hier fehlt, aber immer sinnvoll und funktional ist und somit vorhanden sein sollte, greift obige "Einstellung" voll ins Leere. Fremdschlüssel ohne zugehörigen Primärschlüssel - das ist nicht denkbar als Standard.

Ein JOIN (=> Verknüpfung) in einer Abfrage(!) kann Beziehungen nachahmen, was ja oft recht sinnvoll ist. Das, was man per Normalisierung auseinander genommen hat, setzt man dann wieder zur wohlgefälligen "Tabelle" zusammen. Ein JOIN kann aber auch ganz anderes als einen PK und einen FK der gleichen Beziehung verknüpfen. Hier würde die Aufgabenstellung an die Abfrage die Art und Weise einer Verknüpfung bestimmen, da kann auch aus links einfach rechts werden, oder man braucht Schlüsselgleichheit (INNER JOIN). Voreinstellung ist so etwas, dass man den linken Blinker gleich zusätzlich abschaltet/abklemmt, weil man üblicherweise nur nach rechts abbiegt.
Verknüpfungen müssen zudem nicht per JOIN vorgenommen werden, ein Theta-Join findet bspw. in der WHERE-Klausel statt, vieles andere dann auch, was ein JOIN nicht kann.

Die sogenannte Vordefinition macht nur dort etwas Sinn, wo man sich im Abfrageeditor etwas zusammenklickt und da als Vorschläge zu Verknüpfungen vorhandene Beziehungen mit ihrem Kram bekommt. Wer sich also auf diesen Assistenten stützt, sollte den Assistenten fit machen und hoffentlich keine eigenen Überlegungen hinsichtlich Anforderungen haben, sonst müsste man ja doch eigene Gedanken haben und diese umsetzen können.

Es ist also ein wenig mehr zu betrachten als ein paar Striche mit möglicherweise einer Pfeilspitze dran.

Wenn man ein Beispiel oder eine Demo bereitstellt, sollte man nicht solchen Unsinn hineinschreiben. Ein nächster hält das für abschreibenswert und vervielfältigt Unsinn.
Mit freundlichem Glück Auf!

Eberhard

crystal

@ebs17
Einmal abgesehen von der schwer zu akzeptierenden Polemik in deiner Antwort halte ich es nach wie vor für richtig, bereits im Beziehungsfenster Joins komplett zu definieren. Ich halte das schlicht für logisch. In anderen DBMS (SQL-Server, Oracle etc. pp.) macht man das meines Wissens übrigens auch.

Wenn man später Queries mit den schon verknüpften Tabellen erstellt, sind die Joins auch gleich richtig und man braucht sich in der Datenblatt-Ansicht nicht zu wundern.

Und warum sollte man einen erstmalig und nach reiflicher Überlegung als Left definierten Join nachträglich auf Right ändern wollen??? Das macht für mich keinen Sinn, denn man sollte sich m. E. schon genau überlegen, welche "Richtung" ein Join hat. Davon abgesehen könnte man den Join-Typ in einer Abfrage auch noch ändern, vielleicht zu Testzwecken.

Ich finde keine triftigen Argumente, so nicht vorzugehen. Ist nicht gerade das Beziehungsfester ("Datenmodell") dazu gedacht, Beziehungen optisch einleuchtend und einfach darzustellen? Eine Beziehung erst in einer Query richtig zu definieren, führt m. E. nur zur Verwirrung. Eine Query mit Left, eine andere mit Right, eine dritte mit Inner Join - was sollte das denn bringen? Doch wohl nur unerwartete Ergebnisse und schwer zu findende Fehler.

Verzichtet man im Beziehungsfenster auf die korrekte Definition der Joins, ist es nur noch eine optische Darstellung der Tabellen und man sieht lediglich, das gewisse Felder eine PK-FK-Beziehung haben. Ich habe nun wirklich schon viele Datenmodelle fremder Anwendungen gesehen und in aller Regel sind da die Pfeilspitzen oder Buchstaben/Symbole an den richtigen Stellen.

Referenzielle Integrität und Löschweitergabe habe nicht nicht eingestellt, da es sich um eine Demo handelt und man so zu Testzwecken einzelne Datensätze noch löschen oder umdefinieren kann. Auch das halte ich für legitim und mache das meist so, bis meine Anwendung "in Produktion" geht.

Insgesamt ist deine Antwort - wie so oft - eher verwirrend, zu schwammig und führt eher zur Verängstigung und Verunsicherung des Lesers, besonders das unglücklich gewählte Beispiel (vor allem, wenn er Neuling ist). Ich vermisse zudem eindeutige Argumente.

Fazit und Empfehlung: glaube nicht unkritisch alles, was andere so für richtig halten.

Gruß,
crystal
Wer Fehler in meinen Antworten findet, darf sie behalten, muss sie aber kommentieren. ;-)
Dies ist keineswegs arrogant gemeint, sondern soll nur unterstreichen, dass meine Antworten - natürlich - nicht immer fehlerfrei sind und sein können.
Devise: bitte immer erst selbst probieren!

Aus gesundheitlichen Gründen nur noch selten dabei...

ebs17

Zitatglaube nicht unkritisch alles, was andere so für richtig halten
Ja bitte, und zwar in allen Richtungen und bei allen beteiligten Personen.

Über die Beschäftigung mit fachlichen Grundlagen kann man dann auch Glauben per Wissen ersetzen.
Mit freundlichem Glück Auf!

Eberhard