You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Delphi:修改StringGrid文本时同步更新SynEdit对应行的方法

实现StringGrid文本修改同步到SynEdit对应行

需求说明

我开发了一款程序,可按规则从SynEdit中的文本搜索错误,并将错误结果显示在StringGrid中。现在需要实现:当修改StringGrid中的文本时,同步修改SynEdit中对应的行。

现有操作流程

  • 在SynEdit中打开文件
  • 从SynEdit中的文本创建临时文件
  • 将临时文件(FileName.tmp)加载到TStringlist中
  • 从TStringlist的文本中搜索错误
  • 填充StringGrid

现有核心代码

procedure Tform1.SearchDetailErrors(Sender: TObject);
var
  strlError: TStringlist;
  i:         integer;       
  str:       string;
begin
  if not DirectoryExists('Duplicates & Errors') then                 
    frmMain.CreateDirDuplicates(Sender);                               
  if frmMain.SynEdit.Lines.Count >= 1 then                           
    frmMain.SynEdit.Lines.SaveToFile('Duplicates & Errors\All Erros ' +
                     ExtractFileName(frmMain.OpenTxtFileDlg.FileName) +
                                                               '.tmp');
  strlError := TStringList.Create;                                   
  strlError.LoadFromFile('Duplicates & Errors\All Erros '  +         
          ExtractFileName(frmMain.OpenTxtFileDlg.FileName) +         
                                                    '.tmp');
  for i := 0 to strlError.Count - 1 do                               
    begin
      strlError.Strings[i] := Trim(strlError.Strings[i]);
      if CountPos('<', strlError.Strings[i])  <> 1 then               
        begin
          str := IntToStr(i + 1) + ' | <         | ' +       strlError.Strings[i];
      //str := IntToStr(i + 1) + ' < ' + strlError.Strings[i];
      StrLDupl.AddStrings(str);                              
      str := '';                                             
      CPos := 0;                                             
    end;
  if CountPos('>', strlError.Strings[i])  <> 1 then                
    begin
      str := IntToStr(i + 1) + ' | >         | ' + strlError.Strings[i];
      StrLDupl.AddStrings(str);                                   
      str := '';                                                  
      CPos := 0;                                                  
    end;
   ...
  if Odd(CountPos('!', strlError.Strings[i])) then                   
    begin
      str := IntToStr(i + 1) + ' | !         | ' + strlError.Strings[i];
      //str := IntToStr(i + 1) + ' " ' + strlError.Strings[i];
      StrLDupl.AddStrings(str);                                     
      str := '';                                                    
      CPos := 0;                                                    
    end;
  ...
  StringGridOptions(Sender);
 end;

 procedure Tform1.StringGridOptions(Sender: TObject);
 begin
   with SGDetailErrors do
   ... 
     begin
       Cells[0, 0]  := 'Line № ';                                              
       Cells[1, 0]  := 'Error ';                                               
       Cells[2, 0]  := 'String';                                               
     end;
   FillStringGridResultDetailErrors(Sender);
 end;

 procedure Tform1.FillStringGridResultDetailErrors(Sender: TObject);
 var
   strlError: TStringList;
   i:         Integer;
   s:         String;
 begin
   strlError := TStringList.Create;
   try
     strlError.LoadFromFile('Duplicates & Errors\All Errors '   +
          ExtractFileName(frmMain.OpenTxtFileDlg.FileName) +
                                                    '.txt');
  strlError.QuoteChar := #0;                                  
  for i := 0 to strlError.Count - 1 do
    begin
      with SGDetailErrors do                                               
        begin
          Rows[i + 1].Delimiter     := '|';                               
          strlError.Strings[i]      := StringReplace(strlError.Strings[i],
                                                               ' ', 'tmp',
                                                          [rfReplaceAll]);
          Rows[i + 1].DelimitedText := strlError.Strings[i];              
          Cells[0, i]               := StringReplace(Cells[0, i],         
                                                       'tmp', '',
                                                 [rfReplaceAll]);
          Cells[1, i]               := StringReplace(Cells[1, i],         
                                                       'tmp', '',
                                                 [rfReplaceAll]);
          Cells[2, i]               := StringReplace(Cells[2, i],         
                                                      'tmp', ' ',
                                                 [rfReplaceAll]);
        end;
     end;
   except
    raise Exception.Create('Error processing file.');                       
  end;       
  strlError.Free;
end;

StringGrid界面

StringGrid界面

同步修改实现方案

核心思路

利用StringGrid的OnSetEditText事件,在单元格文本修改完成后,提取对应行号和修改后的内容,直接更新SynEdit的对应行,同时可同步更新临时文件保持数据一致性。

具体实现代码

procedure Tform1.SGDetailErrorsSetEditText(Sender: TObject; ACol, ARow: Integer; const Value: string);
var
  LineNum: Integer;
begin
  // 仅处理内容列(第2列,索引从0开始)
  if ACol = 2 then
  begin
    // 转换StringGrid中显示的行号为SynEdit的索引(行号从1开始,SynEdit索引从0开始)
    LineNum := StrToIntDef(SGDetailErrors.Cells[0, ARow], -1);
    if LineNum > 0 and (LineNum - 1 < frmMain.SynEdit.Lines.Count) then
    begin
      // 同步更新SynEdit对应行
      frmMain.SynEdit.Lines[LineNum - 1] := Value;
      
      // 可选:同步更新临时文件,避免后续搜索时数据不一致
      frmMain.SynEdit.Lines.SaveToFile('Duplicates & Errors\All Erros ' +
        ExtractFileName(frmMain.OpenTxtFileDlg.FileName) + '.tmp');
    end;
  end;
end;

注意事项

  • 确保StringGrid第0列的行号与SynEdit的行一一对应,无错误
  • 增加行号转换的异常处理,防止非法输入导致程序崩溃
  • 若需要持久化修改,可在同步后直接保存SynEdit内容到原文件

内容的提问来源于stack exchange,提问作者Gin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 23:51:00