Solved

Convert object properties to delimited string and save results to file

Posted on 2011-03-24
10
687 Views
Last Modified: 2012-05-11
Suppose we have a Customer obj with the following properties:
- Id
- Name
- Address

I would like to Convert object properties to delimited string with a object method like:

function Customer.ToString(const aDelimiter: Char): string;
begin
  //SAmple code for csv, need change to use aDelimiter parameter
  Result := Format("%s,%s,%s",Id, Name, Description);
end;

where aDelimiter can be ",", ";", tab(\t), etc.

Notice that the result string will be stored in a stringlist later on to be output to a file. For example the Pseudo code:
csvList := TStringList.Create;
foreach customer in CustomerList
  csvList.Add(customer.ToString(',');
csvList.SaveToFile("CustomerExport.csv");

There are thousands of lines to store from CustomerList, any ideas on how to make it this export more efficient will be greatly appreciated.
Note: Compiler is still Delphi 7.
0
Comment
Question by:Miguel Oz
  • 4
  • 3
  • 2
  • +1
10 Comments
 
LVL 32

Expert Comment

by:ewangoya
ID: 35212097

I dont think you can get alot more efficiency out of a sequential list. You have to iterate all the objects in any case.
However you can eliminate the saving to stringlist, save it straight to a file, this will be much faster

You could make the object much better by adding the save method to the CustomerList object and let the methods of the List handle the iteration and also set the delimiter once in the CustomerList Object

private
   FDelimiter: Char;
   function GetText: string;
public
    procedure SaveToFile(const AFileName: string);
    .....
    property Delimiter: char read FDelimiter write FDelimiter;
end;





function TCustomerList.GetText;
var
  L, Size, Count: Integer;
  P: PChar;
  S, LB: string;
begin
  Count := GetCount;
  Size := 0;
  LB := #13#10;
  foreach customer in CustomerList
    Inc(Size, Length(Customer.ToString(FDelimiter) + Length(LB));

  SetString(Result, nil, Size);
  P := Pointer(Result);
  foreach customer in CustomerList
  begin
    S := Customer.ToString(FDelimiter;
    L := Length(S);
    if L <> 0 then
    begin
      System.Move(Pointer(S)^, P^, L);
      Inc(P, L);
    end;
    L := Length(LB);
    if L <> 0 then
    begin
      System.Move(Pointer(LB)^, P^, L);
      Inc(P, L);
    end;
  end;
end;


procedure TCustomerList.SaveToFile(const AFileName: string);
var
  Stream: TFileStream;
  S: string;
begin
  Stream := TFileStream.Create;
  try
    S := GetText;
    Stream.WriteBuffer(Pointer(S)^, Length(S));
  finally
    FreeAndNil(Stream);
  end; 
end;

Open in new window

0
 
LVL 35

Author Comment

by:Miguel Oz
ID: 35212119
Your code does not implement Customer.ToString method using the delimiter parameter.
If you can add thta to your answer will be great
Thanks.
0
 
LVL 32

Expert Comment

by:ewangoya
ID: 35212141

Since Delimiter is already a property of the CustomerList and is accessed within the method GetText, you just set and call SaveToFile


  CustomerList.Delimiter := ',';
  CustomerList.SaveToFile('c:\CusomerExport.csv');
0
Gigs: Get Your Project Delivered by an Expert

Select from freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely and get projects done right.

 
LVL 35

Author Comment

by:Miguel Oz
ID: 35212188
The delimiter is only for the customer properties.
Your posted code use this construct:
Customer.ToString(FDelimiter)
but the implementation (ToString method at Customer object) is not posted. The main objective of this question is how to convert the object to string taking in consideration that this string will be later used in a big list to save it to a file.
0
 
LVL 32

Assisted Solution

by:ewangoya
ewangoya earned 250 total points
ID: 35212238



function Cusomer.ToString(const ADelimiter: string): string;
begin
  Result := Format('%d%s%s%s%s',
      [Id, FDelimiter, Name, FDelimiter, Description]);
end;
0
 
LVL 11

Expert Comment

by:SAMIR BHOGAYTA
ID: 35212301
Hi, this is very useful to you the code is very large so i will give you a link for that

http://www.dotnetperls.com/convert-dictionary-string

http://www.switchonthecode.com/tutorials/csharp-tutorial-serialize-objects-to-a-file
0
 
LVL 25

Expert Comment

by:epasquier
ID: 35213234
You can use a TStringList to build your delimited string. It requires a delimiter, and also a quote in case there can be occurences of the delimiter in the values (the address might contain coma, for example)
the resulting string could then be :

1;John Smith;"123, main street road"
function TCustomer.ToString(Delim:Char=',';Quote:Char='"'):String;
Var
 L:TStringList;
begin
 L:=TStringList.Create;
 L.Delimiter:=Delim;
 L.QuoteChar:=Quote;
 L.Add(IntToStr(ID));
 L.Add(Name);
 L.Add(Address);
 Result:=L.DelimitedText;
 L.Free;
end;

Open in new window

0
 
LVL 35

Author Comment

by:Miguel Oz
ID: 35245682
I use this method:
function Customer.ToString(const AFormat: string): string;
begin
  Result := Format(AFormat,  [Id, Name, Description]);
end;
where  AFormat = '%s,%s,%s'; or any other delimiter I need.Thus the formatiing string is build once and use multiple times

Thank you all for your comments. I will keep the question open a bit longer to see if there is any faster way to do this.
0
 
LVL 25

Accepted Solution

by:
epasquier earned 250 total points
ID: 35260990
You can't get it faster.
Not that it matters anyway, you won't see much difference, even if you use the stringlist Delimited text functionality.
You probably should choose the method to use by considering the ease of coding and maintaining more the speed of execution, as your probable bottleneck is the writing of the file, not the generation of each line. For example, saving each line in a text file line by line instead of all in one SaveToFile will be quicker and consume less memory in the process.
0
 
LVL 35

Author Closing Comment

by:Miguel Oz
ID: 35311226
Guideline without profile backing
0

Featured Post

Courses: Start Training Online With Pros, Today

Brush up on the basics or master the advanced techniques required to earn essential industry certifications, with Courses. Enroll in a course and start learning today. Training topics range from Android App Dev to the Xen Virtualization Platform.

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 Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
This tutorial gives a high-level tour of the interface of Marketo (a marketing automation tool to help businesses track and engage prospective customers and drive them to purchase). You will see the main areas including Marketing Activities, Design …
This Micro Tutorial demonstrates using Microsoft Excel pivot tables, how to reverse engineer competitors' marketing strategies through backlinks.

786 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