Reputation: 973
I have a memo lines like this:
Mahogany
Unpolished
In Stock : Yes
Total Stock : 102
Redwood
Polished
In Stock : Yes
Total Stock : 80
Pine
Polished
In Stock : Yes
Total Stock : 22
And i want to have only the line of Redwood's Total Stock. Since there are many same string of
Total Stock
I can not use this string as my keyword. So, i use "Redwood" , but i don't know how to get the line of "Total Stock" after "Redwood".
var
i: Integer;
s: string;
begin
for i := 0 to mem0.lines.Count - 1 do
begin
if (AnsiContainsStr(mem0.lines[i], 'Redwood')) then
begin
// s:= Redwood's total stock, how to do this ?
end
end;
end;
Upvotes: 1
Views: 1122
Reputation: 28826
Instead of AnsiContainsStr
, you can use StartsWith
, since the rest of the lines of the Redwood part are indentend.
var
I: Integer;
TotalStockLine: string;
MyArray: TArray<string>
begin
for I := 0 to Memo1.Lines.Count - 1 do
if Memo.Lines[I].StartsWith('Redwood') then
begin
TotalStockLine := Trim(Memo.Lines[I + 3];
Break;
end;
if TotalStockLine <> '' then
begin
MyArray := TotalStockLine.Split([':']);
TotalStock := StrToInt(Trim(MyArray[1]));
end;
etc... This can probably be simplified a little, but that shows how you could do this.
FWIW, this assumes you are using XE3 or later. Otherwise you must use the standalone StartsWith
.
Upvotes: 2
Reputation: 30725
You could try this, but like your original code it's a bit 'fragile' in that it makes assumptions about the layout of the text you're searching (in particular that the text you're searching through is packaged in a TStrings object):
function TotalForItem(const ItemName : String; Strings : TStrings) : String;
var
i,
j,
p : Integer;
s : string;
TotalLineIntro : String;
begin
Result := '';
TotalLineIntro := 'Total Stock : ';
for i := 0 to Strings.Count - 1 do
begin
if (Pos(ItemName, Strings[i]) > 0) then
begin
for j:= i + 1 to Strings.Count - 1 do begin
p := Pos(TotalLineIntro, Strings[j]);
if p > 0 then
begin
Result := Copy(Strings[j], p + Length(TotalLineIntro), Length(Strings[j]));
exit;
end;
end;
end
end;
end;
procedure TForm3.Button1Click(Sender: TObject);
begin
ShowMessage(TotalForItem('Redwood', Memo1.Lines));
end;
Upvotes: 3
Reputation: 613163
The missing code is:
s := mem0.Lines[i+3];
This makes the assumption that the format of the data is always exactly as seen in the question. If that assumption is valid then this simple code is the best solution.
It would probably make more sense to use one of the standard human readable structured data formats like JSON or YAML that have good parsers and emitters. Sadly the support for YAML on Delphi is essentially non-existant so that leaves JSON.
Upvotes: 3