?
Solved

Read from a text-file.

Posted on 2001-06-26
21
Medium Priority
?
185 Views
Last Modified: 2010-04-06
I Have a text-file that comes from a exel document.
It looks like this:

04-8103225100     1
04-8109225237     3
04-8114225000     4
04-8101225000/P     4
04-8107225225     1
04-8102225000     1
04-8107225110     1
       
       
       
       
       
04-8111225180     1
       
       
       
       
04-8111225160     1
       
04-452070/B     16
04-452012/B     8
       
04-450020/B     16
04-450020/B     8
       
04-457200/I     2
04-457200/I     1
       
04-452092/B     32
04-452092/B     16
04-452231/A     6
04-452233/A     1
04-452233/A     4
04-452240/A     8
04-452283/A     4
       
04-332225     1
04-332005     1
04-690004     1
       

The column to the left is a article number and the column to the right is a number.

Each line of the text-file must not contain text.
The left column comes from the first column in the exel file and the right column from the second so I dont know if it is a tab between or if it's just spaces.

I like to make a routin that
opens a textfile like the one abowe
and add to a list-view.

so it looks like this:

art-no            no_of
-----------------------
04-8103225100        1
04-8109225237      3
04-8114225000        4
04-8101225000/P        4
04-8107225225        1
04-8102225000        1
04-8107225110        1


Can someone help me with this...

I can split this question in smaller one so you get more points...

0
Comment
Question by:hulken
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 8
  • 5
  • 3
  • +4
21 Comments
 
LVL 6

Expert Comment

by:edey
ID: 6227944
you could try something like this:

var
 sl : TStringList;
 ix : integer;
begin
 sl := TStringList.create;
 sl.loadFromFile('some_fileName_here');
 ix := 0;
 while (ix < sl.count) do
  if sl[ix] = '' then
   sl.delete(ix)
  else
   ix := ix+1;
 sl.commaText := sl.text;
 for ix := 0 to sl.count div 2 do
  with listView1.items.add do
  begin
   caption := sl[ix*2];
   subItems.add(sl[ix*2+1];
  end;
 sl.free;
end;


GL
Mike
0
 

Expert Comment

by:coffeetea
ID: 6228195
function resolve(String strInput):String;
begin
   i,iMid:integer;
   str:String;
   strList:TStringList;
   strList:=TStringList.create;
   for i:=0 to Length(strInput) do
   begin
       str:=copy(strInput,i,1);
       if str=' ' then
       begin
          iMid=i;
          break;
       end;
   end;
   strList.add(trim(copy(strInput,0,iMid)));
   strList.add(trim(copy(strInput,iMid,Length(strInput)-iMid)));  
   result:=strList.text;
end;
//procedure add to listview
var
tempList,strList : TStringList;
index: integer;
ListItem: TListItem;
begin
tempList := TStringList.create;
strList := TStringList.create;
if FileExists(strFilePath) then
begin
     tempList.LoadFromFile(strFilePath);
     index := 0;
     ListView1.items.clear;
     while (index < tempList .count) do
     begin
         ListItem:=ListView1.Items.Add;//???u
         strList.text:=rosolve(tempList.Strings[index]);
         ListItem.Caption:=tempList.Strings[0];
         ListItem.SubItems.Add(tempList.Strings[1]);
         inc(index);
     end;
end;
tempList.free;
strList.free;
end;


0
 

Expert Comment

by:coffeetea
ID: 6228198
function resolve(String strInput):String;
begin
   i,iMid:integer;
   str:String;
   strList:TStringList;
   strList:=TStringList.create;
   for i:=0 to Length(strInput) do
   begin
       str:=copy(strInput,i,1);
       if str=' ' then
       begin
          iMid=i;
          break;
       end;
   end;
   strList.add(trim(copy(strInput,0,iMid)));
   strList.add(trim(copy(strInput,iMid,Length(strInput)-iMid)));  
   result:=strList.text;
end;
//procedure add to listview
var
tempList,strList : TStringList;
index: integer;
ListItem: TListItem;
begin
tempList := TStringList.create;
strList := TStringList.create;
if FileExists(strFilePath) then
begin
     tempList.LoadFromFile(strFilePath);
     index := 0;
     ListView1.items.clear;
     while (index < tempList .count) do
     begin
         ListItem:=ListView1.Items.Add;//???u
         strList.text:=rosolve(tempList.Strings[index]);
         ListItem.Caption:=tempList.Strings[0];
         ListItem.SubItems.Add(tempList.Strings[1]);
         inc(index);
     end;
end;
tempList.free;
strList.free;
end;


0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
LVL 27

Expert Comment

by:kretzschmar
ID: 6228572
well my version :-)

