Einzelnen Beitrag anzeigen

tgvoelker

Registriert seit: 9. Sep 2002
Ort: Oelsnitz, Vogtland
44 Beiträge
 
Delphi 12 Athens
 
#12

AW: Suche Datensenitive ExportToExcel-Funktion

  Alt 4. Jul 2012, 09:38
Das Problem liegt in der Implementierung: Excel erwartet für Range.Value eine Variante. Wenn Du einen String übergibst, dann wandelt den die Excel-Logik um - und das führt zu den beschriebenen Problemen.

Ich hatte das Problem bei TJVGExportExcel aus JVCL Globus, da war genau so vorgegangen worden.

Die lösung war, die Source zu ändern:

Code:
            if ForceTextFormat or
               (Dataset.Fields[I].Datatype in [ftString,ftMemo,ftFmtMemo,ftFixedChar,ftWideString,ftGuid
                                             ,ftFixedWideChar,ftWideMemo,ftBoolean,ftVariant,ftUnknown
                                             ,ftBytes,ftVarBytes,ftBlob,ftGraphic,ftParadoxOle
                                             ,ftDBaseOle,ftTypedBinary,ftCursor,ftADT,ftArray,ftReference
                                             ,ftDataSet,ftOraBlob,ftOraClob,ftInterface,ftIDispatch,ftOraInterval
                                             ,ftConnection,ftParams,ftStream])or
               (Dataset.Fields[I].IsNull) then Sheet.Cells[RecNo, ColNo + I] := GetFieldValue(DataSet.Fields[I])
            Else Sheet.Cells[RecNo, ColNo + I].Value :=GetFieldValueVar(DataSet.Fields[I]);
In der ursprünglichen Implementierung wurde nur die Funktion GetFieldValue aufgerufen:

Code:
function TJvgCommonExport.GetFieldValue(const Field: TField): string;
begin
  if jeoOutputFormattedStrings in Options then
    Result := Field.DisplayText
  else
    Result := Field.AsString;
  if Assigned(FOnExportField) then
    FOnExportField(Self, Field, Result);

  if FTransliterateRusToEng then
    Result := Transliterate(Result, True);

  if (FMaxFieldSize > 0) and (Field.DataType in [ftString, ftMemo, ftFmtMemo]) then
    if Length(Result) > FMaxFieldSize then
      Result := Copy(Result, 1, FMaxFieldSize) + '...';
end;
Konkret tritt das Problem bei Gleitkommazahlen und BCD auf, weil bei Field.AsString ein Punkt ausgegeben wird, anstelle eines Komma. Die Funktion GetFieldValueVar übergibt daher eine Variante:

Code:
function TJvgCommonExport.GetFieldValueVar(const Field: TField): Variant;
//Erweiterung zum korrekten export von Nicht-Zeichenkettendaten.
var i:Int64;d:DWord;
begin
  if jeoOutputFormattedStrings in Options then Begin
    Result := Field.DisplayText;
    Exit;
  End;
  if Field.DataType in [ftSmallint,ftInteger,ftWord,ftAutoInc,ftShortint,ftByte] then Result:=Field.AsInteger
  Else if Field.Datatype=ftLargeint Then Result:=Field.Value
  Else if Field.DataType=ftLongWord Then Begin
    d:=Field.Value;
    i:=d;
    Result:=i;
  End Else if Field.DataType in [ftFloat,ftExtended] Then Result:=Field.AsExtended
  Else if Field.DataType = ftCurrency Then Result:=Field.AsCurrency
  Else if Field.DataType in [ftBCD,ftFMTBcd] Then Result:=BcdToDouble(Field.AsBCD)
  Else if Field.DataType in [ftDate,ftTime,ftDateTime,ftTimeStamp,ftOraTimeStamp] Then Result:=Field.AsDateTime
  Else Result:=Null;
//  if Assigned(FOnExportField) then FOnExportField(Self, Field, Result); //Abgeschaltet, da hier zwingend ein String erwartet wird.
end;
Allerdings ist hier anzumerken, daß der export von 16T Tupeln mit 60 Spalten ewig dauerte - nach 2 Stunden habe ich den abgebrochen. Verwende nun die Native Excel Suite, da ist der Export dieser Datenmenge nach 20 Sekunden fertig.
Thomas Völker
  Mit Zitat antworten Zitat