Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Arbeitszeiterfassung: Die Fortsetzung (https://www.delphipraxis.net/1404-arbeitszeiterfassung-die-fortsetzung.html)

MrSpock 22. Nov 2002 19:21


Arbeitszeiterfassung: Die Fortsetzung
 
Hallo mwerk,

heute möchte ich ein paar Tipps zum Hauptformular zum Besten geben.

Nachdem das Login steht, weist du, wer sich da angemeldet hat, darum wäre es schön, wenn der Benutzer auch persönlich begrüßt wird. Dazu sage ich später etwas mehr.

Die wichtigste Frage ist erst einmal, wie die Daten beschränkt werden, so dass der Benutzer nur auf seine eigenen Daten zugreifen kann. Dazu sind zwei Vorgehensweisen möglich. Entweder über TTable Objekte und Filter oder über SQL. Ich werde hier einmal den zweiten Ansatz etwas näher erläutern.

Zunächst sollen die Daten des angemeldeten Users geholt werden. Dazu ziehst du ein Tquery Komponente auf das Formular und setzt DataBaseName auf den Alias, der auf deine Tabellen zeigt. Der SQL Eigenschaft weist du folgenden Code zu:

Code:
SELECT * FROM Arbeitszeit WHERE
   PersonalNummer = :Pnr
Das mit dem Parameter kennst du ja schon. Setze seinen Typ auf String.

Die Query habe ich qrySelData genannt. Beim Activieren des Formulars soll dann folgender Code ausgeführt werden:

Delphi-Quellcode:
procedure TForm1.FormActivate(Sender: TObject);
begin
   if Not qrySelData.Active then
   begin
     qrySelData.ParamByName('PNr').AsString := frmLogin.PNr;
     qrySelData.Open;
   end;
   Caption := 'Arbeitszeiterfassung für ' +frmLogin.cbUser.Text;
end;
Jetzt wird der Nutzer schon einmal begrüßt (in der Caption) und seine Daten stehen zur Verfügung.

Sag Bescheid, wenn du so weit bist.

m-werk 23. Nov 2002 18:48

Hi,

Zitat:

Zunächst sollen die Daten des angemeldeten Users geholt werden. Dazu ziehst du ein Tquery Komponente auf das Formular und setzt DataBaseName auf den Alias, der auf deine Tabellen zeigt.
Da entsteht bei mir schon das 1. Problem. Ich habe keine Alias bei meinen Datenbanken angegeben.

Es funktioniert soweit alles da habe die Datenbänke im gleichen Ordner gespeichert, wo auch das Programm ist. (Da ich ja keine Alias habe) Mir wäre aber sehr recht, wenn ich die Datenbänke in einem anderen Ordner habe.

Wie kann ich denn diese nachträglich angeben (sofern ich dass muss)?

Wenn ich eine Alias angebe, soll ich dann für alle DBs eine angeben?

Anstonsten können wir mit dem Programm weitermachen.

MrSpock 24. Nov 2002 17:42

Liste der Anhänge anzeigen (Anzahl: 1)
Hallo mwerk,

zunächst einmal zu der Frage des Alias. Du kannst jederzeit einen Alias anlegen, wenn du die Tabellen gerne in einem anderen Verzeichnis ablegen willst, ist das auch kein Problem. Verschiebe dann alle Dateien mit der Endung .DB und .PX in das neue Verzeichnis. Dann rufst du den Datenbank – Explorer auf und wählst dort Object|Neu akzeptierst „standard Treiber“ mit OK und gibst den neuen Alias einen Namen z.B. AZeit. Unter Definition und dann Pfad wählst du den Pfad zu deinen Daten. Das Ganze speicherst du noch ab und fertig. Du könntest sogar den Programmpfad als Datenpfad benutzen, ist aber nicht zu empfehlen, weil es unübersichtlich wird.

So, wenn das erledigt ist, solltest du eine Tabelle noch einmal umstrukturieren, und zwar die Tabelle Arbeitszeit, die sollte wie folgt nach der Änderung aussehen:

PersonalNummer A 10 * (Schlüssel)
Datum D * (Schlüssel)
Start T
Ende T
Pause S

Nutze am besten die Datenbankoberfläche dazu.

Wenn du soweit bist, sag Bescheid.

Übrigens habe ich schon mal das Hauptformular angehängt, wie es aussehen könnte, nach dem nächsten oder übernächsten Schritt.

Also hau rein.

m-werk 24. Nov 2002 18:35

Hi, ich hab jetzt alles geändert. Auch alle Alias-Adressen hab ich angelegt. (Funktioniert super)

Die Arbeitszeit-DB ist auch schon geändert.

Ich habe mir dein Hauptformular angesehen. So hab ich es mir auch ca. vorgestellt.

Von mir aus kanns jetzt weitergehen......

MrSpock 24. Nov 2002 19:41

Liste der Anhänge anzeigen (Anzahl: 1)
Hallo m-werk,

also gut...

Wie du in dem Bild sehen kannst, benutze ich dort eine Freeware - Kalenderkomponente. Das Tolle an dieser ist, dass man Tage markieren kann. Ich habe z.B. alle Tage, für die bereits eine Eintragung zur Arbeitszeiterfassung stattgefunden haben blau markiert. Außerdem kann man Feiertage markieren, was du ja auch wolltest. Die Kompo ist also für deine Anwendung maßgeschneidert.

Ich habe den Quellcode angehängt.

Installiere mal die Komponente und melde dich, wenn du fertig bist.

MrSpock 25. Nov 2002 20:24

Hallo m-werk,
ich gehe mal davon aus, dass du die Kalenderkomponente installiert hast. Wenn alles glatt gegangen ist, befindet sich die Komponente jetzt in der Rubrik Beispiele.

Jetzt geht es an das Formular:

Zunächst solltest du ein Panel einfügen:
Name: pnlBottom
Align: alBottom

Dazu ein DBGrid:
Align: alClient

Ein MainMenu:
Mit dem Eintrag: Datei | Beenden


Die neue Kalenderkompo kommt auf Panel pnlBottom.
Name: cal
ColHoliday: clGreen
ColMarked: clBlue
GermanDate: True
UseLongDate: True
ShowDate: True
TabOrder: 2

Ein TButton:
Name: btnEingabe
Caption: Eingabe

Ein weiterer Button:
Name: btnPost
Caption: Übernahme

Ein BitBtn:
Kind: bkClose

Eine Query Komponente:
Name: qrySelData
DataBaseName: Dein ALIAS
SQL: SELECT * FROM Arbeitszeit WHERE
PersonalNummer = :Pnr
Params: Pnr: Typ: ftString

Nach Doppelklick auf die Query Komponente kannst du erst alle Fellder hinzufügen und die 3 Felder Start, Ende und Pause in das Formular ziehen.
Namen: dbeStart, dbeEnde, dbePause

Für die Felder PersonalNummer und Datum bitte die Eigenschaft Visible auf False.

Jetzt noch eine DataSource Komponente:
DataSet: qrySelData

Im DBGrid noch:
DataSource: DataSource1
ReadOnly: True

Leider bin ich morgen Abend nicht da, so dass es erst übermorgen weitegehen kann.

m-werk 26. Nov 2002 07:02

Hi MrSpock, danke für die ausführliche beschreibung.

Ich bin leider gestern nicht dazugekommen die Kompo zu installieren. Das ist aber kein problem. werd ich entweder heute oder morgen machen. Ich habe diese Woche noch ein wenig stress, da kann es schon sein, dass ich 2, 3 Tage nicht bei meinem Programm arbeiten kann.

Sobald ich alle deine Schritte habe, melde ich mich wieder

m-werk 27. Nov 2002 17:46

Hi, ich habe jetzt den Kalender installiert, und auch alles so gemacht wie du dannach geschrieben hast.

Ich hab nur ein kleines Problem: Ich finde kenen Panel, wo ich dann den Kalender hineinstelle.

Ich habe den Kalender normal ins programm gestellt. Wo kann ich denn den Panel finden?

Sonst hab ich mal alles. Wie gehts weiter?

MrSpock 27. Nov 2002 19:44

Hallo mwerk,

die Komponente Panel befindet sich auf der Seite "Standard".
Wenn du eine Komponente mal nicht findest, kannst du Ansicht|Komponentenliste anklicken. Dort die Komponente z.B. TPanel eingeben und "Hinzufügen" anklicken.

MrSpock 27. Nov 2002 21:15

Hallo m-werk,

schnell noch ein paar Infos:

Ich habe, wie schon einmal in einem anderen Thread beschrieben, im privat Bereich des Hauptformulars die Variable FirstTime deklariert:

Delphi-Quellcode:
TForm1 = class(TForm)
    ...
  private
   { Private-Deklarationen }
    FirstTime   : Boolean;
    ...
  public
    { Public-Deklarationen }
  end;
Diese wird in FormCreate initialisiert:
Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
begin
  FirstTime := True;
end;
und in FormActivate benutzt:
Delphi-Quellcode:
procedure TForm1.FormActivate(Sender: TObject);
begin
   if FirstTime then
   begin
      FirstTime := False;
      if Not qrySelData.Active then
      begin
         qrySelData.ParamByName('PNr').AsString := frmLogin.PNr;
         qrySelData.Open;
      end;
      Caption := 'Arbeitszeiterfassung für '
                        +frmLogin.cbUser.Text;
      UpdateCalMark;
   end
end;
Hier habe ich eine Procedure UpdateCalMark aufgerufen, die du ebenfalls im Privat Bereich deklarieren solltest. Sie dient dazu, die Tage im Kalender zu markieren, für die bereits ein Eintrag existiert.
Delphi-Quellcode:
procedure TForm1.UpdateCalMark;
var
   jahr, monat, tag : Word;
   merken   : TBookmark;
begin
   qrySelData.DisableControls;
   merken := qrySelData.GetBookmark;
   qrySelData.First;
   cal.Markdays.Clear;
   while Not qrySelData.Eof do
   begin
      DecodeDate(qrySelDataDatum.Value, jahr, monat, tag);
      if (jahr = cal.Year) and
          (monat = cal.Month) then
          if tag < 10 then
             cal.Markdays.Add(FormatDateTime('d.mm.',qrySelDataDatum.Value))
          else
             cal.Markdays.Add(FormatDateTime('dd.mm.',qrySelDataDatum.Value));

      qrySelData.Next;
   end;
   cal.Invalidate;
   qrySelData.GotoBookmark(merken);
   qrySelData.EnableControls;
end;
So, da hast du wieder was zu tun. Aber nicht nur abtippen :mrgreen:, sonst hilft dir das für zukünftige Probleme gar nicht. Versuche genau zu verstehen, was ich da vorschlage und warum. Wenn es nicht klar ist, solltest du lieber fragen.

m-werk 1. Dez 2002 10:56

Hi, So nach langen umerhumtüfteln, hab ich es noch immer nicht ganz geschafft.

Ich weiss nicht, wie ich UpdateCalMark im Privaten Teil deklarieren soll!

Ich habe

UpdateCalMark : Boolean;

Wenn ich das habe, glaube ich, dass dann die Fehlermeldungen, die mit dem letzten Code zusammenhängen, auch weg sind.

MrSpock 1. Dez 2002 12:31

Hallo m-werk,

im zweiten Source Abschnitt meies letzten Postings habe ich ja eine Methode vorgestellt:

Delphi-Quellcode:
procedure TForm1.UpdateCalMark;
Dort erkennst du, dass die Procedure UpdateCalMark eine Methode der Klasse TForm1 ist. Die Deklaration muss demnach lauten:

Delphi-Quellcode:
TForm1 = class(TForm)
    ...
  private
   { Private-Deklarationen }
    FirstTime  : Boolean;
   [b] procedure UpdateCalMark;[/b]
    ...
  public
    { Public-Deklarationen }
  end;

m-werk 1. Dez 2002 19:28

Hi, darauf hätte ich auch selber kommen können. Das kommt davon, wenn man nicht genau nachdenkt, was man tut.

Ich habe jetzt leider ein anderes kleines problem:

Ich habe mir die Kalenderkomponenten auf meinen Komponentenordner, wo ich schon andere Komponenten auch drinn habe, hineinkopiert.

Dann bin ich auf Komponenten installieren gegangen, und der Kalender wurde hinzugefügt.

Dann habe ich den Kalender im Programm so eingebaut, wie du beschrieben hast und das hat auch funktioniert.
Wenn ich dann den PC ausschalte, und dann später wieder weitermache, ist zwar der Kalender drinn aber wenn ich das Programm dann starten möchte, kommt die Fehlermeldung:

[Fataler Fehler] Arbeitszeit.pas: Datei nicht gefunden: 'Calpnl.dcu'

Und der Cursor steht bei:

Code:
uses
  Windows, Messages, SysUtils,.......,Calpnl;
Ich muss dann wieder die Kalenderkomponenten neu installieren und dann gehts wieder.

Was ist da los?

m-werk 1. Dez 2002 19:33

Weiters Hab ich noch zu den Eingabe und Übername-Buttons eine Frage:

Ist es nicht so, dass die Daten, die man eingibt automatisch in die DB gespeichert werden. Den Übernamebutton versteh ich ja noch aber Warum gibt es einen Eingabebutton?

MrSpock 1. Dez 2002 20:10

Hallo m-werk,

wenn Delphi das Programm "linked", sucht es nach den DCU (delphi compiled unit) der Bibliotheken, die benötigt werden.

Wo überall gesucht wird, kannst du auf der Optionen Seite einstellen:

Tools|Umgebungsoptionen... Seite Bibliothek dort hinter Suchpfad die 3 Punkte anklicken und in das untere Editfeld des Dialogs Verzeichnisse den Pfad auswählen, in dem die DCU des Kalenders steht. Dann noch Hinzufügen anklicken und dann noch OK.

Dann sollte es funktionieren.

MrSpock 1. Dez 2002 20:22

Hallo m-werk,

der Eingabebutton erzeugt einen neuen Eintrag für das Datum, das im Kalender angewählt ist. Wenn ein Eintrag für dieses Datum bereits existiert, wird dieser ggf. überschrieben:

Delphi-Quellcode:
procedure TForm1.btnEingabeClick(Sender: TObject);
var
   pickDate   : TDateTime;
    tag      : Integer;
begin
   with cal do
    begin
         if qrySelData.Locate('Datum',
                        EncodeDate(year,month,day), []) then
            if MessageDlg('Eintrag für diesen Tag existiert schon.'#10
                               +'Soll der Eintrag geändert werden?',
                                 mtConfirmation, [mbYes, mbNo], 0) = mrNo then
               exit
            else
               qrySelData.Edit
         else begin
            qrySelData.Append;
            qrySelDataDatum.Value := EncodeDate(year,month,day);
         end;
         ActiveControl := dbeStart
    end;
    btnPost.Enabled := True;
    btnCancel.Enabled := True
end;
Damit der Code funktioniert musst du noch einen weiteren Button namens btnCancel hinzufügen, der unter dem Button Übernahme steht und mit "Rückgängig" beschriftet ist. Damit kann der Nutzer die Eingabe abbrechen. Der Code für den Übernahme Button:

Delphi-Quellcode:
procedure TForm1.btnPostClick(Sender: TObject);
begin
   try
      qrySelData.Post;
      btnPost.Enabled := False;
      btnCancel.Enabled := False;
   except
    { Fehlermeldung }
   end;
end;
Und für den Abbrechen Button:
Delphi-Quellcode:
procedure TForm1.btnCancelClick(Sender: TObject);
begin
   qrySelData.Cancel;
   btnPost.Enabled := False;
   btnCancel.Enabled := False;
end;
Dem OnNewRecord Event von qrySelData weist du folgenden Code zu:
Delphi-Quellcode:
procedure TForm1.qrySelDataNewRecord(DataSet: TDataSet);
begin
   qrySelDataPersonalNummer.Value := frmLogin.PNr;
end;
Damit wird auch die Personalnummer automatisch gesetzt, denn die kennt der Benutzer ja nicht.

So, das soll es mal für heute sein.

m-werk 4. Dez 2002 20:08

Hi, das mit dem Kalender funktioniert jetzt.

Ich habe auch die anderen Codes so eingebaut wie du beschrieben hast.

Den letzten Code hab ich leider nicht verstanden, was dieser bewirkt.

Leider habe ich da ein Problem.

1. Ich kann in die Editfelder nichts eintragen. (Readonly ist auf False)
2. Wenn ich, bevor ich überhaupt was eintrage auf "Eingabe" klicke, kommt folgende Fehlermeldung:

qrySelData: Cannot modify a read-only dataset.

Ich hab mir alles nochmal angesehen, und konnte keinen Fehler entdecken.

Was hats da?

Nochwas möchte ich machen beim Login-Form.

Wenn der User sein PW eingibt, soll er mit der Enter-Taste zum Hauptmenü kommen. Ich habe schon dem EditFeld "ePasswort" bei Ereignisse den OnClick den Button "Login" zugewiesen aber das geht nicht.

MrSpock 4. Dez 2002 21:18

Hallo m-werk,

zunächst einmal musst du RequestLive bei qrySelData auf True setzen, dann hast du eine editierbare Datenmenge. Dann kannst du nach Betätigung des Eingabe-Schalters auch Werte in die DBEdit Felder schreiben.

Das letzte Codestück setzt das Feld Personalnummer bei jedem neu eingefügten Datensatz auf den Wert, den wir uns im Loginformular als die Personalnummer der Person gemerkt haben, die sich gerade eingeloggt hat. Wie gesagt, deine Mitarbeiter kennen ja ihre Personalnummer gar nicht, ist ja auch nicht nötig. Außerdem könnten sie bei manueller Eingabe aus Versehen die falsche Nummer eingeben und so z.B. deine Arbeitszeit eingeben :shock:, und das verhindert dieser Code.

MrSpock 4. Dez 2002 21:39

Hallo m-werk,

nach Eingabe eines neuen Datensatzes soll der Kalender angepasst werden, damit auch für das neue Datum der Tag blau markiert wird:

Delphi-Quellcode:
procedure TForm1.qrySelDataAfterPost(DataSet: TDataSet);
begin
   UpdateCalMark
end;
Wenn der Mitarbeiter einen Tag im Kalender anwählt, soll aus der Datenbank gleich der dazugehörige Datensatz angezeigt werden:

Delphi-Quellcode:
procedure TForm1.calDateChange(Sender: TObject);
begin
   with cal do
   begin
      UpdateCalMark;
      qrySelData.Locate('Datum', EncodeDate(year,month,day), [])
   end;
end;
Bevor ein neue Satz endgültig übernommen wird, sind noch ein paar Prüfungen notwendig:

Delphi-Quellcode:
procedure TForm1.qrySelDataBeforePost(DataSet: TDataSet);
var
   hilf   : TDateTime;
begin
   if Trim(qrySelDataStart.AsString) = '' then
   begin
      ShowMessage('Ungültige Startzeit');
      ActiveControl := dbeStart;
      Abort
   end;

   if Trim(qrySelDataEnde.AsString) = '' then
   begin
      ShowMessage('Ungültige Endzeit');
      ActiveControl := dbeEnde;
      Abort
   end;

   if qrySelDataStart.Value > qrySelDataEnde.Value then
   begin
      hilf := qrySelDataStart.Value;
      qrySelDataStart.Value := qrySelDataEnde.Value;
      qrySelDataEnde.Value := hilf
   end;
end;
So, jetzt hast du bereits das Wichtigste geschafft.

m-werk 8. Dez 2002 17:27

Hi, bin erst jetzt dazugekommen, mir den Code genauestens unter die Lupe zu nehmen, da ich zur Zeit wenig Zeit habe.

Folgendes: Ich habe den Code jetzt eingegeben und kann jetzt auch Werte in die Editfelder schreiben.

Wenn ich jetzt aber auf irgendein Datum im Kalender klicke kommt folgende Meldung:

Key violation

Was bedeutet das und was sagt diese Fehlermeldung aus?

Weiters: wenn ich einen Wert eingebe, ist nichts blau im Kalender hinterlegt.

Im Datumsfeld (DBGrid) steht auch kein Datum drinn.
Wenn ich das Programm dann schließe, und wieder öffne, ist der Datensatz auch weg.

MrSpock 8. Dez 2002 19:46

Hallo m-werk,

wenn du auf ein neues Datum im Kalender klickt werden zwei Aktionen durchgeführt, zuerst wird der Kalender aktualisiert und dann wird versucht den Eintrag zum aktuellen Datum auszuwählen.

Bei beiden Aktionen ist eine Key violation ungewöhnlich. Key violations treten dann auf, wenn du versuchst in eine Datenbank zwei Datensätze einzutragen, die beide denselben Schlüssel haben und der Key als unique, also eindeutig erklärt wurde. Überprüfe noch einmal den Code bei UpdateCalMark. Falls du nicht finden kann durchlaufe die Anwendung einmal im Einzelschritt (mit F7), um festzustellen, wo genau der Fehler auftritt.

m-werk 9. Dez 2002 20:03

Hi, ich habe alles überprüft, und auch mit dem einzellschrittmodus.
Ich habe keinen Fehler Feststellen können.


Nur bei folgenden Code kommt ein Hinweis:

Code:
procedure TArbeitszeitForm.btnEingabeClick(Sender: TObject);
var
   pickDate  : TDateTime;
    tag     : Integer;
begin
   with cal do
    begin
....................
Hinweis Arbeitszeit.pas: Variable 'pickDate' wurde deklariert, aber in 'TArbeitszeitForm.btnEingabeClick' nicht verwendet

Hinweis Arbeitszeit.pas: Variable 'tag' wurde deklariert, aber in 'TArbeitszeitForm.btnEingabeClick' nicht verwendet


Kann es was damit zu tun haben?


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:49 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz