Deleting a range

General TRichView support forum. Please post your questions here
Post Reply
Alvaro
Posts: 17
Joined: Wed Apr 14, 2010 4:01 am

Deleting a range

Post by Alvaro »

Hi, in search query I put "delete lines" and I choosed Search for all terms, but nothing helped me.
My question is how can I delete more then one line following this steps:
Suppose a text:

reserved word(i)
text
text
text
reserved word(f)

I would like to select a range starting at reserved word(i) until reserved word(f) and delete all lines in this range.

I tryed this, but returned an error, could you help me, please?

Code: Select all

rve.SearchText('Inicia bloco', [rvseoDown, rvseoWholeWord]).ToInteger;
nPosI := RVGetLinearCaretPos(rve);
rve.SearchText('Termina bloco', [rvseoDown, rvseoWholeWord]).ToInteger;
nPosF := RVGetLinearCaretPos(rve);

rve.DeleteParas(nPosI, nPosF);

or

rve.SetSelectionBounds(nPosI, rve.GetOffsBeforeItem(nPosI), nPosF, rve.GetOffsAfterItem(nPosF));
rve.DeleteSelection;

Sergey Tkachenko
Site Admin
Posts: 17805
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Post by Sergey Tkachenko »

You must not use RVGetLinearCaretPos here. This function returns a number of characters from the beginning of document to the caret position. But DeleteParas and SetSelectedBounds does not need this value, they need index of item.

The first code could be:

Code: Select all

rve.SearchText('Inicia bloco', [rvseoDown, rvseoWholeWord]);
nPosI := rve.CurItemNo;
rve.SearchText('Termina bloco', [rvseoDown, rvseoWholeWord]);
nPosF := rve.CurItemNo;
rve.DeleteParas(nPosI, nPosF); 
It deletes all paragraphs, starting from paragraphs containing the first word and ending to paragraph containing the last word. Document is reformatted, but this change is not written in undo buffer, so it may become invalid, and you need to call rve.ClearUndo.

Do you need to delete reserved words as well? In this case, the second code could be:

Code: Select all

var ItemNoI, ItemNoF, OffsI, OffsF: Integer;

rve.SearchText('Inicia bloco', [rvseoDown, rvseoWholeWord]); 
rve.GetSelectionBounds(ItemNoI, OffsI, dummy, dummy, True); // storing the position  before selection in ItemNoI, OffsI
rve.SearchText('Termina bloco', [rvseoDown, rvseoWholeWord]); 
rve.GetSelectionBounds(dummy, dummy, ItemNoF, OffsF, True);// storing the position  after selection in ItemNoF, OffsF

rve.SetSelectionBounds(ItemNoI, OffsI, ItemNoF, OffsF);
rve.DeleteSelection;
Note 1: In a real code, you need to check the result of SearchText to see if the word was really found.
Note 2: These code fragments assume that both words are in the root editor, not in table cells. The second code can be modified to support table cells:

Code: Select all

var ItemNoI, ItemNoF, OffsI, OffsF: Integer;
  tle1, tle2: TCustomRichViewEdit;

rve.SearchText('Inicia bloco', [rvseoDown, rvseoWholeWord]); 
tle1 := rve.TopLevelEditor;
tle1.GetSelectionBounds(ItemNoI, OffsI, dummy, dummy, True); // storing the position  before selection in ItemNoI, OffsI
rve.SearchText('Termina bloco', [rvseoDown, rvseoWholeWord]); 
tle2 := rve.TopLevelEditor;
tle2.GetSelectionBounds(dummy, dummy, ItemNoF, OffsF, True);// storing the position  after selection in ItemNoF, OffsF
if tle1=tle2 then begin // otherwise, the selection is in different cells
  tle2.SetSelectionBounds(ItemNoI, OffsI, ItemNoF, OffsF);
  tle2.DeleteSelection;
end;
Alvaro
Posts: 17
Joined: Wed Apr 14, 2010 4:01 am

Post by Alvaro »

Thank you very much Sergey was exactly what I needed, here in Brazil is still night, but have a excelente day my friend.
DanielM
Posts: 16
Joined: Thu Mar 27, 2025 5:31 pm

Re: Deleting a range

Post by DanielM »

var ItemNoI, ItemNoF, OffsI, OffsF: Integer;
tle1, tle2: TCustomRichViewEdit;

rve.SearchText('Inicia bloco', [rvseoDown, rvseoWholeWord]);
tle1 := rve.TopLevelEditor;
tle1.GetSelectionBounds(ItemNoI, OffsI, dummy, dummy, True); // storing the position before selection in ItemNoI, OffsI
rve.SearchText('Termina bloco', [rvseoDown, rvseoWholeWord]);
tle2 := rve.TopLevelEditor;
tle2.GetSelectionBounds(dummy, dummy, ItemNoF, OffsF, True);// storing the position after selection in ItemNoF, OffsF
if tle1=tle2 then begin // otherwise, the selection is in different cells
tle2.SetSelectionBounds(ItemNoI, OffsI, ItemNoF, OffsF);
tle2.DeleteSelection;
end;
I tried this code and if the delimiting words are in different cells, and there are other words after the first one, the delimiters are deleted, but also what is between them.

How can I delete delimited text when it is in different cells?
Attachments
2.PNG
2.PNG (1.56 KiB) Viewed 553 times
1.PNG
1.PNG (16.2 KiB) Viewed 553 times
Sergey Tkachenko
Site Admin
Posts: 17805
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Re: Deleting a range

Post by Sergey Tkachenko »

This code must do nothing is the words are in different cells.
The check "if tle1=tle2 then" is to ensure that the words are in the same cell.

The code for deleting content between two cells would be much more complicated.
What does "content between cells" mean? If the cells are in different rows and columns? If they are in different tables, maybe nested in each other?
DanielM
Posts: 16
Joined: Thu Mar 27, 2025 5:31 pm

Re: Deleting a range

Post by DanielM »

Theoretically it should delete everything between the two keywords, true, it could be on other rows, but never in different tables.
Sergey Tkachenko
Site Admin
Posts: 17805
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Re: Deleting a range

Post by Sergey Tkachenko »

For example, if the cells are (2, 2) and (3,3).
Should it clear the cells in the (2, 3) and (3, 2)?
Or should it clear all cels in the row after (2, 2), and all cells in the row before (3, 3)?
DanielM
Posts: 16
Joined: Thu Mar 27, 2025 5:31 pm

Re: Deleting a range

Post by DanielM »

Like this demo, remove all item between \if_del\ and \end_del\
3.png
3.png (48.13 KiB) Viewed 504 times
Sergey Tkachenko
Site Admin
Posts: 17805
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Re: Deleting a range

Post by Sergey Tkachenko »

The original code has a bug.
It's incorrect to compare tle1 and tle2.
If a new tle2 is created, tle1 is destroyed.
It is possible that the Delphi memory manager reuses a freed memory, so tle1 = tle2.

The comparison must be like this:

Code: Select all

var ItemNoI, ItemNoF, OffsI, OffsF: Integer;
tle1, tle2: TCustomRichViewEdit;
SourceData: TCustomRVData;

rve.SearchText('Inicia bloco', [rvseoDown, rvseoWholeWord]);
tle1 := rve.TopLevelEditor;
SourceData := tle1.RVData.GetSourceRVData;
tle1.GetSelectionBounds(ItemNoI, OffsI, dummy, dummy, True); // storing the position before selection in ItemNoI, OffsI
rve.SearchText('Termina bloco', [rvseoDown, rvseoWholeWord]);
tle2 := rve.TopLevelEditor;
tle2.GetSelectionBounds(dummy, dummy, ItemNoF, OffsF, True);// storing the position after selection in ItemNoF, OffsF
if SourceData = tle2.RVData.GetSourceRVData then// otherwise, the selection is in different cells
begin
  tle2.SetSelectionBounds(ItemNoI, OffsI, ItemNoF, OffsF);
  tle2.DeleteSelection;
end;
Sergey Tkachenko
Site Admin
Posts: 17805
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Re: Deleting a range

Post by Sergey Tkachenko »

The code supporting starting and ending codes in different cells is below.

This kind of selection (from the starting cell till the end of the row; then all cells in the rows between; then cells till the ending cell) is not natural for TRichViewEdit: TRichViewEdit selects cell that are inside the specified rectangular area.
As a result, all cells need to be cleared one-by-one; and the code became large.

Code: Select all

procedure DeleteBetween(rve: TCustomRichViewEdit; const StartWord, EndWord: String);
var
  ItemNoI, ItemNoF, OffsI, OffsF, dummy, R1, C1, R2, C2, R, C: Integer;
  tle1, tle2: TCustomRichViewEdit;
  Cell1, Cell2: TRVTableCellData;
  SourceData: TCustomRVData;
  Table: TRVTableItemInfo;
begin
  if not rve.SearchText(StartWord, [rvseoDown, rvseoWholeWord]) then
    exit;
  tle1 := rve.TopLevelEditor;
  SourceData := tle1.RVData.GetSourceRVData;
  // storing the position  before selection in ItemNoI, OffsI
  tle1.GetSelectionBounds(ItemNoI, OffsI, dummy, dummy, True);
  if rve.TopLevelEditor <> rve then
  begin
    // if the word is in a table, storing this table and the cell
    Cell1 := SourceData as TRVTableCellData;
    Table := Cell1.GetTable;
    Table.GetCellPosition(Cell1, R1, C1);
  end
  else
  begin
    Table := nil;
    Cell1 := nil;
  end;
  if not rve.SearchText(EndWord, [rvseoDown, rvseoWholeWord]) then
    exit;
  tle2 := rve.TopLevelEditor;
  tle2.GetSelectionBounds(dummy, dummy, ItemNoF, OffsF, True);// storing the position  after selection in ItemNoF, OffsF
  if SourceData = tle2.RVData.GetSourceRVData then
  begin
    // the both words are in the same document/subdocument
    tle2.SetSelectionBounds(ItemNoI, OffsI, ItemNoF, OffsF);
    tle2.DeleteSelection;
  end
  else if (Table <> nil) and (rve.TopLevelEditor <> rve) then
  begin
    // the both words are in tables (or in the same table)
    Cell2 := tle2.RVData.GetSourceRVData as TRVTableCellData;
    if Cell2.GetTable <> Table then
      exit;
    // the both words are in the same table
    Table.GetCellPosition(Cell2, R2, C2);
    rve.Und
    rve.BeginUpdate;
    try
      rve.BeginUndoGroup2(rvutDelete);
      // deleting content in the ending cell
      tle2.SetSelectionBounds(0, tle2.GetOffsBeforeItem(0), ItemNoF, OffsF);
      rve.DeleteSelection;
      // deleting content in the starting cell
      Cell1.Edit;
      TCustomRVFormattedData(Cell1.GetRVData).SetSelectionBounds(ItemNoI, OffsI,
        Cell1.GetRVData.ItemCount - 1,
        Cell1.GetRVData.GetOffsAfterItem(Cell1.GetRVData.ItemCount - 1));
      rve.DeleteSelection;
      if R2 <> R1 then
      begin
        // clearing all cells after the starting cell
        for C := C1 + 1 to Table.ColCount - 1 do
          if Table.Cells[R1, C] <> nil then
          begin
            Table.Select(R1, C, 0, 0);
            rve.DeleteSelection;
          end;
        // clearing all rows between
        for R := R1 + 1 to R2 - 1 do
          for C := 0 to Table.ColCount - 1 do
            if Table.Cells[R, C] <> nil then
            begin
              Table.Select(R, C, 0, 0);
              rve.DeleteSelection;
            end;
        // clearing all cells before the ending cell
        for C := 0 to C2 - 1 do
          if Table.Cells[R2, C] <> nil then
          begin
            Table.Select(R2, C, 0, 0);
            rve.DeleteSelection;
          end;
      end
      else
        // clearing all cells between
        for C := C1 + 1 to C2 - 1 do
          if Table.Cells[R1, C] <> nil then
          begin
            Table.Select(R1, C, 0, 0);
            rve.DeleteSelection;
          end;
      rve.EndUndoGroup2(rvutDelete);
      rve.TopLevelEditor.Change;
    finally
      rve.EndUpdate;
    end;
  end;
end;
DanielM
Posts: 16
Joined: Thu Mar 27, 2025 5:31 pm

Re: Deleting a range

Post by DanielM »

Yes, now it detects the two keywords in the text ok, but the problem remained with detecting keywords in tables an remove text in cells.
DanielM
Posts: 16
Joined: Thu Mar 27, 2025 5:31 pm

Re: Deleting a range

Post by DanielM »

Wow, how fast you posted, I'll try the acid towards the end of the weekend. Thanks.
Post Reply