Entwickler-Ecke
Sonstiges (Delphi) - Problem bei Typecasting
LuMa86 - Di 14.05.13 23:14
Titel: Problem bei Typecasting
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:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8:
|
if Excel.Cells[row, 8].Value <> '' then 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 - 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:
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.
jaenicke - Mi 15.05.13 06:50
Wie wäre es mit TryStrToFloat?
jasocul - Mi 15.05.13 17:26
Oder StrToFloatDef?
jaenicke - 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 - Mi 15.05.13 20:39
jaenicke hat folgendes geschrieben : |
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:
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[1, 2].Value; ErgebnisTyp := VarType(Ergebnis) and VarTypeMask;
case ErgebnisTyp of varEmpty : StringTyp := 'varEmpty'; varNull : StringTyp := 'varNull'; varSmallInt : StringTyp := 'varSmallInt'; varInteger : StringTyp := 'varInteger'; varSingle : StringTyp := 'varSingle'; varDouble : StringTyp := 'varDouble'; varCurrency : StringTyp := 'varCurrency'; varDate : StringTyp := 'varDate'; varOleStr : StringTyp := 'varOleStr'; 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);
end; |
Quelle:
http://www.delphibasics.co.uk/RTL.asp?Name=VarType
jasocul - Mi 15.05.13 22:07
jaenicke hat folgendes geschrieben : |
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
Tranx jedenfalls nicht für besonders gut. Try..Except sollte wirklich nur Ausnahmen behandeln.
jaenicke - Do 16.05.13 06:16
jasocul hat folgendes geschrieben : |
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 Tranx 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:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| function StrToFloatDef(const S: string; const Default: Extended; const AFormatSettings: TFormatSettings): Extended; begin if not TextToFloat(PChar(S), Result, fvExtended, AFormatSettings) then Result := Default; end;
function TryStrToFloat(const S: string; out 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.
jasocul - 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 - So 19.05.13 18:25
Ah, von "Try" hatte ich noch nie gehört. Damit geht es wunderbar :) Danke
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!