Subversion Repositories delphiutils

Rev

Rev 83 | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. unit ZeiterfassungMain;
  2.  
  3. interface
  4.  
  5. uses
  6.   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  7.   Dialogs, DB, ADODB, Grids, Wwdbigrd, Wwdbgrid, ExtCtrls, DBCtrls, StdCtrls;
  8.  
  9. type
  10.   TForm1 = class(TForm)
  11.     ADOConnection1: TADOConnection;
  12.     wwDBGrid1: TwwDBGrid;
  13.     ADOTable1: TADOTable;
  14.     DataSource1: TDataSource;
  15.     ADOTable1TAG: TWideStringField;
  16.     ADOTable1KOMMEN: TWideStringField;
  17.     ADOTable1PAUSE_START: TWideStringField;
  18.     ADOTable1PAUSE_ENDE: TWideStringField;
  19.     ADOTable1GEHEN: TWideStringField;
  20.     ADOTable1SONSTIGER_ABZUG: TWideStringField;
  21.     ADOTable1ZUHAUSE: TWideStringField;
  22.     ADOTable1BERSTUNDEN_SALDO: TIntegerField;
  23.     ADOTable1BERSTUNDEN: TIntegerField;
  24.     ADOTable1FREIER_TAG: TBooleanField;
  25.     Panel1: TPanel;
  26.     Button1: TButton;
  27.     DBNavigator1: TDBNavigator;
  28.     ADOTable1WOCHENTAG: TStringField;
  29.     ADOTable1USERNAME: TStringField;
  30.     ComboBox1: TComboBox;
  31.     Label1: TLabel;
  32.     Label2: TLabel;
  33.     ADOTable1BEMERKUNG: TStringField;
  34.     procedure ADOTable1NewRecord(DataSet: TDataSet);
  35.     procedure FormClose(Sender: TObject; var Action: TCloseAction);
  36.     procedure ADOTable1BeforePost(DataSet: TDataSet);
  37.     procedure ADOTable1BERSTUNDEN_SALDOGetText(Sender: TField; var Text: string;
  38.       DisplayText: Boolean);
  39.     procedure ADOTable1BERSTUNDENGetText(Sender: TField; var Text: string;
  40.       DisplayText: Boolean);
  41.     procedure wwDBGrid1CalcCellColors(Sender: TObject; Field: TField;
  42.       State: TGridDrawState; Highlight: Boolean; AFont: TFont; ABrush: TBrush);
  43.     procedure ADOTable1AfterPost(DataSet: TDataSet);
  44.     procedure Button1Click(Sender: TObject);
  45.     procedure ADOTable1TAGChange(Sender: TField);
  46.     procedure ADOTable1SONSTIGER_ABZUGSetText(Sender: TField;
  47.       const Text: string);
  48.     procedure ADOTable1ZUHAUSESetText(Sender: TField; const Text: string);
  49.     procedure ADOTable1GEHENSetText(Sender: TField; const Text: string);
  50.     procedure ADOTable1PAUSE_ENDESetText(Sender: TField; const Text: string);
  51.     procedure ADOTable1PAUSE_STARTSetText(Sender: TField; const Text: string);
  52.     procedure ADOTable1KOMMENSetText(Sender: TField; const Text: string);
  53.     procedure FormShow(Sender: TObject);
  54.     procedure ADOTable1WOCHENTAGGetText(Sender: TField; var Text: string;
  55.       DisplayText: Boolean);
  56.     procedure ComboBox1Change(Sender: TObject);
  57.     procedure ADOTable1TAGSetText(Sender: TField; const Text: string);
  58.     procedure ADOTable1AfterDelete(DataSet: TDataSet);
  59.     procedure ADOTable1TAGGetText(Sender: TField; var Text: string;
  60.       DisplayText: Boolean);
  61.     procedure ADOTable1KOMMENGetText(Sender: TField; var Text: string;
  62.       DisplayText: Boolean);
  63.     procedure ADOTable1PAUSE_STARTGetText(Sender: TField; var Text: string;
  64.       DisplayText: Boolean);
  65.     procedure ADOTable1PAUSE_ENDEGetText(Sender: TField; var Text: string;
  66.       DisplayText: Boolean);
  67.     procedure ADOTable1GEHENGetText(Sender: TField; var Text: string;
  68.       DisplayText: Boolean);
  69.     procedure ADOTable1SONSTIGER_ABZUGGetText(Sender: TField; var Text: string;
  70.       DisplayText: Boolean);
  71.     procedure ADOTable1ZUHAUSEGetText(Sender: TField; var Text: string;
  72.       DisplayText: Boolean);
  73.     procedure ADOTable1BeforeScroll(DataSet: TDataSet);
  74.   private
  75.     function GueltigeZeile: boolean;
  76.   protected
  77.     procedure ReorgDataSet;
  78.     procedure ReorgAll;
  79.     function RegelArbeitszeit: integer;
  80.   end;
  81.  
  82. var
  83.   Form1: TForm1;
  84.  
  85. implementation
  86.  
  87. {$R *.dfm}
  88.  
  89. // TODO: Trennstriche zwischen Wochen oder zwischen Urlauben
  90. // IDEE: Wochenend-Multiplikator
  91. // TODO: "Gehen um" Anzeige
  92.  
  93. uses
  94.   DateUtils, StrUtils, IniFiles;
  95.  
  96. {$REGION 'Hilfsfunktionen'}
  97.  
  98. function SQL_Escape(const s: string): string;
  99. begin
  100.   result := StringReplace(s, '''', '\''', [rfReplaceAll]);
  101. end;
  102.  
  103. function IstLeer(f: TField): boolean;
  104. begin
  105.   result := f.IsNull or (f.AsString = '') or (f.AsString = '00:00:00');
  106. end;
  107.  
  108. function Minuten(f: TField): integer;
  109. begin
  110.   if IstLeer(f) then
  111.   begin
  112.     result := 0;
  113.   end
  114.   else
  115.   begin
  116.     result := MinuteOfTheDay(f.AsDateTime);
  117.   end;
  118. end;
  119.  
  120. function MinutenZuHF_Int(min: integer): string;
  121. var
  122.   d: integer;
  123. begin
  124.   d := min;
  125.   if d < 0 then
  126.   begin
  127.     result := '-';
  128.     d := -d;
  129.   end
  130.   else
  131.   begin
  132.     result := '';
  133.   end;
  134.   result := result + Format('%.2d:%.2d', [d div 60, d mod 60]);
  135. end;
  136.  
  137. function MinutenZuHF(f: TField): string;
  138. begin
  139.   if IstLeer(f) then
  140.   begin
  141.     result := '';
  142.   end
  143.   else
  144.   begin
  145.     result := MinutenZuHF_Int(f.AsInteger);
  146.   end;
  147. end;
  148.  
  149. function EchtesDatum(f: TField): TDate;
  150. begin
  151.   if Copy(f.AsString, 5, 1) = '-' then
  152.   begin
  153.     result := EncodeDate(
  154.     StrtoInt(Copy(f.AsString, 1, 4)),
  155.     StrtoInt(Copy(f.AsString, 6, 2)),
  156.     StrtoInt(Copy(f.AsString, 9, 2))
  157.     );
  158.   end
  159.   else
  160.     result := StrToDate(f.AsString);
  161. end;
  162.  
  163. function WUserName: String;
  164. var
  165.   nSize: DWord;
  166. begin
  167.   nSize := 1024;
  168.   SetLength(Result, nSize);
  169.   if GetUserName(PChar(Result), nSize) then
  170.     SetLength(Result, nSize-1)
  171.   else
  172.     RaiseLastOSError;
  173. end;
  174.  
  175. {$ENDREGION}
  176.  
  177. function TForm1.RegelArbeitszeit: integer;
  178. var
  179.   test: TADOQuery;
  180. begin
  181.   test := TADOQuery.Create(nil);
  182.   try
  183.     test.Connection := ADOConnection1;
  184.     test.Close;
  185.     test.SQL.Text := 'select MINUTEN from REGELARBEITSZEIT where USERNAME = ''' + SQL_Escape(ComboBox1.Text) + '''';
  186.     test.Open;
  187.     if test.RecordCount = 0 then
  188.     begin
  189.       result := 8 * 60;
  190.     end
  191.     else
  192.     begin
  193.       result := test.FieldByName('MINUTEN').AsInteger;
  194.     end;
  195.   finally
  196.     test.Free;
  197.   end;
  198. end;
  199.  
  200. procedure TForm1.ReorgAll;
  201. var
  202.   saldo: integer;
  203.   baks, baku: string;
  204.   bakEv: TDataSetNotifyEvent;
  205.   dead: boolean;
  206. begin
  207.   if ADOTable1TAG.IsNull then
  208.   begin
  209.     baks := '';
  210.   end
  211.   else
  212.   begin
  213.     if Copy(ADOTable1TAG.AsString, 5, 1) = '-' then
  214.       baks := ADOTable1TAG.AsString
  215.     else
  216.       DateTimeToString(baks, 'YYYY-MM-DD', ADOTable1TAG.AsDateTime);
  217.   end;
  218.   baku := ADOTable1USERNAME.AsString;
  219.   ADOTable1.Requery();
  220.  
  221.   bakEv := ADOTable1.AfterPost;
  222.   ADOTable1.AfterPost := nil;
  223.   ADOTable1.DisableControls;
  224.   try
  225.     ADOTable1.First;
  226.     saldo := 0;
  227.     dead := false;
  228.     while not ADOTable1.Eof do
  229.     begin
  230.       ADOTable1.Edit;
  231.       if not dead then ReorgDataSet;
  232.       dead := dead or ADOTable1BERSTUNDEN.IsNull;
  233.       if dead then
  234.       begin
  235.         ADOTable1BERSTUNDEN_SALDO.Clear;
  236.       end
  237.       else
  238.       begin
  239.         saldo := saldo + ADOTable1BERSTUNDEN.AsInteger;
  240.         ADOTable1BERSTUNDEN_SALDO.AsInteger := saldo;
  241.         saldo := ADOTable1BERSTUNDEN_SALDO.AsInteger;
  242.       end;
  243.       ADOTable1.Post;
  244.       ADOTable1.Next;
  245.     end;
  246.   finally
  247.     if baks <> '' then ADOTable1.Locate('USERNAME;TAG', VarArrayOf([baku, baks]), []);
  248.     ADOTable1.AfterPost := bakEv;
  249.     ADOTable1.EnableControls;
  250.   end;
  251. end;
  252.  
  253. procedure TForm1.ADOTable1AfterDelete(DataSet: TDataSet);
  254. begin
  255.   ReorgAll;
  256. end;
  257.  
  258. procedure TForm1.ADOTable1AfterPost(DataSet: TDataSet);
  259. begin
  260.   ReorgAll;
  261. end;
  262.  
  263. function TForm1.GueltigeZeile: boolean;
  264. begin
  265.   result := false;
  266.  
  267.   if IstLeer(ADOTable1KOMMEN) <> IstLeer(ADOTable1GEHEN) then exit;
  268.   if IstLeer(ADOTable1PAUSE_START) <> IstLeer(ADOTable1PAUSE_ENDE) then exit;
  269.   if not IstLeer(ADOTable1PAUSE_START) and (ADOTable1PAUSE_START.AsDateTime < ADOTable1KOMMEN.AsDateTime) then exit;
  270.   if not IstLeer(ADOTable1PAUSE_ENDE) and (ADOTable1PAUSE_ENDE.AsDateTime < ADOTable1PAUSE_START.AsDateTime) then exit;
  271.   if not IstLeer(ADOTable1GEHEN) and (ADOTable1GEHEN.AsDateTime < ADOTable1KOMMEN.AsDateTime) then exit;
  272.   if not IstLeer(ADOTable1GEHEN) and not IstLeer(ADOTable1PAUSE_START) and (ADOTable1GEHEN.AsDateTime < ADOTable1PAUSE_START.AsDateTime) then exit;
  273.   if not IstLeer(ADOTable1GEHEN) and not IstLeer(ADOTable1PAUSE_ENDE) and (ADOTable1GEHEN.AsDateTime < ADOTable1PAUSE_ENDE.AsDateTime) then exit;
  274.  
  275.   result := true;
  276. end;
  277.  
  278. procedure TForm1.ReorgDataSet;
  279. var
  280.   m: integer;
  281. begin
  282.   if GueltigeZeile then
  283.   begin
  284.     m :=   (Minuten(ADOTable1GEHEN) - Minuten(ADOTable1KOMMEN))
  285.          - (Minuten(ADOTable1PAUSE_ENDE) - Minuten(ADOTable1PAUSE_START))
  286.          - Minuten(ADOTable1SONSTIGER_ABZUG)
  287.          + Minuten(ADOTable1ZUHAUSE);
  288.  
  289.     if not ADOTable1FREIER_TAG.AsBoolean then
  290.     begin
  291.       m := m - RegelArbeitszeit;
  292.     end;
  293.  
  294.     ADOTable1BERSTUNDEN.AsInteger := m;
  295.   end
  296.   else
  297.   begin
  298.     ADOTable1BERSTUNDEN.Clear;
  299.   end;
  300. end;
  301.  
  302. procedure TForm1.ADOTable1BeforePost(DataSet: TDataSet);
  303. begin
  304.   if (ADOTable1.State = dsInsert) and ADOTable1TAG.IsNull then
  305.   begin
  306.     AdoTable1.Cancel;
  307.     Abort;
  308.   end;
  309.  
  310.   ReorgDataSet;
  311. end;
  312.  
  313. procedure TForm1.ADOTable1BeforeScroll(DataSet: TDataSet);
  314. begin
  315.   if (DataSet.State = dsInsert) and (not ADOTable1TAG.IsNull) then Dataset.Post;
  316. end;
  317.  
  318. procedure TForm1.ADOTable1BERSTUNDENGetText(Sender: TField; var Text: string;
  319.   DisplayText: Boolean);
  320. begin
  321.   Text := MinutenZuHF(ADOTable1BERSTUNDEN);
  322. end;
  323.  
  324. procedure TForm1.ADOTable1BERSTUNDEN_SALDOGetText(Sender: TField;
  325.   var Text: string; DisplayText: Boolean);
  326. begin
  327.   Text := MinutenZuHF(ADOTable1BERSTUNDEN_SALDO);
  328. end;
  329.  
  330. procedure TForm1.ADOTable1GEHENGetText(Sender: TField; var Text: string;
  331.   DisplayText: Boolean);
  332. begin
  333.   Text := Copy(Sender.AsString, 1, 5);
  334. end;
  335.  
  336. procedure TForm1.ADOTable1GEHENSetText(Sender: TField; const Text: string);
  337. begin
  338.   if Text = '' then
  339.   begin
  340.     ADOTable1GEHEN.Clear;
  341.   end
  342.   else
  343.   begin
  344.     if Pos(':', Text) = 0 then
  345.       ADOTable1GEHEN.AsString := Text + ':00'
  346.     else
  347.       ADOTable1GEHEN.AsString := Text;
  348.   end;
  349. end;
  350.  
  351. procedure TForm1.ADOTable1KOMMENGetText(Sender: TField; var Text: string;
  352.   DisplayText: Boolean);
  353. begin
  354.   Text := Copy(Sender.AsString, 1, 5);
  355. end;
  356.  
  357. procedure TForm1.ADOTable1KOMMENSetText(Sender: TField; const Text: string);
  358. begin
  359.   if Text = '' then
  360.   begin
  361.     ADOTable1KOMMEN.Clear;
  362.   end
  363.   else
  364.   begin
  365.     if Pos(':', Text) = 0 then
  366.       ADOTable1KOMMEN.AsString := Text + ':00'
  367.     else
  368.       ADOTable1KOMMEN.AsString := Text;
  369.   end;
  370. end;
  371.  
  372. procedure TForm1.ADOTable1NewRecord(DataSet: TDataSet);
  373. var
  374.   test: TADOQuery;
  375. begin
  376.   ADOTable1FREIER_TAG.AsBoolean := false;
  377.   ADOTable1USERNAME.AsString := ComboBox1.Text;
  378.   test := TADOQuery.Create(nil);
  379.   try
  380.     test.Connection := ADOConnection1;
  381.     test.Close;
  382.     test.SQL.Text := 'select * from TAGE where TAG = ''' + DateToStr(Date) + ''' and USERNAME = ''' + SQL_Escape(ComboBox1.Text) + '''';
  383.     test.Open;
  384.     if test.RecordCount = 0 then
  385.     begin
  386.  
  387.       ADOTable1TAG.AsDateTime := Date;
  388.       ADOTable1KOMMEN.AsString := TimeToStr(Time);
  389.       ADOTable1FREIER_TAG.AsBoolean := (DayOfWeek(Date) = 1{Sunday}) or
  390.                                        (DayOfWeek(Date) = 7{Saturday});
  391.     end;
  392.   finally
  393.     test.Free;
  394.   end;
  395.  
  396.   wwDBGrid1.SelectedField := ADOTable1TAG;
  397. end;
  398.  
  399. procedure TForm1.ADOTable1PAUSE_ENDEGetText(Sender: TField; var Text: string;
  400.   DisplayText: Boolean);
  401. begin
  402.   Text := Copy(Sender.AsString, 1, 5);
  403. end;
  404.  
  405. procedure TForm1.ADOTable1PAUSE_ENDESetText(Sender: TField; const Text: string);
  406. begin
  407.   if Text = '' then
  408.   begin
  409.     ADOTable1PAUSE_ENDE.Clear;
  410.   end
  411.   else
  412.   begin
  413.     if Pos(':', Text) = 0 then
  414.       ADOTable1PAUSE_ENDE.AsString := Text + ':00'
  415.     else
  416.       ADOTable1PAUSE_ENDE.AsString := Text;
  417.   end;
  418. end;
  419.  
  420. procedure TForm1.ADOTable1PAUSE_STARTGetText(Sender: TField; var Text: string;
  421.   DisplayText: Boolean);
  422. begin
  423.   Text := Copy(Sender.AsString, 1, 5);
  424. end;
  425.  
  426. procedure TForm1.ADOTable1PAUSE_STARTSetText(Sender: TField;
  427.   const Text: string);
  428. begin
  429.   if Text = '' then
  430.   begin
  431.     ADOTable1PAUSE_START.Clear;
  432.   end
  433.   else
  434.   begin
  435.     if Pos(':', Text) = 0 then
  436.       ADOTable1PAUSE_START.AsString := Text + ':00'
  437.     else
  438.       ADOTable1PAUSE_START.AsString := Text;
  439.   end;
  440. end;
  441.  
  442. procedure TForm1.ADOTable1SONSTIGER_ABZUGGetText(Sender: TField;
  443.   var Text: string; DisplayText: Boolean);
  444. begin
  445.   Text := Copy(Sender.AsString, 1, 5);
  446. end;
  447.  
  448. procedure TForm1.ADOTable1SONSTIGER_ABZUGSetText(Sender: TField;
  449.   const Text: string);
  450. begin
  451.   if Text = '' then
  452.   begin
  453.     ADOTable1SONSTIGER_ABZUG.Clear;
  454.   end
  455.   else
  456.   begin
  457.     if Pos(':', Text) = 0 then
  458.       ADOTable1SONSTIGER_ABZUG.AsString := Text + ':00'
  459.     else
  460.       ADOTable1SONSTIGER_ABZUG.AsString := Text;
  461.   end;
  462. end;
  463.  
  464. procedure TForm1.ADOTable1TAGChange(Sender: TField);
  465. begin
  466.   ADOTable1FREIER_TAG.AsBoolean := (DayOfWeek(ADOTable1TAG.AsDateTime) = 1{Sunday}) or
  467.                                    (DayOfWeek(ADOTable1TAG.AsDateTime) = 7{Saturday});
  468.   // TODO: "Wochentag" Feld aktualisieren
  469. end;
  470.  
  471. procedure TForm1.ADOTable1TAGGetText(Sender: TField; var Text: string;
  472.   DisplayText: Boolean);
  473. begin
  474.   if IstLeer(Sender) then
  475.     Text := Sender.AsString
  476.   else
  477.     Text := DateToStr(EchtesDatum(Sender));
  478. end;
  479.  
  480. procedure TForm1.ADOTable1TAGSetText(Sender: TField; const Text: string);
  481. var
  482.   i, punktCount: integer;
  483. begin
  484.   punktCount := 0;
  485.   for i := 1 to Length(Text) do
  486.   begin
  487.     if Text[i] = '.' then inc(punktCount);
  488.   end;
  489.  
  490.   if punktCount = 1 then
  491.   begin
  492.     ADOTable1TAG.AsString := Text + '.' + IntToStr(CurrentYear);
  493.   end
  494.   else if (PunktCount = 2) and EndsStr('.',Text) then
  495.   begin
  496.     ADOTable1TAG.AsString := Text + IntToStr(CurrentYear);
  497.   end
  498.   else
  499.   begin
  500.     ADOTable1TAG.AsString := Text;
  501.   end;
  502. end;
  503.  
  504. procedure TForm1.ADOTable1WOCHENTAGGetText(Sender: TField; var Text: string;
  505.   DisplayText: Boolean);
  506. begin
  507.   try
  508.     if ADOTable1TAG.AsString <> '' then
  509.       Text := ShortDayNames[DayOfWeek(EchtesDatum(ADOTable1TAG))]
  510.     else
  511.       Text := '';
  512.   except
  513.     Text := '??';
  514.   end;
  515. end;
  516.  
  517. procedure TForm1.ADOTable1ZUHAUSEGetText(Sender: TField; var Text: string;
  518.   DisplayText: Boolean);
  519. begin
  520.   Text := Copy(Sender.AsString, 1, 5);
  521. end;
  522.  
  523. procedure TForm1.ADOTable1ZUHAUSESetText(Sender: TField; const Text: string);
  524. begin
  525.   if Text = '' then
  526.   begin
  527.     ADOTable1ZUHAUSE.Clear;
  528.   end
  529.   else
  530.   begin
  531.     if Pos(':', Text) = 0 then
  532.       ADOTable1ZUHAUSE.AsString := Text + ':00'
  533.     else
  534.       ADOTable1ZUHAUSE.AsString := Text;
  535.   end;
  536. end;
  537.  
  538. procedure TForm1.Button1Click(Sender: TObject);
  539. begin
  540.   ReorgAll;
  541. end;
  542.  
  543. procedure TForm1.ComboBox1Change(Sender: TObject);
  544. begin
  545.   Label2.Caption := MinutenZuHF_Int(RegelArbeitszeit) + ' Std.';
  546.  
  547.   ADOTable1.DisableControls;
  548.  
  549.   ADOTable1.Active := false;
  550.   ADOTable1.ReadOnly := false;
  551.   ADOTable1.Filter := 'USERNAME = ''' + SQL_Escape(ComboBox1.Text) + '''';
  552.   ADOTable1.Filtered := true;
  553.   ADOTable1.Active := true;
  554.  
  555.   ReorgAll;
  556.  
  557.   ADOTable1.Active := false;
  558.   ADOTable1.ReadOnly := (ComboBox1.Text <> WUserName) and (WUserName <> 'Administrator');
  559.   ADOTable1.Active := true;
  560.  
  561.   ADOTable1.Last;
  562.   Button1.Enabled := not ADOTable1.ReadOnly;
  563.  
  564.   ADOTable1.EnableControls;
  565. end;
  566.  
  567. procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
  568. begin
  569.   if ADOTable1.State in [dsEdit, dsInsert] then
  570.   begin
  571.     try
  572.       ADOTable1.Post;
  573.     except
  574.       on E: EAbort do
  575.       begin
  576.         exit;
  577.       end;
  578.     end;
  579.   end;
  580. end;
  581.  
  582. procedure TForm1.FormShow(Sender: TObject);
  583. var
  584.   test: TADOQuery;
  585.   ini: TMemIniFile;
  586. resourcestring
  587.   DefaultConnectionString = 'Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=ZEITERFASSUNG;' +
  588.                             'Data Source=SHS\CORA2017,49011;Use Procedure for Prepare=1;Auto Translate=True;Packet Size=4096;Workstation ID=MARSCHALL;Use Encryption for Data=False;Tag with column collation when possible=False;';
  589. begin
  590.   ini := TMemIniFile.Create(IncludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0))) + ChangeFileExt(ExtractFileName(ParamStr(0)), '.ini'));
  591.   try
  592.     ADOConnection1.ConnectionString := ini.ReadString('Connection', 'ConnectionString', DefaultConnectionString);
  593.   finally
  594.     ini.Free;
  595.   end;
  596.   ADOConnection1.Connected := true;
  597.  
  598.   {$REGION 'Username Combobox füllen'}
  599.   test := TADOQuery.Create(nil);
  600.   try
  601.     test.Connection := ADOConnection1;
  602.     test.Close;
  603.     test.SQL.Text := 'select distinct USERNAME from TAGE';
  604.     test.Open;
  605.     ComboBox1.Items.Clear;
  606.     while not test.EOF do
  607.     begin
  608.       ComboBox1.Items.Add(test.FieldByName('USERNAME').AsString);
  609.       test.Next;
  610.     end;
  611.   finally
  612.     test.Free;
  613.   end;
  614.  
  615.   if ComboBox1.Items.IndexOf(WUserName) = -1 then
  616.     ComboBox1.Items.Add(WUserName);
  617.   ComboBox1.Sorted := true;
  618.   ComboBox1.ItemIndex := ComboBox1.Items.IndexOf(WUserName);
  619.  
  620.   ComboBox1Change(ComboBox1);
  621.   {$ENDREGION}
  622.  
  623.   if wwDBGrid1.CanFocus then wwDBGrid1.SetFocus;
  624.   wwDBGrid1.SelectedField := ADOTable1TAG;
  625. end;
  626.  
  627. procedure TForm1.wwDBGrid1CalcCellColors(Sender: TObject; Field: TField;
  628.   State: TGridDrawState; Highlight: Boolean; AFont: TFont; ABrush: TBrush);
  629. begin
  630.   if Highlight then exit;
  631.  
  632.   if (Field.FieldName = ADOTable1WOCHENTAG.FieldName) or
  633.      (Field.FieldName = ADOTable1BERSTUNDEN.FieldName) or
  634.      (Field.FieldName = ADOTable1BERSTUNDEN_SALDO.FieldName) then
  635.   begin
  636.     ABrush.Color := clBtnFace;
  637.   end;
  638.  
  639.   if (Field.FieldName = ADOTable1BERSTUNDEN.FieldName) then
  640.   begin
  641.     if ADOTable1BERSTUNDEN.AsInteger < 0 then
  642.     begin
  643.       AFont.Color := clRed;
  644.     end;
  645.   end;
  646.  
  647.   if (Field.FieldName = ADOTable1BERSTUNDEN_SALDO.FieldName) then
  648.   begin
  649.     if ADOTable1BERSTUNDEN_SALDO.AsInteger < 0 then
  650.     begin
  651.       AFont.Color := clRed;
  652.     end;
  653.   end;
  654. end;
  655.  
  656. end.
  657.