// Getestet mit D2010 unter W7

// 1.  
// Es werden alle Werte einer Zeile in einem Stringgrid addiert   
// und das Ergebnis in einem Label angezeigt. Enthält eine Zelle   
// keine Zahl, sondern ein Wort oder ein Leerzeichen,   
// wird diese Zelle als "0" gewertet.   
   
const   
  zeile: integer = 2;   { dritte Zeile, da die Zählung bei 0 beginnt }  
   
procedure TForm1.Button1Click(Sender: TObject);   
var   
  x: integer;   
  Ergebnis: Double;   
begin   
  Ergebnis := 0;   
  for x := StringGrid1.fixedCols to StringGrid1.ColCount - 1 do   
  try   
    Ergebnis := Ergebnis +   
      StrToFloat(Stringreplace(StringGrid1.Cells[x, zeile], '.', '',   
      [rfReplaceAll]));   
  except end;   
  label1.Caption := FloatToStr(Ergebnis);   
end;   
   
//-------------------------------------------------------------   
   
   
// 2.  
// Es wird eine Spalte addiert. Im Gegensatz zu oben, wird die Summe nicht   
// in einem Label sondern in der untersten Zelle der Spalte angezeigt.    
// Diese Summen-Zelle sollte natürlich nicht anderweitig genutzt werden.   
   
const   
  spalte: integer = 3;    { vierte Spalte einschl. FixedCols }  
   
   
procedure TForm1.Button2Click(Sender: TObject);   
var   
  x: integer;   
  Ergebnis: Double;   
begin   
  Ergebnis := 0;   
  for x := StringGrid1.fixedRows to StringGrid1.RowCount - 2 do   
  try   
    Ergebnis := Ergebnis +   
      StrToFloat(Stringreplace(StringGrid1.Cells[spalte, x], '.', '',   
      [rfReplaceAll]));   
  except end;   
  StringGrid1.Cells[spalte, StringGrid1.RowCount - 1] :=   
    FloatToStr(Ergebnis);   
end;

//-------------------------------------------------------------  
  
  
//
3. 
// Wenn man im Objektinspektor doppelt auf "OnSetEditText" klickt,  
// wird das entsprechende Event angelegt, das man mit dem folgenden  
// Code ergänzen kann. Hierbei wird sofort die Summe in der untersten  
// Zelle aktualisiert, sobald irgendwo in der Spalte eine Zahl eingegeben  
// oder geändert wird (natürlich muss dazu "goEditing" auf true stehen).  
// Aus Geschwindigkeitsgründen wurde die Abfrage ob "Zahl oder nicht"
// gegenüber den anderen Beispielen verändert.

const 
  spalte: integer = 3;  // Spalte, die addiert wird
   
function isZahl(p: string): boolean;  
var  
  x, lg: integer;  
  iskomma, ise, isvorzeichen: boolean;  
begin  
  result := false;  
  lg := length(p);  
  if (lg = 0) then exit;  
  isvorzeichen := false;  
  iskomma := false;  
  ise := false;  
  for x := 1 to lg do begin  
    if (p[x] = ',') then begin  
      if iskomma or ise then exit;  
      iskomma := true;  
      continue;  
    end;  
    if (lowercase(p[x]) = 'e') then begin  
      if ise or (x = 1) then exit;  
      isvorzeichen := false;  
      ise := true;  
      continue;  
    end;  
    if (p[x] = '+') or (p[x] = '-') then begin  
      if (x > 1) and (lowercase(p[x - 1]) <> 'e') or isvorzeichen  
        or (lg = 1) or (x < lg) and (lowercase(p[x + 1]) = 'e') then exit;  
      isvorzeichen := true;  
      continue;  
    end;  
    if not (p[x] in ['0'..'9']) then exit;  
  end;  
  result := true;  
end; 
 
procedure TForm1.StringGrid1SetEditText(Sender: TObject; ACol, 
  ARow: Integer; const Value: string);  
var  
  x: integer;  
  Ergebnis: Double;  
begin 
  if spalte = ACol then begin 
    Ergebnis := 0; 
    for x := StringGrid1.fixedRows to StringGrid1.RowCount - 2 do begin 
      if isZahl(StringGrid1.Cells[spalte, x]) then 
        Ergebnis := Ergebnis + 
          StrToFloat(Stringreplace(StringGrid1.Cells[spalte, x], '.', '', 
            [rfReplaceAll])); 
    end; 
    StringGrid1.Cells[spalte, StringGrid1.RowCount - 1] := 
      FloatToStr(Ergebnis); 
  end; 
