将字符串复制到StringGrid?

时间:2012-03-11 17:15:55

标签: delphi delphi-xe

我想将备忘录的内容复制到TStringGrid。

如果字符串之间有空格或间隙,则应将该字添加到StringGrid中自己的单元格中。

所以,假设我的Wordwrapped备忘录包含一些信息:

enter image description here

如何将该信息复制到StringGrid?

为了这个例子的目的,我制作了一个示例Image来说明结果应该如何:

enter image description here

重要的是要知道我不会总是知道要使用的列数,例如,如果从文本文件加载备忘录。

预定数量的列可能更好,例如5或6列。行数也是未知的。

我怎么能这样做?

3 个答案:

答案 0 :(得分:5)

如果我找对你,那么应该这样做:

procedure TForm1.FormClick(Sender: TObject);
type
  TWordPos = record
    Start, &End: integer;
  end;
const
  ALLOC_BY = 1024;
var
  Words: array of TWordPos;
  ActualLength, i: integer;
  txt: string;
  ThisWhite, PrevWhite: boolean;
begin

  ActualLength := 0;
  txt := Memo1.Text;
  PrevWhite := true;
  for i := 1 to Length(txt) do
  begin
    ThisWhite := Character.IsWhiteSpace(txt[i]);
    if PrevWhite and not ThisWhite then
    begin
      if ActualLength = Length(Words) then
        SetLength(Words, Length(Words) + ALLOC_BY);
      Words[ActualLength].Start := i;
      inc(ActualLength);
      PrevWhite := false;
    end else if (ActualLength>0) and ThisWhite then
      Words[ActualLength - 1].&End := i;
    PrevWhite := ThisWhite;
  end;

  SetLength(Words, ActualLength);

  StringGrid1.RowCount := Ceil(Length(Words) / StringGrid1.ColCount);

  for i := 0 to Length(Words) - 1 do
  begin
    StringGrid1.Cells[i mod StringGrid1.ColCount, i div StringGrid1.ColCount] :=
      Copy(Memo1.Text, Words[i].Start, Words[i].&End - Words[i].Start);
  end;

end;

Screenshot http://privat.rejbrand.se/stringgridwordsfrommemo.png

答案 1 :(得分:5)

RTL中有Tokenizer(由David评论)。 它会使用您选择的分隔符将文本拆分为单词。

这个例子来自Olaf Moinen在Zarko Gaijic的一篇文章中的评论:how-to-split-a-delphi-string-to-words-tokens.htm

uses HTTPUtil;

procedure TForm1.Button1Click(Sender: TObject);
var
  LTokenizer: IStringTokenizer;
begin
  Memo1.Clear;
  LTokenizer := StringTokenizer(Edit1.Text, ' ');
  while LTokenizer.hasMoreTokens do
  Memo1.Lines.Add(LTokenizer.nextToken);
end;

它将从编辑控件中获取文本并将其放入备忘录中。 我将把它作为练习从备忘录到字符串格式做同样的事情。

答案 2 :(得分:2)

TStringGrid具有填充不存在的单元格的功能,这些单元格超出ColCount * RowCount。因此,在填写字符串网格之前不必计算单词。

然后,直接的方法导致:

procedure TForm1.Button1Click(Sender: TObject);
var
  WordCount: Integer;
  WordStart: Integer;
  S: String;
  I: Integer;
begin
  WordCount := 0;
  WordStart := 1;
  S := Memo.Text + ' ';
  for I := 1 to Length(S) do
    if S[I] = ' ' then
    begin
      if WordStart <> I then
      begin
        Grid.Cells[WordCount mod Grid.ColCount, WordCount div Grid.ColCount] :=
          Copy(S, WordStart, I - WordStart);
        Inc(WordCount);
      end;
      WordStart := I + 1;
    end;
  Grid.RowCount := ((WordCount - 1) div Grid.ColCount) + 1;
end;

注意:为防止文本的额外内存分配(由于添加了' '),请在循环后将最后一个单词添加到网格中。

奖金功能:

为了能够调整列数,请按如下方式对字符串网格进行子类化,并自动重新排列所有单元格:

type
  TStringGrid = class(Grids.TStringGrid)
  protected
    procedure SizeChanged(OldColCount, OldRowCount: Integer); override;
  end;

  TForm1 = class(TForm)
  ...

procedure TStringGrid.SizeChanged(OldColCount, OldRowCount: Integer);
var
  I: Integer;
begin
  if OldColCount < ColCount then
  begin
    for I := 0 to OldColCount * OldRowCount - 1 do
      Cells[I mod ColCount, I div ColCount] :=
        Cells[I mod OldColCount, I div OldColCount];
  end
  else if OldColCount > ColCount then
  begin
    for I := OldColCount * OldRowCount - 1 downto 0 do
      Cells[I mod ColCount, I div ColCount] :=
        Cells[I mod OldColCount, I div OldColCount];
  end;
  if OldColCount <> OldRowCount then
    for I := OldColCount * OldRowCount to ColCount * RowCount - 1 do
      Cells[I mod ColCount, I div ColCount] := '';
end;