Word使用逗号而不是空格将Delphi字符串包装到一定长度?

问题描述 投票:3回答:2

我在字符串中生成逗号分隔的名称列表,例如

Mr John Blue, Miss A Green, Mr Posh Hyphenated-Surname, Mr Fred Green, Miss Helen Red, Ms Jean Yellow

我现在想要在一个备忘录框中显示它们,每个行上可以容纳50个字符,以便每行显示尽可能多的名称(以及它们的尾随逗号)。所以上面应该是这样的

Mr John Blue, Miss A Green,
Mr Posh Hyphenated-Surname, Mr Fred Green,
Miss Helen Red, Ms Jean Yellow

我玩过

Memo1.text := WrapText(Mystring,50)

但它在姓氏和姓氏之间的空格处打破了线条,我试过了

Memo1.text := WrapText(MyString, slinebreak, ',' ,50) 

强制它只在逗号之后断开但是在空格和逗号处都破坏了。两者都倾向于用连字符打破,我注意到Rob Kennedy对类似问题的回答,即嵌入式引号引起Wrap()的问题,所以像John O'Donald先生这样的名字会引起问题。

我甚至尝试通过计算字符和寻找逗号来完成我自己的功能,但是陷入了多个嵌套的IF(太尴尬地显示了可怕的代码!)

任何人都可以提供任何帮助或代码,说明如何做到这一点?

PS我看过了

  • '在TMemo中用加号(+)字符包装词'
  • '如何将长字符串拆分为“包裹”字符串?'
  • '在字符串中查找某个单词,然后将其环绕'

和其他类似的帖子,但似乎没有匹配我要找的东西。

regex string delphi word-wrap
2个回答
1
投票

设置Memo1.WordWrap:=False;

有很多解决方案,我在这里只展示一个。 但要小心: 如果您使用大量数据,则执行速度很慢

procedure TForm1.AddTextToMemo(needle,xsSrc:string);
var
xsNew:string;
mposOld,mposNew:integer;
start:byte;
begin
xsNew:=xsSrc;
repeat
  repeat
   mposOld:=mposNew;
   mposNew:=Pos(needle,xsSrc);
   if mposNew>0 then xsSrc[mposNew]:='*';
  until (mposNew > 50) OR (mposNew = 0);
  if  mposOld > 0  then begin
     if xsNew[1] = ' ' then start := 2 else start := 1;
     if mposNew = 0 then mposOld:=Length(xsNew);
     Memo1.Lines.Add(copy(xsNew,start,mposOld));
     if mposNew = 0 then exit;
     xsNew:=copy(xsNew,mposOld+1,Length(xsNew)-mposOld);
     xsSrc:=xsNew;
     mposNew:=0;
  end else xsSrc:='';
until xsSrc = '';
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
Memo1.Clear;
AddTextToMemo(',','Mr John Blue, Miss A Green, Mr Posh Hyphenated-Surname, '+
                  'Mr Fred Green, Miss Helen Red, Ms Jean Yellow');
end;

UPDATE

如果您有少量数据,这里快速且易于阅读。

...
var
 Form1: TForm1;
 NameList: TStrings;

...
 NameList := TStringList.Create;
...

procedure TForm1.AddTextToMemoB(needle,xsSrc:string);
var
xsNew:string;
i:integer;
sumLen:byte;

begin
xsNew:=''; sumLen:=0;
nameList.Text:=StringReplace(xsSrc,needle,needle+#13#10,[rfReplaceAll]);
for i := 0 to nameList.Count - 1 do begin
  sumLen:=SumLen+Length(nameList[i]);
  if i < nameList.Count - 1 then begin
    if (sumLen + Length(nameList[i+1]) > 50) then begin
       if xsNew='' then xsNew:=nameList[i];
       Memo1.Lines.Add(xsNew);
       xsNew:='';
       sumLen:=0;
    end else if xsNew='' then xsNew:=nameList[i]+nameList[i+1] else   
                              xsNew:=xsNew+nameList[i+1];
  end else Memo1.Lines.Add(xsNew);
end; // for
end;

1
投票

我还没有对它进行过测试,但是以下几行应该可以解决这个问题。

for LCh in S do
begin
  case LCh of
    ',' : //Comma completes a word
    begin
      LWord := LWord + LCh;
      if  (LLine <> '') and //Don't wrap if we haven't started a line
          ((Length(LLine) + Length(LWord)) > ALineLimit) then
      begin
        //Break the current line if the new word makes it too long
        AStrings.Add(LLine);
        LLine := '';
      end;
      if (LLine <> ' ') then LLine := LLine + ' '; //One space between words
      LLine := LLine + LWord;
      LWord := '';
    end;
  else
    if (LWord = '') and (LCh in [' ', #9]) then
    begin
      //Ignore whitespace at start of word.
      //We'll explicitly add one space when needed.
      //This might remove some extraneous spaces.
      //Consider it a bonus feature.
    end else
    begin
      LWord := LWord + LCh;
    end;
  end;
end;

//Add the remainder
if  (LLine <> '') and //Don't wrap if we haven't started a line
    ((Length(LLine) + Length(LWord)) > ALineLimit) then
begin
  //Break the current line if the new word makes it too long
  AStrings.Add(LLine);
  LLine := '';
end;
if (LLine <> ' ') then LLine := LLine + ' '; //One space between words
LLine := LLine + LWord;
AStrings.Add(LLine);

当然,您可能已经注意到应该移动到子例程的重复。 调整你心中的内容。

© www.soinside.com 2019 - 2024. All rights reserved.