AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi CSV Dateien über OLE importieren, falsches Format in Feldern
Thema durchsuchen
Ansicht
Themen-Optionen

CSV Dateien über OLE importieren, falsches Format in Feldern

Ein Thema von ArneWolf · begonnen am 16. Jul 2008 · letzter Beitrag vom 17. Jul 2008
Antwort Antwort
ArneWolf

Registriert seit: 6. Feb 2008
5 Beiträge
 
#1

CSV Dateien über OLE importieren, falsches Format in Feldern

  Alt 16. Jul 2008, 11:42
Hallo,

ich arbeite an einem Programm, welches Datensätze aus extra dafür erstellten Excelvorlagen über OLE ausliest und in ein entsprechendes Übertragungsformat umwandelt (Übertragungsdatei ist reines Textformat).
Nun kam von Kundenseite der Wunsch hinzu auch CSV Dateien einlesen und übertragen zu können. An sich kein Problem, solange sich die erstellte CSV Datei an der Excelvorlage orientiert. Sprich es sollen bei der Umwandlung die gleichen Codierungs-Funktionen bei der CSV-Datei zum Einsatz kommen, wie auch schon bei den bisherigen Excel-Dateien, um sich größere Arbeiten an der eigentlichen Programmlogik selbst zu ersparen.

Nun tritt das Problem auf, dass die Daten der CSV-Datei von Excel falsch interpretiert werden und die einzelnen Felder mit diversen leider unpassenden Formaten belegt werden und diese falsch dargestellten Daten vom Programm anschließend auch so übernommen werden. Als Beispiel aus dem Uhrzeit-String "12:20" wird "0,513888888888889" ausgelesen oder aus "01.06.2007" wird "39234" usw. Das merkwürdige ist auch, öffne ich die CSV-Datei mit Excel, werden die meisten Daten noch korrekt dargestellt. Wandle ich jetzt aber das Arbeitsblatt in das eigentlich benötigte Text-Format um, so ist ein Großteil der Datensätze unbrauchbar geworden.
Deshalb funktioniert es leider auch nicht, das Arbeitsblatt zu Beginn als Text-Format zu formatieren.

Delphi-Quellcode:
ExcelApp:=CreateOLEObject('Excel.Application');
ExcelApp.Visible:=false;
ExcelApp.DisplayAlerts:=False;
ExcelApp.Workbooks.Open(Excelvorlage.text);
ExcelApp.Workbooks[1].Worksheets[1].Select;
ExcelApp.Selection.NumberFormat := '@';
Andere Versuche waren es einzelne Felder mit .NumberFormat zu formatieren, was auch nicht zum Erfolg führte.
Z.B. in der CSV-Datei steht "06:00". Excel interpretiert dies als benutzerdefiniertes Format und macht daraus "06:00:00" (auch wenn weiterhin "06:00" angezeigt werden). Delphi liest aus diesem Benutzerdefinierten-Feld nun aber "0,25" aus. Ändert man nun das Zellenformat in Text macht Excel von sich aus daraus ebenfalls wieder eine falsche "0,25", die so natürlich auch ausgelesen wird.

Das voranstellen eines Hochkommas brachte ebenso nichts, da hierbei auch nicht die richtigen Ursprungsdaten ausgelesen werde, sondern die falsch dargestellten einschließlich dem hinzugefügten Hochkomma.

Und mein dritter nicht brauchbarer Lösungsansatz war es, die CSV-Datei einfach temporär ins Excel-Format zu speichern und dann wieder einzulesen. Dies klappte allerdings auch nicht, da diese Datei von Excel nicht mehr erkannt wird.


Ich häng an diesem Problem/Denkfehler schon den ganzen Vormittag fest und habe noch keine brauchbare Lösung gefunden. Aber es sollte doch irgendwie möglich sein, Daten aus CSV-Files mit dem Umweg über Excel in ein Delphi-Programm zu importieren?

Danke und Gruß
Arne
  Mit Zitat antworten Zitat
Benutzerbild von iKilledKenny
iKilledKenny

Registriert seit: 25. Apr 2007
Ort: Bergstrasse
49 Beiträge
 
Delphi 5 Professional
 
#2

Re: CSV Dateien über OLE importieren, falsches Format in Fel

  Alt 16. Jul 2008, 11:50
Wenn ich das richtig verstehe, soll zusätzlich zu der Variante Excel->Text eine neue Variante CSV->Text entstehen. Warum dann der Umweg über Excel? Mache doch die Umwandlung selbst.
Alexander Stork
  Mit Zitat antworten Zitat
ArneWolf

Registriert seit: 6. Feb 2008
5 Beiträge
 
#3

Re: CSV Dateien über OLE importieren, falsches Format in Fel

  Alt 16. Jul 2008, 12:27
@ iKilledKenny
Ja du hast das schon richtig verstanden und wäre ja auch normal die beste Lösung. Nur ist bei uns der Programmteil, welcher die unzähligen Nachrichtenvorlagen auswertet und in eines von n Übertragungsformaten umwandelt schon über 50k Zeilen Source groß und bisher nur zur Verarbeitung von Excel-Dateien vorbereitet. Darum wären hier Änderungen viel zu aufwendig und der Umweg über Excel notwendig.
Es scheitert ja im Prinzip auch nur daran, dass Excel die Felder mit unpassenden Formaten belegt, weshalb die Daten falsch ausgelesen werden. Dies muss doch irgendwie zu unterbinden sein?
  Mit Zitat antworten Zitat
Benutzerbild von iKilledKenny
iKilledKenny

