![]() |
Hat Jemand eine Ahnung wie ich diese Datei in ein Stringgrid bekomme.
Liste der Anhänge anzeigen (Anzahl: 1)
Ich schreibe zur Zeit ein Programm, das Messprotokolle auswertet. Dabei bekomme ich von einem Aufzeichnungsgerät diese angehängte Dateien.
Mit Excel bekomme ich sie ohne Probleme, in eier Tabellenstruktur geöffnet. Es ist aber keine CSV-Datei. Bis jetzt lade ich sie über Excel in ein Stringgrid, entnehme für mich nötige Informationen und füge diese in ein Listview. Das dauert bei 2000 Dateien aber ewig lange. Andere Messdateien die in CSV vorliegen kann ich direkt ins Stringgrid laden, das dauert nur ein paar Sekunden.
Delphi-Quellcode:
function Xls_To_StringGrid(AGrid: TStringGrid; AXLSFile: string): Boolean;
const xlCellTypeLastCell = $0000000B; var XLApp, Sheet: OLEVariant; RangeMatrix: Variant; x, y, k, r: Integer; begin Result := False; XLApp := CreateOleObject('Excel.Application'); try XLApp.Visible := False; XLApp.Workbooks.Open(AXLSFile); Sheet := XLApp.Workbooks[ExtractFileName(AXLSFile)].WorkSheets[1]; Sheet.Cells.SpecialCells(xlCellTypeLastCell, EmptyParam).Activate; x := XLApp.ActiveCell.Row; y := XLApp.ActiveCell.Column; AGrid.RowCount := x; AGrid.ColCount := y; RangeMatrix := XLApp.Range['A1', XLApp.Cells.Item[X, Y]].Value; k := 1; repeat for r := 1 to y do AGrid.Cells[(r - 1), (k - 1)] := RangeMatrix[K, R]; Inc(k, 1); AGrid.RowCount := k + 1; until k > x; RangeMatrix := Unassigned; finally if not VarIsEmpty(XLApp) then begin XLApp.Quit; XLAPP := Unassigned; Sheet := Unassigned; Result := True; end; end; end; |
AW: Hat Jemand eine Ahnung wie ich diese Datei in ein Stringgrid bekomme.
Das ist schon eine CSV. Spaltentrenner sieht nach einem Tab-Zeichen aus :)
|
AW: Hat Jemand eine Ahnung wie ich diese Datei in ein Stringgrid bekomme.
Mit dieser Funktion öffne ich die anderen Messdateien
Delphi-Quellcode:
bei dieser Datei erhalte ich die Fehlermeldung "Listenindex überschreitet das Maximum".
procedure tform1.LoadCSV(Filename: string; sg: TStringGrid);
var i, j, Position, count, edt1: integer; temp, tempField : string; FieldDel: char; Data: TStringList; begin Data := TStringList.Create; FieldDel := ';'; Data.LoadFromFile(Filename); temp := Data[1]; count := 0; for i:= 1 to length(temp) do if copy(temp,i,1) = FieldDel then inc(count); edt1 := count+1; sg.ColCount := 30; sg.RowCount := Data.Count +1; sg.FixedCols := 0; for i := 0 to Data.Count - 1 do begin; temp := Data[i]; if copy(temp,length(temp),1) <> FieldDel then temp := temp + FieldDel; while Pos('"', temp) > 0 do begin Delete(temp,Pos('"', temp),1); end; for j := 1 to edt1 do begin Position := Pos(FieldDel,temp); tempField := copy(temp,0,Position-1); sg.Cells[j-1,i+1] := tempField; Delete(temp,1,length(tempField)+1); end; end; Data.Free; end; |
AW: Hat Jemand eine Ahnung wie ich diese Datei in ein Stringgrid bekomme.
Nö, das ist kein CSV und Tabs kommen dadrin auch nicht vor.
Das ist 'ne ordinäre DBase-Datei. Entweder mit der BDE (Achtung arg veraltet) TTable, TDataSource ... verarbeiten. Dann kann man die Daten statt in 'nem StringGrid in 'nem TDBGrid anzeigen und wie eine Datenbanktabelle verarbeiten. Oder ![]() Die Felder der Tabelle sind ID, LFDNR, P, Q und Flags, alles nummerische. Wenn's eher händisch sein soll, dann die ersten 193 Byte (DBase-Header) überlesen. Anschließend ergeben jeweils 59 Byte die Werte eines "Datensatzes", sie sind linksbündig mit Leerzeichen aufgefüllt. Löschkennzeichen = Byte 1, wenn * dann Löschkennzeichen gesetzt, sonst nicht. ID = Byte 2 bis 7 (Integer) LFDNR = Byte 8 bis 13 (Integer) P = Byte 14 bis 33 (Fließkomma) Q = Byte 34 bis 53 (Fließkomma) FLAGS = Byte 54 bis 59 (Integer) Das letzte Byte der Datei darf getrost ignoriert werden, heißt halt nur: "Hier ist die Datei zu Ende". |
AW: Hat Jemand eine Ahnung wie ich diese Datei in ein Stringgrid bekomme.
Würde es gern ohne zusätzliche Komponente machen. Was aber nicht, wie ich das aufsplitten soll.
|
AW: Hat Jemand eine Ahnung wie ich diese Datei in ein Stringgrid bekomme.
Delphi.Narium schrieb doch eine Anleitung wie Du die Datensätze ohne Zusatz Komponente reinladen kannst, wofür ich mal eben Applaus gebe :)
|
AW: Hat Jemand eine Ahnung wie ich diese Datei in ein Stringgrid bekomme.
Ich habe Dir sehr ausführlich beschrieben, wie die Daten aufzuteilen sind.
Welche Bytes am Anfang zu überlesen sind, welches am Ende zu ignorieren ist und wie die einzelen Datensätze "dazwischen" aufzuteilen sind. ![]() |
AW: Hat Jemand eine Ahnung wie ich diese Datei in ein Stringgrid bekomme.
Hallo
zum Aufsplitten nehme ich immer eine zweite TStringList. |
AW: Hat Jemand eine Ahnung wie ich diese Datei in ein Stringgrid bekomme.
Ich würd's eher mit dem vielfachen von 59 Bytes puffern und intern splitten, geht schneller als dauernd BlockRead() anzuwenden, oder lieg ich wieder falsch?
[EDIT] Abzüglich der ersten 193 Bytes natürlich, also ab File-Offset 193. Menno, BlockRead() kann man ja so nutzen, ich hatte TStream im Kopf als Lese-Methode, also beides geht will ich damit sagen, sorry! [/EDIT] |
AW: Hat Jemand eine Ahnung wie ich diese Datei in ein Stringgrid bekomme.
TDBGrid + ClientDataSet/MemoryDataSet und z.B.
![]() Aber da es eh keine CSV ist, bleibt es beim DBGrid :stupid: |
AW: Hat Jemand eine Ahnung wie ich diese Datei in ein Stringgrid bekomme.
DBase kann man übrigens auch über ODBC lesen.
Dazu reicht die Nutzung der ADO-Komponenten. Damit kann man dann auch per SQL auf die Daten zugreifen. (Braucht keine BDE und keine weiteren Komponenten isntallieren.) Für professionelle Software würd' ich mir jedenfalls kein "Hilfsmittel" basteln, das genau mit dieser einen Form von DBase-Dateien zurecht kommt. Der Nächste, der dann mit DBase kommt und nur die Felder in 'ner anderen Reihenfolge liefert, bekommt dann auch eine eigene Implementierung ...? Das ist doch eher etwas "ungeeignet". |
AW: Hat Jemand eine Ahnung wie ich diese Datei in ein Stringgrid bekomme.
Vielleicht wäre es ganz hilfreich, erst einmal zu wissen welche Dateiformate für die Eingabe vorliegen.
Der nächste Schritt wäre, ein für die weitere Verarbeitung geeignetes Format zu definieren, in das alle Deine Eingaben überführt werden. Da in der Beispieldatei etwas mehr als 2600 Einträge sind und es wohl mehrere EingabeDateien gibt, könnte man u.U an eine DB denken auch wenn das bei einer so einfachen Datenstruktur nach Overkill aussieht. Allerdings ist die Suche nach einem Wertepaar, dann relativ einfach zu lösen. Also mach Dir erst einmal ein paar Gedanken zu Deinem Konzept. Gruß k-H |
AW: Hat Jemand eine Ahnung wie ich diese Datei in ein Stringgrid bekomme.
Meiner Meinung nach kann man sowas nur sinnvoll und performant machen, wenn man eine "datenbankähnliche" Struktur nimmt.
Also entweder man packt die Dateien in eine Datenbank (wenn auch nur für die Zeit der Verarbeitung) oder nutzt direkt Komponenten, die mit dem Dateiformat umgehen können. ClientDataSet, die ADO-Komponenten, bei älteren Delphis (wie's im Profil steht Delphi 6) gerne auch noch die BDE. Dort kann man auch Strukturdateien definieren, die den Aufbau von Textdateien enthalten. Mit der Kombination Textdatei und Strukturdatei kann man dann auf die Textdateien wie auf Datenbanktabellen zugreifen. Man kann damit dann auch mit einfachem SQL auf Textdateien zugreifen. So eine Strukturdatei kann so aussehen (Beispiel für eine alte Bankleitzahlendatei):
Code:
Im Programm könnte man hiermit dann z. B. per FieldByName('FIELD10').AsString auf den Ort zugreifen.
[BLZ0509PC]
FILETYPE = FIXED CHARSET = china DELIMITER = SEPARATOR = Field1 = BANKLEITZAHL, CHAR, 8,0, 0 Field2 = EIGENEBANKLEITZAHL,CHAR, 1,0, 8 Field3 = LOESCHBANKLEITZAHL,CHAR, 8,0, 9 Field4 = LBZGIROKONTO, CHAR, 1,0, 17 Field5 = LOESCHDATUM, CHAR, 4,0, 18 Field6 = NACHFOLGEINSTITUT, CHAR, 5,0, 22 Field7 = NAMEKURZ, CHAR, 58,0, 27 Field8 = KURZBEZEICHNUNG, CHAR, 20,0, 85 Field9 = POSTLEITZAHL, CHAR, 5,0,105 FIELD10 = ORT, CHAR, 29,0,110 FIELD11 = BTX_EZU, CHAR, 27,0,139 FIELD12 = PAN, CHAR, 5,0,166 FIELD13 = VEROEFFENTLICHT, CHAR, 1,0,171 FIELD14 = BIC, CHAR, 9,0,172 FIELD15 = KENNZIFFER, CHAR, 2,0,181 FIELD16 = LFDNR, CHAR, 5,0,183 Aber 'ne eigene Schnittstelle für DBase-Dateien programmieren, würd' ich jetzt nicht unbedingt empfehlen. Wenn aber unbedingt doch, dann hier eine passende Beschreibung dessen, was man dann so vor sich hat: ![]() |
AW: Hat Jemand eine Ahnung wie ich diese Datei in ein Stringgrid bekomme.
[EDIT]
Diesen Code nicht benutzen da er anscheinend schlecht ist. Tut mir leid. [/EDIT]
Delphi-Quellcode:
So könnte die ClientDataSet-Variante umgesetzt werden, in diesem Beispiel-Code gleich Threaded.
unit Unit1;
interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, DBTables, Db; const WM_OPENDATASET = WM_USER + 1; WM_EXECUTESQL = WM_USER + 2; type TThreadDataSet = class(TThread) private procedure WMOpenDataSet(Msg: TMsg); procedure WMExecSQL(Msg: TMsg); protected procedure Execute; override; public procedure Open(DataSet: TDataSet); procedure ExecSQL(DataSet: TDataSet); end; TForm1 = class(TForm) procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private FThread : TThreadDataSet; public end; var Form1: TForm1; implementation {$R *.DFM} procedure TThreadDataSet.ExecSQL(DataSet: TDataSet); begin PostThreadMessage(ThreadID, WM_EXECUTESQL, Integer(DataSet), 0); end; procedure TThreadDataSet.Execute; var Msg : TMsg; begin FreeOnTerminate := True; PeekMessage(Msg, 0, WM_USER, WM_USER, PM_NOREMOVE); while not Terminated do begin if GetMessage(Msg, 0, 0, 0) then case Msg.Message of WM_OPENDATASET: WMOpenDataSet(Msg); WM_EXECUTESQL: WMExecSQL(Msg); end; end; end; procedure TThreadDataSet.Open(DataSet: TDataSet); begin PostThreadMessage(ThreadID, WM_OPENDATASET, Integer(DataSet), 0); end; procedure TThreadDataSet.WMExecSQL(Msg: TMsg); var Qry : TQuery; begin try Qry := TQuery(Msg.wParam); try Qry.Open; except Qry.ExecSQL; end; except On E: Exception do ShowMessage(E.Message); end; end; procedure TThreadDataSet.WMOpenDataSet(Msg: TMsg); var Ds : TDataSet; begin try Ds := TDataSet(Msg.wParam); Ds.Open; except On E: Exception do ShowMessage(E.Message); end; end; // MAIN PART procedure TForm1.FormCreate(Sender: TObject); begin FThread := TThreadDataSet.Create(False); FThread.Open(Table1); // Öffne ein DataSet (table oder query) FThread.ExecSQL(Query1); // Execute die SQL end; procedure TForm1.FormDestroy(Sender: TObject); begin FThread.Terminate; end; end. Um damit Sinnvoll umzugehen die Hilfe-Datei lesen. |
AW: Hat Jemand eine Ahnung wie ich diese Datei in ein Stringgrid bekomme.
Hallo,
Zitat:
|
AW: Hat Jemand eine Ahnung wie ich diese Datei in ein Stringgrid bekomme.
Zitat:
Dieser Code zeigt wie man es per Thread steuern könnte. Das ist nur ein skelett auf das minimum reduziert nur um zu zeigen wie's per Thread gehen könnte, ich hatte an Performance gedacht, jeglicher Code der Table1 oder Query1 enthält ist bewusst entfernt da es aus meinem DataSet-Sample entspringt. |
AW: Hat Jemand eine Ahnung wie ich diese Datei in ein Stringgrid bekomme.
Moin...:P
Zitat:
Zitat:
|
AW: Hat Jemand eine Ahnung wie ich diese Datei in ein Stringgrid bekomme.
Zitat:
Dann kommt noch dazu das der Code für die Threadnutzung vor Fehlern nur so wimmelt. FreeOnTerminate true und freigeben im Form Destroy. ---- >Aua Davon Ausgehen dass der Thread schon Messages entgegen nehmen kann, ohne jede Synchronisierung . ---- Aua Was ich damit meine:
Delphi-Quellcode:
Es ist nicht! Sichergestellt das der Thread schon läuft, weshalb das PostThreadMessage im Open fehl schlagen kann.
FThread := TThreadDataSet.Create(False);
FThread.Open(Table1); // Öffne ein DataSet (table oder query) Keinerlei Überprüfung der Rückgabe. Beim beenden keine Synchronisierung Das ist einfach nur Code den man so nicht zeigen sollte. Und vor allem es geht komplett am Ursprungsthema vorbei! |
AW: Hat Jemand eine Ahnung wie ich diese Datei in ein Stringgrid bekomme.
Zitat:
Und warum macht Execute ein Open? |
AW: Hat Jemand eine Ahnung wie ich diese Datei in ein Stringgrid bekomme.
In einem meiner alten Delphi 7 Anwendungen hab ich die Class so in Benutzung, funktioniert tadellos, FormCreate/FormDestroy sollte lediglich zeigen wie man auf den Thread zugreifen könnte, hab's nun mit Warnung versehen und bin still.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:38 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz