Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

Convert object properties to delimited string and save results to file

Posted on 2011-03-24
10
Medium Priority
?
707 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:Ephraim Wangoya
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 36

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:Ephraim Wangoya
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
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 36

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:Ephraim Wangoya
Ephraim Wangoya earned 750 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 36

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 750 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 36

Author Closing Comment

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

Featured Post

Industry Leaders: 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

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
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…
This Micro Tutorial will teach you how to add a cinematic look to any film or video out there. There are very few simple steps that you will follow to do so. This will be demonstrated using Adobe Premiere Pro CS6.
In a question here at Experts Exchange (https://www.experts-exchange.com/questions/29062564/Adobe-acrobat-reader-DC.html), a member asked how to create a signature in Adobe Acrobat Reader DC (the free Reader product, not the paid, full Acrobat produ…
Suggested Courses

926 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