Plik csv z multilinią wczytanie do StringGrid

0

Witam.

Ma ktoś jakiś fajny sposób wczytywania takiego pliku.
W pliku są pola gdzie występują multilie, z zaszytym kodem #10
Natomiast kolumna SN ma użyte separatory tysięczne.

Stworzyłem procedurę wczytywana ale mi się nie podoba. Zrobiona po prostu na siłę.

Ładowanie danych przez:

Stream := TFileStream.Create( NameCsv , fmOpenRead );

sypie się i otrzymuje nie prawidłowe dane. Podobnie jest z:

sl := TStringList.Create;  sl.LoadFromFile(nameCSV);

Pozdrawiam
Janusz

0

co znaczy sypie się ?

EDT... już widzę, #10 w pierwszym wierszu tekstu

0

spróbuj

sl := TStringList.Create; 
sl.LineBreak:=#13;
sl.LoadFromFile(nameCSV);

0

dla sl ustaw separator nowego wiersza na #13 i działa

0

Wgrywam podany załącznik w ten sposób.


procedure TgGrid.CsvLoadHdd ( NameCsv : string );
var  Lines : TStringList;
     I     : Longint;

function OccurencesOfChar(ContentString:string; CharToCount:char):integer;
begin
   OccurencesOfChar := Length(ContentString)-
       Length(StringReplace(ContentString, CharToCount,'', [rfReplaceAll, rfIgnoreCase]));
end;

begin
     if nameCsv = '' then nameCsv := FCsvSaveName;
     Lines := TStringList.Create;
     try
        Lines.Delimiter:=FCsvSeparate; // ';';
        Lines.QuoteChar:=FCsvTextSeparate; // '"';
        Lines.LineBreak := #13;
    		Lines.LoadFromFile( nameCsv );
        ColCount := OccurencesOfChar(Lines[0], FCsvSeparate )+1;
        RowCount := Lines.Count-1;
    		for i := 0 to  Lines.Count -1 do
           begin
              Rows[i].Delimiter := FCsvSeparate;
              Rows[i].QuoteChar := FCsvTextSeparate;
              Rows[i].DelimitedText := Lines[i];
           end;
     finally
    		Lines.Free;
    	end;
     AutoSizeCol;
end;

Teraz wszystko jest już OK. grzegorz_so Dzięki za pomoc.

0

a po co ten fragment kodu ??

        ColCount := OccurencesOfChar(Lines[0], FCsvSeparate )+1;
        RowCount := Lines.Count-1;

zmienne ColCount i RowCount nie są nigdzie dalej użyte. Kompilator optymalizując kod wywali te dwa podstawienia z wykonywalnego kodu
a tym samym funkcja OccurencesOfChar staje się zupełnie niepotrzebna

0

To jest ładowanie danych do TStringGrid

0
RowCount := Lines.Count-1;

Zmienna RowCount jest kłamliwa – zamiast przechowywać liczbę wierszy, przechowuje indeks ostatniego wiersza. Skoro tak nazywasz zmienną to trzymaj w niej wartość niezerową dla niezerowej ilości.

Poza tym, jeśli Lines.Count zwróci 0 to do zmiennej trafi -1. Tak więc jeśli dalsze instrukcje porównują wartość zmiennej do 0, to warunek przestanie być spełniany. Już nie mówiąc o tym, że jeśli RowCount jest jakimkolwiek uint-em to ten kod przekręci mu licznik.

0

wiem , ale nigdzie nie widzę użycia tych dwóch zmiennych/ pól klasy
może gdzieś indziej w kodzie są Ci potrzebne, ale na pewno nie są potrzebne w podanym kodzie

0

Przed załadowanie csv do siatki mam takie ustawianie.
screenshot-20171225210144.png
To kiedy według Ciebie mam ustawiać ColCount i RowCount .

0

rozumiem że potrzebujesz przechować w zmiennej liczbę wierszy w pliku csv, ale żle to robisz

powinno być

RowCount := Lines.Count
0

furious programming Faktycznie masz rację, myślę że teraz będzie ok.

procedure TgGrid.CsvLoadHdd ( NameCsv : string );
var  Lines : TStringList;
     I     : Longint;
function OccurencesOfChar(ContentString:string; CharToCount:char):integer;
begin
   OccurencesOfChar := Length(ContentString)-
       Length(StringReplace(ContentString, CharToCount,'', [rfReplaceAll, rfIgnoreCase]));
end;

begin
     if nameCsv = '' then nameCsv := FCsvSaveName;
     Lines := TStringList.Create;
     try
        Lines.Delimiter:=FCsvSeparate; // ';';
        Lines.QuoteChar:=FCsvTextSeparate; // '"';
        Lines.LineBreak := #13;
    	Lines.LoadFromFile( nameCsv );
        if Lines.Count >= 2 then // nie ładować csv jeżeli są w nim tylko same nagłówki kolumn bez danych
          begin
             if copy(Lines[0],1,3) = '"Dz' then Lines.Delete(0);
             ColCount := OccurencesOfChar(Lines[0], FCsvSeparate )+1;
             RowCount := Lines.Count-1;
         	   for i := 0 to  Lines.Count -1 do
                 begin
                   Rows[i].Delimiter := FCsvSeparate;
                   Rows[i].QuoteChar := FCsvTextSeparate;
                  Rows[i].DelimitedText := Lines[i];
                 end;
          end;
     finally
    		Lines.Free;
    	end;
     AutoSizeCol; 
end;

Dzięki na zwrócenie uwagi.
Pozdrawiam
Janusz

0

Tak wychodzi jak nie ma -1

screenshot-20171225211452.png

0
RowCount := Lines.Count - YourGrid.FixedRows;

Zróbmy uniwersalnie. ;)

0

Biorąc pod uwagę że z pliku csv wgrywam też nagłówki to nie mogę tak zrobić.
Wychodzi coś takiego. W pliku jest osiem linii danych.

w Object Inspector ustawiłem FixedRows na 3

RowCount := Lines.Count - FixedRows;

screenshot-20171226091807.png

Teoretycznie powinienem jeszcze sprawdzać jaka jest wartość FixedRows i całość odpowiednio przesuwać.
Daruję to sobie.

0
dasej napisał(a):

Teoretycznie powinienem jeszcze sprawdzać jaka jest wartość FixedRows i całość odpowiednio przesuwać.

No nie tylko teoretycznie, bo indeks pierwszego wiersza z danymi to dokładnie Grid.FixedRows. Póki co ten kod działa prawidłowo, bo poprawnie określa liczbę wszystkich wierszy – nie jest ich ani za dużo, ani za mało.

1 użytkowników online, w tym zalogowanych: 0, gości: 1