Registriert seit: 25. Apr 2007
Ort: Bergstrasse
49 Beiträge
 
Delphi 5 Professional
 
#4

Re: CSV Dateien über OLE importieren, falsches Format in Fel

  Alt 16. Jul 2008, 13:56
siehe Delphi-Treff

Ziemlich unten ("Um eine Zelle im generellen Zahlenformat zu formatieren:"), ich denke das ists, was du suchst.
Alexander Stork
  Mit Zitat antworten Zitat
oki

Registriert seit: 30. Dez 2002
Ort: Brandshagen
1.819 Beiträge
 
Delphi 2007 Professional
 
#5

Re: CSV Dateien über OLE importieren, falsches Format in Fel

  Alt 16. Jul 2008, 13:59
Hi ArneWolf,

ich verstehe dein Problem nicht. CSV ist doch auch nur eine Textdatei. Du wandelst Text in Text. Da ist doch nichts dran. Was kann dir passieren? Doch nur variable <-> feste Länge der Felder; Strings in Hochkommata. Das machst du doch auf dem direkten Weg nebenbei beim Frühstück. Deinen Aufwand über Exel versteh ich da nicht. Auch wenn die Unit 50k Code enthält macht die kleine Funktion den Kohl doch nicht fett.

gruß oki
42
  Mit Zitat antworten Zitat
ArneWolf

Registriert seit: 6. Feb 2008
5 Beiträge
 
#6

Re: CSV Dateien über OLE importieren, falsches Format in Fel

  Alt 17. Jul 2008, 09:16
Hallo,

vielen Dank für die rege Beteiligung und die guten Lösungsansätze. Habe es jetzt mit einer Hilfsfunktion gelöst, die mir die CSV-Datei auf einer temporären als Text formatierten Excel-Arbeitsmappe einliest und zwischenspeichert. Hat den Vorteil, dass man dieser leeren Arbeitsmappe bei Bedarf alle möglichen Formatierungen mitgeben kann.

Ich stelle die Funktion auch mal hier zur Verfügung, falls jemand ein ähnliches Problem mit dem einlesen von CSV nach Excel und den daraus folgenden falschen Feld-Formatierungen haben sollte.
Hat allerdings bisher noch 3 Einschränkungen, da diese bei unserem Einsatzzweck alle nicht auftreten können. Sollte aber kein Ding sein dies bei Bedarf noch zu erweitern.
- Separator-Zeichen innerhalb von Nutzdaten werden nicht abgefangen
- keine Berücksichtigung von Datenklammerzeichen
- CSV-Dateien, die nur aus einer einzigen Spalte bestehen, werden falsch eingelesen

Delphi-Quellcode:
function CsvToExcel(Eingabe:string):boolean;
var
  CsvArray:TStringDynArray;
  ArrayMax, SegmentNr, Zeile, Spalte, PosUmbruch, Zeilenumbruchnacher:integer;
  CsvExcel:variant;
begin
  Eingabe := StringReplace(Eingabe,#$D#$A,'<><><>',[rfReplaceAll]); //Zeilenumbruch abfangen, da hiermit innerhalb des Arrays nicht mehr gearbeitet werden kann
  CsvArray := explode(';', Eingabe); //explode und StringReplace bei großen Dateien besser durch etwas schnelleres ersetzen!
  SegmentNr := 0;
  Zeile := 1;
  Spalte := 1;
  CsvExcel := CreateOLEObject('Excel.Application');
  try
    CsvExcel.Visible:=false;
    CsvExcel.DisplayAlerts:=false;
    CsvExcel.Workbooks.Open(ExtractFilePath(ParamStr(0))+'resources\csv.xls');
    CsvExcel.Workbooks[1].Worksheets[1].Select;

    repeat
      if (CsvArray[0+SegmentNr] <> '') and (copy(CsvArray[0+SegmentNr],1,6) <> '<><><>') then begin
        if (POS('<><><>',CsvArray[0+SegmentNr]) > 0) then begin
          PosUmbruch := PosEx('<><><>', CsvArray[0+SegmentNR]);
          CsvExcel.cells[Zeile,Spalte] := copy(CsvArray[0+SegmentNR], 1, PosUmbruch-1);
          Spalte := 1;
          Zeile := Zeile+1;
          CsvExcel.cells[Zeile,Spalte] := copy(CsvArray[0+SegmentNR], PosUmbruch+6);
          SegmentNr := SegmentNr+1;
          Spalte := Spalte+1;
          continue;
        end
        else begin
          CsvExcel.cells[Zeile,Spalte] := CsvArray[0+SegmentNR];
          SegmentNr := SegmentNr+1;
          Spalte := Spalte+1;
          continue;
        end;
      end
      else if (copy(CsvArray[0+SegmentNr],1,6) = '<><><>') then begin
        Spalte := 1;
        Zeile := Zeile+1;
        CsvExcel.cells[Zeile,Spalte] := copy(CsvArray[0+SegmentNR],7);
        SegmentNr := SegmentNr+1;
        Spalte := Spalte+1;
        continue;
      end
      else begin
        SegmentNr := SegmentNr+1;
        Spalte := Spalte+1;
        continue;
      end;
    until (SegmentNr = length(CsvArray)-1);

    except begin
      CsvExcel.quit;
      CsvExcel := unassigned;
      Result := false;
      exit;
    end;
  end;
  CsvExcel.ActiveWorkBook.SaveAs(ExtractFilePath(ParamStr(0))+'resources\'+'tmp.xls');
  CsvExcel.quit;
  CsvExcel := unassigned;
  Result := true;
end;
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:19 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz