Скопировать строку в StringGrid?
Я хотел бы скопировать содержимое Заметки в TStringGrid.
Если между строками есть пробел или пробел, то это слово должно быть добавлено в свою собственную ячейку в StringGrid.
Итак, предположим, что моя заметка, которая Wordwrapped содержит некоторую информацию, например:
Как я могу скопировать эту информацию в StringGrid?
для целей этого примера я сделал образец изображения, чтобы проиллюстрировать, как результат должно быть:
важно знать, что я не всегда буду знать количество столбцов для использования, если, например, заметка загружается из текстового файла.
возможно, предопределенное количество столбцов было бы лучше, например, 5 или 6 столбцов. Количество строк также будет неизвестно.
Как я могу это сделать?
3 ответов
Если я правильно понял, то это должно сделать это:
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;
скриншот http://privat.rejbrand.se/stringgridwordsfrommemo.png
есть Tokenizer
(Как прокомментировал Дэвид) в RTL.
Он разделит текст на слова, используя разделитель по вашему выбору.
этот пример из комментария Олафа Мойнена в статье Зарко Гайича:how-to-split-a-delphi-string-to-words-tokens.НТМ.
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;
Он возьмет текст из элемента управления редактирования и поместит его в заметку. Я оставлю это как упражнение, чтобы сделать то же самое из заметки в stringgrid.
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;