end; 

//-------------------------------------------------------------  


//
4. 
// Im folgenden Beispiel wird ein ganzer Bereich addiert und das  
// Ergebnis in eine bestimmte Zelle geschrieben. Dieses Ergebnisfeld  
// darf nicht innerhalb des zu addierenden Bereiches liegen. Zu   
// Demo-Zwecken sind die Spalten mit Buchstaben (
'A'..) bezeichnet. 
// Die Anzahl der Spalten darf höchstens 256 (+ 1 FixedCols) sein. 
// Im Beispiel wird der Bereich
'A1:C4' addiert und in der Zelle 'D1' 
// wird das Ergebnis angezeigt. Damit Gleitkommazahlen ordnungsgemäß
// addiert werden können, werden die Tausenderpunkte in den entsprechenden
// Zellen entfernt. Im Gegensatz zu oben ist es hier auch möglich
// Zahlen in wissenschaftlicher Notation einzugeben
(z.B.: 17E+4)
.

type 
  cr = record 
    Col, Row: Integer; 
  end; 
 
  aecr = record 
    Anfang, Ende: cr; 
  end; 
 
var 
  SummCell: cr; 
  Felder: aecr; 
  ok: Boolean; 
  Punkt, Komma: byte; 
 
  Bereich: string = 'A1:C4'; 
  SummenFeld: string = 'D1'; 
 
function isZahl(p: pchar): Boolean; stdcall; 
var 
  x: cardinal; 
asm 
  xor ecx, ecx 
  mov edx, p 
  mov x, edx 
 @schleife: 
  mov al, [edx] 
  cmp al, 0 
  jnz @plus 
  cmp edx, x 
  jz @false 
  jmp @true 
 @plus: 
  cmp al, '+' 
  jnz @minus 
 @vorzeichen: 
  cmp ch, 0 
  jnz @false 
  mov ch, 1 
  cmp edx, x 
  jz @eins 
  mov ah, [edx-2]  // [edx-1] 
  cmp ah, 'e' 
  jz @weiter 
  cmp ah, 'E' 
  jz @weiter 
 @eins: 
  mov ah, [edx+2]  // [edx+1] 
  cmp ah, 0 
  jz @false 
  cmp edx, x 
  jnz @false 
  cmp ah, 'e' 
  jz @false 
  cmp ah, 'E' 
  jz @false 
  jmp @weiter 
 @minus: 
  cmp al, '-' 
  jnz @komm 
  jmp @vorzeichen 
 @komm: 
  cmp al, Komma 
  jnz @e 
  cmp cl, 0 
  jg @false 
  cmp ecx, $101 
  jg @false 
  mov cl, 1 
  jmp @weiter 
 @e: 
  cmp al, 'e' 
  jz @etest 
  cmp al, 'E' 
  jnz @ziffer 
 @etest: 
  cmp ecx, $101 
  jg @false 
  cmp edx, x 
  jz @false 
  or ecx, $10000 
  xor ch, ch 
  jmp @weiter 
 @ziffer: 
  cmp al, Punkt 
  jz @weiter 
  cmp al, '0' 
  jl @false 
  cmp al, '9' 
  jg @false 
 @weiter: 
  add edx, 2    // inc edx 
  jmp @schleife 
 @false: 
  mov @result, 0 
  jmp @raus 
 @true: 
  mov result, 1 
 @raus: 
end; 
 
procedure pruefen(p1, p2: pointer); stdcall; 
asm 
  mov edx,p1 
  mov eax,[edx] 
  mov edx,p2 
  mov ecx,[edx] 
  cmp eax,ecx 
  jle @fertig 
  mov [edx],eax 
  mov edx,p1 
  mov [edx],ecx 
 @fertig: 
end; 
 
function Punktweg(p: PWideChar): pchar; stdcall; 
asm 
  push ebx 
  xor ebx, ebx 
  mov edx, p 
  mov @result, edx 
 @loop: 
  mov al, [edx] 
  cmp al, 0 
  jz @fertig 
  cmp al, Punkt 
  jz @pw 
  add edx, 2  // inc edx 
  jmp @loop 
 @pw: 
  mov ecx, edx 
  inc ebx 
 @loop2: 
  mov ah, [edx+2]    // [edx+1] 
  mov [edx], ah 
  cmp ah, 0 
  jz @weiter 
  add edx, 2   // inc edx 
  jmp @loop2 
 @weiter: 
  mov edx, ecx 
  jmp @loop 
 @fertig: 
  mov edx, p 
  sub edx, 4 
  mov eax, [edx] 
  sub eax, ebx 
  mov [edx], eax 
  pop ebx 
