Autor Beitrag
LuMa86
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 76



BeitragVerfasst: Di 14.05.13 23:14 
Moin,
ich betreibe Leistungssport, daher führe ich auch ein Trainingsprotokoll. Unser Trainer bekommt das von uns wöchentlich als Excel Datei zugeschickt, um dann einen Monats- bzw. Jahresüberblick zu erstellen/berechnen, funktioniert ja wunderbar mit Excel. Ich habe mir ein Programm geschreiben, was dieses Protokoll ausfüllt. Dafür nutze ich OLE, und das klappt auch alles. Allerdings möchte ich die Excel.DAteien auch lesen können. DAfür habe ich folgendes gemacht:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
{TPData ist ein ClientDataSet, TPDataDauer das Feld, was die Dauer eines Trainings enthält.
Es soll zuerst geprüft werden, ob das Feld überhaupt beschreiben ist, denn wenn das Feld (das ist
übrignes Standartformatiert, nichts besonderes) leer ist, dann entsteht bei dem ".AsFloat" eine Null. 
Diese Null landet dann in den Feldern. Und wenn ich das Protkoll dann wieder speicher, ist alles voller
Nullen, da wo eben eigentlichts nichts steht, bzw. ''.}


if Excel.Cells[row, 8].Value <> '' then // Hier liegt der Fehler
  TPDataDauer.AsFloat := Excel.Cells[row, 8].Value;


Die "if-" Abfrage soll verhinder, das durch das ".AsFloat" aus einem LeerString eine Null wird. Beim abspeichern würden man dann alle leeren Felder in der Excel Datei mit Nullen füllen (sollte man die Excel Datei vorher importiert haben und dabei alle '' zu Nullen gemacht haben). Das ist unübersichtlich und nervig. Allerdings gibt es, wenn ich die "if-" Anweisung NICHT ausklammere/entferne folgenden Fehler: "Exception [...] Variante des Types (UnicodeString) konnte nicht in Typ (Double) konvertiert werden."
Ich hoffe ihr versteht was ich meine und ic hab mich einigermaßen verständlich ausgedrückt :)

Danke :)
Tranx
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 648
Erhaltene Danke: 85

WIN 2000, WIN XP
D5 Prof
BeitragVerfasst: Mi 15.05.13 06:23 
Die Umwandlung von nicht Zahlen in den entsprechenden Excel-Zellen in Zahlen erzeugt immer einen Fehler. Du kannst folgendes machen:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
try
  TPDataDauer.AsFloat := Excel.Cells[row, 8].Value;          
except
  TPDataDauer.AsFloat := 0;
end;


Dann fängt Delphi den Fehler ab und macht dann - statt die Variable mit dem Wert - der ja keiner ist (z.B. '' oder 'Startzeit' ....) das, was Du willst. Du kannst den Except-Teil auch leer lassen. Ich denke, Du willst bei "fehlerhaften" Zellen keine Datenübergabe machen. Dann fällt die Anweisung TPDataDauer.AsFloat := 0; einfach weg. Der Fehler wird durch das try weggefangen.

_________________
Toleranz ist eine Grundvoraussetzung für das Leben.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19314
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mi 15.05.13 06:50 
Wie wäre es mit TryStrToFloat?
jasocul
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 6393
Erhaltene Danke: 147

Windows 7 + Windows 10
Sydney Prof + CE
BeitragVerfasst: Mi 15.05.13 17:26 
Oder StrToFloatDef?
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19314
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mi 15.05.13 19:28 
Das würde ja gerade die Nullen in die Felder schreiben, was ja nicht gewünscht ist, soweit ich das verstanden habe. Vielleicht lässt sich auch mit VarIsNull oder so abfragen, ob da ein Wert ist.
Gerd Kayser
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 632
Erhaltene Danke: 121

Win 7 32-bit
Delphi 2006/XE
BeitragVerfasst: Mi 15.05.13 20:39 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Vielleicht lässt sich auch mit VarIsNull oder so abfragen, ob da ein Wert ist.

Man kann abfragen, was für ein Typ im Variant enthalten ist.
Beispiel:
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
procedure TMainform.Button2Click(Sender: TObject);
var
  Excel       : Variant;
  Blatt       : Variant;
  ExcelWS     : Variant;
  Ergebnis    : Variant;
  ErgebnisTyp : integer;
  StringTyp   : string;