unit lv_fill_file_u;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ComCtrls;

type
  TForm1 = class(TForm)
    ListView1: TListView;
    Button1: TButton;
    OpenDialog1: TOpenDialog;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

//a generic stringsplitter
function SplitStr(Var AString : String; ADelim : String) : String;
var APos : Integer;
begin
  Result := '';
  APos := Pos(ADelim,AString);
  if APos > 0 then
  begin
    Result := Copy(AString,1,APos-1);
    AString := copy(Astring,APos+length(Adelim),MaxLongInt);
  end
  else
  begin
    Result := AString;
    AString := '';
  end;
end;


//the filling routine
procedure do_fill_lv(AFileName : String; AListView : TListView);
var
  sl : TStringList;
  I : Integer;
  s : String;
  li : TListItem;
begin
  sl := TStringList.Create;
  Try
    try
      sl.loadfromfile(AFileName);
      AListView.Items.Clear;
      for i := 0 to sl.count - 1 do
      begin
        s := sl[i];
        li := AlistView.Items.Add;
        li.Caption := SplitStr(s,'     '); //five blanks as delimiter
        li.SubItems.Add(s);
      end;
    finally
      sl.free;
    end;
  except
    raise;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  if opendialog1.execute then
    do_fill_lv(opendialog1.filename,listview1);
end;

end.

meikl ;-)
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 6228648
corected version, because the blank lines:

unit lv_fill_file_u;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ComCtrls;

type
  TForm1 = class(TForm)
    ListView1: TListView;
    Button1: TButton;
    OpenDialog1: TOpenDialog;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

function SplitStr(Var AString : String; ADelim : String) : String;
var APos : Integer;
begin
  Result := '';
  APos := Pos(ADelim,AString);
  if APos > 0 then
  begin
    Result := Copy(AString,1,APos-1);
    AString := copy(Astring,APos+length(Adelim),MaxLongInt);
  end
  else
  begin
    Result := AString;
    AString := '';
  end;
end;


procedure do_fill_lv(AFileName : String; AListView : TListView);
var
  sl : TStringList;
  I : Integer;
  s : String;
  li : TListItem;
begin
  sl := TStringList.Create;
  Try
    try
      sl.loadfromfile(AFileName);
      AListView.Items.Clear;
      for i := 0 to sl.count - 1 do
      begin
        s := sl[i];
        if trim(s) <> '' then
        begin
          li := AlistView.Items.Add;
          li.Caption := SplitStr(s,'     '); //five blanks as delimiter
          li.SubItems.Add(s);
        end;
      end;
    finally
      sl.free;
    end;
  except
    raise;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  if opendialog1.execute then
    do_fill_lv(opendialog1.filename,listview1);
end;

end.

meikl ;-)
0
 

Author Comment

by:hulken
ID: 6230110
kretzschmar,
With your solution I get all
items in the same column in the list-view.

http://130.236.233.202/Test.zip

or

http://130.236.233.202/test.txt

Will cointain a example of the file I like to import.
0
 

Author Comment

by:hulken
ID: 6230115
kretzschmar,


Your solution seems to work fine if I replace:


li.Caption := SplitStr(s,'     '); //five blanks as delimiter


with

