Строковый список с разделителем в виде строки? - PullRequest
2 голосов
/ 21 июля 2010

У меня есть атрибут HistoryText в объекте, который хранится в виде строки.Я хочу показать все строки в сетке.Я должен иметь возможность удалять и редактировать строки в сетке.Формат:

16.5.2003-$-12:09-$-anna-$-Organization created
2.6.2005-$-13:03-$-jimmy-$-Organization edited
19.12.2005-$-13:33-$-madeleine-$-Organization edited

Таким образом, в каждой строке есть 4 поля: дата, время, пользователь и сообщение со строкой-разделителем в виде '- $ -'.Поскольку в качестве разделителя используется строка, а не символ, он не может быть назначен свойству разделителя списков строк.

У меня есть процедура для извлечения строки в список строк:

procedure ParseDelimited(const aStringList: TStringList; const aOrgList, aDelimiter: string);
var
   vDelimiterPos : integer;
   vPartialStr : string;
   vRemaingTxt : string;
   vDelimiterLength : integer;
begin
   vDelimiterLength := Length(aDelimiter);

   if (AnsiRightStr(aOrgList, Length(aDelimiter)) = aDelimiter) then
     vRemaingTxt := aOrgList
   else
     vRemaingTxt := aOrgList + aDelimiter;

   aStringList.BeginUpdate;
   aStringList.Clear;
   try
     while Length(vRemaingTxt) > 0 do
     begin
       vDelimiterPos := Pos(aDelimiter, vRemaingTxt);
       vPartialStr := Copy(vRemaingTxt,0,vDelimiterPos-1);
       aStringList.Add(vPartialStr);
       vRemaingTxt := Copy(vRemaingTxt,vDelimiterPos+vDelimiterLength,MaxInt);
     end;
   finally
     aStringList.EndUpdate;
   end;
end;

, и, похоже,отлично работаетМоя проблема заключается в синхронизации изменений в StringList обратно в исходное свойство String?Имеется так много исторических данных с этим разделителем, поэтому я не думаю, что заменить его на TChar - это реалистичный вариант.

Обновление: Уточнение.Я думаю, что мне удалось преобразовать String в StringList с помощью метода выше.Тогда отобразить его в сетке не должно быть так сложно.Проблема возникает, когда я хочу преобразовать TStringList обратно в исходное свойство String с '- $ -' в качестве разделителя.Я не могу сделать HistoryText: = myStringList.Delimitedtext, например.

Второе обновление: Я решил это.Вы все получили +1 за быстрые ответы и действительно пытаетесь помочь.Вкратце, как я это сделал.

Чтение из Historytext:

MyStringList.Text := Historytext;

Теперь у каждой строки есть 3 разделителя '- $ -', и каждая строка отделена переводом строки как обычно.

  • В цикле анализировать список строк и показывать его в сетке.Я больше не беспокоюсь о MyStringList.
  • Позвольте пользователю удалять и редактировать строки в сетке.
  • Когда закончите цикл за строкой и столбцами в сетке и создайте новую строку с тем же самымотформатируйте как оригинал.
  • Назначьте эту строку для HistoryText.

Так что смещение фокуса с StringList на сетку облегчило:)

Ответы [ 2 ]

5 голосов
/ 21 июля 2010

Вместо Delimiter (символ) и DelimitedText вы также можете использовать LineBreak (строка) и Text:

lst := TStringList.Create;
try
  lst.LineBreak := '-$-';
  lst.Text := '16.5.2003-$-12:09-$-anna-$-Organization created';
  Memo1.Lines := lst;  // or whatever you do with it
finally
  lst.Free;
end;

И это работает даже наоборот.

2 голосов
/ 21 июля 2010

Дикий удар в темноте (не очень понятно, о чем вы спрашиваете):

Работа через строки сетки:

  • Для каждого ряда:
    • назначить пустую строку для временной строки var
    • Для каждого столбца добавьте значение строки / столбца плюс разделитель во временную строку var
    • удалить последний разделитель из временной строки var (если она не пустая)
    • добавить временную строку var в список строк
  • Написать свойство textlist обратно в ваш HistoryText

const
  Delimiter = '-$-';
var
  row: Integer;
  col: Integer;
  SL: TStringList;
  rowString: string;
begin
  SL := TStringList.Create;
  try
    for row := 0 to StringGrid1.RowCount - 1 do begin
      rowString := '';
      for col := 0 to StringGrid1.ColCount - 1 do begin
        rowString := StringGrid1.Cells[col, row] + Delimiter;
      end;
      if rowString <> '' then begin
        rowString := Copy(rowString, 1, Length(rowString) - Length(Delimiter));
      end;
      SL.Add(rowString);
    end;
    HistoryText := SL.Text;
  finally
    SL.Free;
  end;
end;

Использование решения Уве для свойства LineBreak от TStrings:

var
  row: Integer;
  col: Integer;
  SLRows: TStringList;
  SLCols: TStringlist;
begin
  SLRows := TStringList.Create;
  try
    SLCols := TStringList.Create;
    try
      SLCols.LineBreak := '-$-';
      for row := 0 to StringGrid1.RowCount - 1 do begin
        SLCols.Clear;
        for col := 0 to StringGrid1.ColCount - 1 do begin
          SLCols.Add(StringGrid1.Cells[col, row]);
        end;
        SLRows.Add(SLCols.Text);
      end;
      HistoryText := SLRows.Text;
    finally
      SLCols.Free;
    end;
  finally
    SLRows.Free;
  end;
end;
...