begin
  try
    Excel := GetActiveOleObject('Excel.Application');
  except
    Excel := CreateOleObject('Excel.Application');
  end;
  Excel.Visible := True;

  Excel.WorkBooks.Open('C:\Test.xlsx');
  Blatt := Excel.Worksheets.Item['Tabelle1'];

  Blatt.Activate;
  ExcelWS := Excel.ActiveSheet;

  Ergebnis := ExcelWS.Cells[12].Value;  // Zeile 1, Spalte 2
  ErgebnisTyp := VarType(Ergebnis) and VarTypeMask;

  // Bei Excel kommen nur wenige davon in Betracht. Einfach ausprobieren.

  case ErgebnisTyp of
    varEmpty     : StringTyp := 'varEmpty';      // Excel
    varNull      : StringTyp := 'varNull';
    varSmallInt  : StringTyp := 'varSmallInt';
    varInteger   : StringTyp := 'varInteger';
    varSingle    : StringTyp := 'varSingle';
    varDouble    : StringTyp := 'varDouble';     // Excel
    varCurrency  : StringTyp := 'varCurrency';   // Excel
    varDate      : StringTyp := 'varDate';       // Excel
    varOleStr    : StringTyp := 'varOleStr';     // Excel
    varDispatch  : StringTyp := 'varDispatch';
    varError     : StringTyp := 'varError';
    varBoolean   : StringTyp := 'varBoolean';
    varVariant   : StringTyp := 'varVariant';
    varUnknown   : StringTyp := 'varUnknown';
    varByte      : StringTyp := 'varByte';
    varWord      : StringTyp := 'varWord';
    varLongWord  : StringTyp := 'varLongWord';
    varInt64     : StringTyp := 'varInt64';
    varStrArg    : StringTyp := 'varStrArg';
    varString    : StringTyp := 'varString';
    varAny       : StringTyp := 'varAny';
    varTypeMask  : StringTyp := 'varTypeMask';
  end;

  ShowMessage('StringTyp:   ' + StringTyp);

  // Excel.Quit;                    // Excel beenden.
end;


Quelle: www.delphibasics.co....RTL.asp?Name=VarType
jasocul
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 6393
Erhaltene Danke: 147

Windows 7 + Windows 10
Sydney Prof + CE
BeitragVerfasst: Mi 15.05.13 22:07 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Das würde ja gerade die Nullen in die Felder schreiben, was ja nicht gewünscht ist, soweit ich das verstanden habe.

Dann nimmt man als Fehlerwert eben "0" und vergleicht dann das Ergebnis auf "0". In dem Fall wird die Zuweisung übersprungen.
Es geht ja hier auch darum, dass ein paar mehr Werte übernommen werden sollen. Das mit einer Try-Variante zu machen ist nicht besonders performant. Wobei ich zugebe, dass ich die Performanz von TryStrToFloat nicht geprüft habe.
Ich halte die Lösung von user profile iconTranx jedenfalls nicht für besonders gut. Try..Except sollte wirklich nur Ausnahmen behandeln.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19314
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Do 16.05.13 06:16 
user profile iconjasocul hat folgendes geschrieben Zum zitierten Posting springen:
Das mit einer Try-Variante zu machen ist nicht besonders performant. Wobei ich zugebe, dass ich die Performanz von TryStrToFloat nicht geprüft habe.
Ich halte die Lösung von user profile iconTranx jedenfalls nicht für besonders gut. Try..Except sollte wirklich nur Ausnahmen behandeln.
Öhm... wenn es um die Performance geht, solltest du dir mal dringend die beiden Funktionen anschauen... Die haben rein gar nichts mit try..except zu tun und nutzen intern den selben Code.
Denn:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
function StrToFloatDef(const S: stringconst Default: Extended;
  const AFormatSettings: TFormatSettings): Extended;
begin
  if not TextToFloat(PChar(S), Result, fvExtended, AFormatSettings) then
    Result := Default;
end;

function TryStrToFloat(const S: stringout Value: Extended;
  const AFormatSettings: TFormatSettings): Boolean;
begin
  Result := TextToFloat(PChar(S), Value, fvExtended, AFormatSettings);
end;
:wink:

Deshalb ist deine Lösung mit StrToFloatDef sogar langsamer, weil erstens intern geprüft wird, ob die Umwandlung erfolgreich ist und dann der Defaultwert genommen wird und du dann zusätzlich erneut vergleichst und ggf. anders zuweist.

Für diesen Beitrag haben gedankt: jasocul
jasocul
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 6393
Erhaltene Danke: 147

Windows 7 + Windows 10
Sydney Prof + CE
BeitragVerfasst: Do 16.05.13 07:09 
Ich hatte ja geschrieben, dass ich mir die Funktion noch nicht angesehen hatte. Durch die Namensgebung bin ich von einer falschen Annahme ausgegangen. Danke für deine Aufklärung. :beer:
LuMa86 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 76



BeitragVerfasst: So 19.05.13 18:25 
Ah, von "Try" hatte ich noch nie gehört. Damit geht es wunderbar :) Danke