end; 
 
 
function Feldwandeln(s: string; var z: cr): Boolean; 
var 
  x, p: Integer; 
begin 
  result := false; 
  p := -1; 
  s := trim(uppercase(s)); 
  for x := 2 to length(s) do 
    if not CharInset(s[x], ['A' .. 'Z']) then 
    begin 
      p := x; 
      break; 
    end; 
  if (p > 3) or (p < 0) then 
    exit; 
  try 
    if p = 2 then 
      z.Col := ord(s[1]) - 64 
    else 
      z.Col := ord(s[2]) - 64 + (ord(s[1]) - 64) * 26; 
    if z.Col > 256 then 
      exit; 
    z.Row := strtoint(copy(s, p, maxint)); 
  except 
    exit; 
  end; 
  result := true; 
end; 
 
function Arealwandeln(s: string; var fl: aecr): Boolean; 
var 
  p: Integer; 
begin 
  result := false; 
  p := pos(':', s); 
  with fl do 
  begin 
    if not Feldwandeln(copy(s, 1, p - 1), Anfang) then 
      exit; 
    if not Feldwandeln(copy(s, p + 1, maxint), Ende) then 
      exit; 
    pruefen(@Anfang.Col, @Ende.Col); 
    pruefen(@Anfang.Row, @Ende.Row); 
    if (SummCell.Col in [Anfang.Col .. Ende.Col]) and 
      (SummCell.Row in [Anfang.Row .. Ende.Row]) then 
      exit; 
  end; 
  result := true; 
end; 
 
procedure TForm1.FormCreate(Sender: TObject); 
var 
  x: Integer; 
begin 
  Punkt := ord(ThousandSeparator); 
  Komma := ord(Decimalseparator); 
  with StringGrid1 do 
  begin 
    Options := Options + [goEditing]; 
    fixedRows := 1; 
    fixedCols := 1; 
    for x := 1 to ColCount - 1 do // Nummerieren der Spalten 
      if x <= 26 then 
        Cells[x, 0] := chr(x + 64) 
      else if x <= 256 then 
        Cells[x, 0] := chr((x - 1) div 26 + 64) + chr((x - 1) mod 26 + 65); 
    for x := 1 to RowCount - 1 do 
      Cells[0, x] := inttostr(x); 
  end; 
  ok := Feldwandeln(SummenFeld, SummCell) and Arealwandeln(Bereich, Felder); 
  if not ok then 
  begin 
    StringGrid1.Cells[0, 0] := 'Fehler'; 
    beep; 
  end; 
end; 
 
procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; 
  Rect: TRect; State: TGridDrawState); 
begin 
  if (ACol = 4) and (ARow = 1) then // Summenfeld 
    with StringGrid1, Canvas do 
    begin 
      Brush.Color := clNavy; 
      Font.Color := clYellow; 
      FillRect(Rect); 
      Textout(Rect.Left + 2, Rect.Top + 2, Cells[ACol, ARow]); 
    end; 
end; 
 
procedure TForm1.StringGrid1SetEditText(Sender: TObject; ACol, ARow: Integer; 
  const Value: string); 
var 
  x, y: Integer; 
  Ergebnis: Double; 
begin 
  with Felder do 
  begin 
    if ok and (ACol in [Anfang.Col .. Ende.Col]) and 
      (ARow in [Anfang.Row .. Ende.Row]) then 
    begin 
      Ergebnis := 0; 
      for y := Anfang.Row to Ende.Row do 
        for x := Anfang.Col to Ende.Col do 
        begin 
          if not isZahl(pchar(StringGrid1.Cells[x, y])) then 
            Continue; 
          Ergebnis := Ergebnis + StrToFloat 
            (Punktweg(PWideChar(StringGrid1.Cells[x, y]))); 
        end; 
      if Ergebnis <> 0 then 
        StringGrid1.Cells[SummCell.Col, SummCell.Row] := FloatToStr(Ergebnis) 
      else 
        StringGrid1.Cells[SummCell.Col, SummCell.Row] := ''; 
    end; 
  end; 
end;



Zugriffe seit 6.9.2001 auf Delphi-Ecke