li.Caption := SplitStr(s,#9); //Tab as delimiter

But how can I change this to work eaven if it's more than one Tab or if the columns are separated with one or more spaces?
0
 
LVL 27

Accepted Solution

by:
kretzschmar earned 1200 total points
ID: 6230164
well, my generic splitstr can used also like


s := asourcestring;
while s <> '' do
begin
  AFirstPart := splitsr(s,ADelim);
  //Do Something with a firstpart
end;

this partial routines splits the string into all fields, which is separeted by a delimiter

more specific sample

s := '1-2-3-4-5-6-7-8-9';
while s <> '' do
begin
  AFirstPart := splitsr(s,'-');
  listbox1.items.add(AfirstPart);
  //Do Something with a firstpart
end;

the listbox now contains
1
2
3
4
5
6
7
8
9

or to change the filling routine

procedure do_fill_lv(AFileName : String; AListView : TListView);
var
 sl : TStringList;
 I : Integer;
 s : String;
 li : TListItem;
begin
 sl := TStringList.Create;
 Try
   try
     sl.loadfromfile(AFileName);
     AListView.Items.Clear;
     for i := 0 to sl.count - 1 do
     begin
       s := sl[i];
       if (trim(s) <> '') or
          (trim(s)[1] <> #9) then  //maybe one tab remains, not tested
       begin
         li := AlistView.Items.Add;
         li.Caption := SplitStr(s,#9);
         while s <> '' do  
           li.SubItems.Add(SplitStr(s,#9));
       end;
     end;
   finally
     sl.free;
   end;
 except
   raise;
 end;
end;


>if it's more than one Tab or if the columns are separated with
one or more spaces?
well ,tabs should be not a problem, the problem is that you must know how the fields are delimted. u caould use a variable for this like

procedure do_fill_lv(AFileName : String; AListView : TListView);
var
 sl : TStringList;
 I : Integer;
 s : String;
 li : TListItem;
begin
 sl := TStringList.Create;
 Try
   try
     sl.loadfromfile(AFileName);
     AListView.Items.Clear;
     for i := 0 to sl.count - 1 do
     begin
       s := sl[i];
       if (trim(s) <> '') or
          (trim(s)[1] <> #9) then  //maybe one tab remains, not tested
       begin
         li := AlistView.Items.Add;
         li.Caption := SplitStr(s,form1.edit1.text); //holds your variable delimiter
         while s <> '' do  
           li.SubItems.Add(SplitStr(s,form1.edit1.text));
       end;
     end;
   finally
     sl.free;
   end;
 except
   raise;
 end;
end;

hope this helps

meikl ;-)
0
 
LVL 14

Expert Comment

by:AvonWyss
ID: 6230358
Just for fun, another version:

procedure TextToListView(const AName: string; AView: TListView);
var
     Line: Integer;
     S: string;
     function CutStringPart: string;
     var
          SB,SE: Integer;
     begin
          SB:=1;
          while (SB<=Length(S)) and (S[SB]<=#32) do //detect leading spaces
               Inc(SB);
          SE:=SB;
          while (SE<=Length(S)) and (S[SE]>#32) do //trace text part
               Inc(SE);
          Result:=Copy(S,SB,SE-SB);
          while (SE<=Length(S)) and (S[SE]<=#32) do //find trailering spaces
               Inc(SE);
          Delete(S,1,SE-1);
     end;
begin
     with TStringList.Create do try
          LoadFromFile(AName);
          AView.Items.Clear;
          for Line:=0 to Count-1 do begin
               S:=Strings[Line];
               if S<>'' then
                    with AView.Items.Add do begin
                         Caption:=CutStringPart;
                         while S<>'' do
                              SubItems.Add(CutStringPart);
                    end;
          end;
     finally
          Free;
     end;
end;
0
 
LVL 9

Expert Comment

by:ITugay
ID: 6230418
good points,

let me try it too :-)

var
  L: TStringList;
  I,J: Integer;
  S: String;
begin
  ListView1.Items.Clear;
  L := TStringList.Create;
  try
    L.LoadFromFile('D:\FILE1.TXT');
    for I := 0 to L.Count-1 do
    begin
      S := Trim(L[I]);
      if S <> '' then
      begin
        J := Pos(' ', S);
        with ListView1.Items.Add do
        begin
          Caption := Trim(Copy(S, 1, J-1));
          Subitems.Add(Trim(Copy(S, J, 255)));
        end
      end
    end
  finally
    L.Free
  end
end;


-----
Igor
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 6230458
:-)) many ways possible
0
 

Expert Comment

by:RAGAB2000
ID: 6231282
If you are get the text file from excel document.
There are a component that deal with excel documents.
This will be more accurate to read your data.
It's name is XLSReadWrite and it's URL http://www.axolot.com 
Thanks
Ahmed Ragab
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 6231303
? may this will be an answer, if there is only this textfile with no chance to access the excel-sheet directly from which this will come?

i will recommend you to with draw your answer!

if hulken have the possibility to access excel directly,
then of course it would be a suggestion of many others.

let hulken decide, what do best fit to his needs

meikl ;-)
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 6231319
:-) with draw -> withdraw

as i had seen, your suggestion is comercial
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 6231325
my last two comments are pointd to RAGAB2000

;-)
0
 
LVL 6

Expert Comment

by:edey
ID: 6231713
My original solution will only work for comma & space delimited text files, though it wouldn't be hard to alter.  Classes.pas has this function def. for GetCommaText (the parser behind TStrings.commaText):

function TStrings.GetCommaText: string;
var
  S: string;
  P: PChar;
  I, Count: Integer;
begin
  Count := GetCount;
  if (Count = 1) and (Get(0) = '') then
    Result := '""'
  else
  begin
    Result := '';
    for I := 0 to Count - 1 do
    begin
      S := Get(I);
      P := PChar(S);
      while not (P^ in [#0..' ','"',',']) do P := CharNext(P);
      if (P^ <> #0) then S := AnsiQuotedStr(S, '"');
      Result := Result + S + ',';
    end;
    System.Delete(Result, Length(Result), 1);
  end;
end;


You'd just need to modify:

(P^ in [#0..' ','"',','])

to contain the char(s) you do want to delimit by., for ex:

(P^ in [#0..' ','"',',',#9])

GL
Mike
0
 
LVL 6

Expert Comment

by:edey
ID: 6231739
Another thought, if you'd prefer not to mess with your own parsing routines (though the above is a very simple mod) is to use the nthword funtion (in PSock, so you need the fastnet components, though I wouldn't recomend using them for inet stuff ;P ).  It'll take a string, an arbritary delimiter & give the n'th word from the input string.

GL
Mike
0
 

Author Comment

by:hulken
ID: 6233981
as I said... it was a textfile I like to work with..
0
 

Author Comment

by:hulken
ID: 6233993
OK,
edy, coffeetea , : ITugay and : AvonWyss

Thnks for helping me out.. I will add some questions with name points for XXX (where XXX is your name) to give you some points for helping me to learn how to work with text-files.

: kretzschmar:

I fell for youw solutions so I will accept your comment as an answer.. Thanks!

: RAGAB2000

Your propose was not what I asked for but mabe I will have some need for your comment lateron so I will add a question with points for you also.


Thnks every one for helping me out...
You are realy nice all of you...

I will probably see you here lateron.
0
 

Author Comment

by:hulken
ID: 6233996
Thanks for the help.

0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 6234111
well, thanks for the points :-)
glad you like it and its usefull for you,
glad to helped you :-)

good luck again

meikl ;-)
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
Michael from AdRem Software explains how to view the most utilized and worst performing nodes in your network, by accessing the Top Charts view in NetCrunch network monitor (https://www.adremsoft.com/). Top Charts is a view in which you can set seve…
This tutorial will teach you the special effect of super speed similar to the fictional character Wally West aka "The Flash" After Shake : http://www.videocopilot.net/presets/after_shake/ All lightning effects with instructions : http://www.mediaf…
Suggested Courses
Course of the Month10 days, 18 hours left to enroll

770 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question