3

I need to go through a ton of data that is stored in a paradox table within a Memo field. I need to process this data line by line and process each line.

How can I tell Delphi to fetch each line in the memo field one by one?

Could I use #13#10 as a delimiter?

2 Answers2

4

Assuming that what is in the memo field uses #13#10 as the line separator then I would use a TStringList, and the very useful Text property to split the memo field text into separate lines:

var
  StringList: TStringList;
  Line: string;
.....
StringList.Text := MemoFieldText;
for Line in StringList do
  Process(Line);

Even if your memo field uses Unix linefeeds then this code will interpret the memo field correctly.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • `TStringList` supports parsing text that use `#13#10`, `#13`, and `#10` as line breaks. – Remy Lebeau Apr 06 '12 at 20:38
  • @Remy Documentation states "When setting Text, the value will be parsed by separating into substrings whenever a carriage return or linefeed is encountered. (The two do not need to form pairs)." Is that out of date? I checked the documentation for this very point just before my final grace period edit (i.e. the final sentence). – David Heffernan Apr 06 '12 at 20:40
  • 1
    no, it is still valid. When the `LineBreak` property is set to `sLineBreak` (the OS native line break), then all three line break types (`CR`, `LF`, `CRLF`) are looked for. When the `LineBreak` property is set to something else, then only that value is looked for. – Remy Lebeau Apr 06 '12 at 21:12
  • 1
    @remy Thanks. It seems that the documentation is a little lacking in these details – David Heffernan Apr 06 '12 at 21:14
  • @David, "a little lacking" is too kind wording. – LU RD Apr 07 '12 at 17:39
1

It depends on how the field is actually declared in Paradox. If it's a TMemoField, it's pretty easy:

var
  SL: TStringList;
  Line: string;
begin
  SL := TStringList.Create;
  try
    SL.Text := YourMemoField.GetAsString;
    for Line in SL do
     // Process each line of text using `Line`
  finally
    SL.Free;
  end;
end;

If it's a TBlobField, it's a little more complicated. You need to read the memo field using a TBlobStream, and load the content of that stream into a TStringList:

// For Delphi versions that support it:
procedure LoadBlobToStringList(const DS: TDataSet; const FieldName: string;
  const SL: TStringList);
var
  Stream: TStream;
begin
  Assert(Assigned(SL), 'Create the stringlist for LoadBlobToStringList!');
  SL.Clear;
  Stream := DS.CreateBlobStream(DS.FieldByName(FieldName), bmRead);
  try
    SL.LoadFromStream(Stream);
  finally
    Stream.Free;
  end;
end;

// For older Delphi versions that do not have TDataSet.CreateBlobStream
procedure LoadBlobToStringList(const DS: TDataSet; const TheField: TField; 
  const SL: TStringList);
var
  BlobStr: TBlobStream;
begin
  Assert(Assigned(SL), 'Create the stringlist for LoadBlobToStringList!');
  SL.Clear;
  BlobStr := TBlobStream.Create(DS.FieldByName(TheField), bmRead);
  try
    SL.LoadFromStream(BlobStr);
  finally
    BlobStr.Free;
  end;
end;

// Use it
var
  SL: TStringList;
  Line: string;
begin
  SL := TStringList.Create;
  LoadBlobToStringList(YourTable, YourMemoFieldName, SL);
  for Line in SL do
    // Process each Line, which will be the individual line in the blob field

  // Alternatively, for earlier Delphi versions that don't support for..in
  // declare an integer variable `i`
  for i := 0 to SL.Count - 1 do
  begin
    Line := SL[i];
    // process line of text using Line
  end;
end;
Wouter van Nifterick
  • 23,603
  • 7
  • 78
  • 122
Ken White
  • 123,280
  • 14
  • 225
  • 444
  • You should use the `TDataSet.CreateBlobStream()` method instead of instantiating the `TBlobStream` class directly. That allows the DB component to decide the best implementation to use for the stream. – Remy Lebeau Apr 06 '12 at 21:14
  • @Remy: I thought about adding the snippet for that; I'll update my code to show that alternative as well. (It didn't exist in early Delphi versions, and there wasn't a version mentioned in the question; I went with least common demoninator and what I had handy at the time.) – Ken White Apr 06 '12 at 21:33
  • `CreateBlobStream()` has existed since at least D5 for sure, maybe earlier. – Remy Lebeau Apr 06 '12 at 21:39
  • Possibly; I don't have a version that old (or any prior to that) installed to check. Since the OP didn't specify *any* version, and mentioned `BDE` and `Paradox`, this could be as old as Delphi 1. :) Regardless, I took your suggestion and updated my answer to include both. – Ken White Apr 06 '12 at 21:46