📄 tablesort.pas
字号:
{*******************************************************}
{ }
{ RichView }
{ Table rows sorting. }
{ }
{ Copyright (c) Sergey Tkachenko }
{ svt@trichview.com }
{ http://www.trichview.com }
{ }
{*******************************************************}
unit TableSort;
interface
uses
SysUtils, Windows, Messages, Classes, Graphics,
RVClasses, RVItem, RVTable, RVGetText, RVStyle, RichView, RVEdit;
// Can this table be sorted? Yes, if it does not have cells merged across rows
function CanSortTable(table: TRVTableItemInfo): Boolean;
// Returns a new table, a sorted copy of table.
// Table must be inserted in rv.
// Sorting is performed by the content of the Column-th column
// (must be in range 0..table.ColCount-1).
// Content is compared as ANSI string
function CreateSortedTable(rv: TCustomRichView; table: TRVTableItemInfo;
Column: Integer; Ascending, IgnoreCase: Boolean): TRVTableItemInfo;
// Sorts the current table in rve, as an editing operation (can be undone)
function SortCurrentTable(rve: TCustomRichViewEdit;
Column: Integer; Ascending, IgnoreCase: Boolean): Boolean;
implementation
function CanSortTable(table: TRVTableItemInfo): Boolean;
var r,c: Integer;
begin
Result := False;
for r := 0 to table.RowCount-1 do
for c := 0 to table.ColCount-1 do
if (table.Cells[r,c]<>nil) and
(table.Cells[r,c].RowSpan>1) then
exit;
Result := True;
end;
{------------------------------------------------------------------------------}
type
TCellSortInfo = class
Row: Integer;
Text: String;
end;
function CompareCellsA(Item1, Item2: Pointer): Integer;
begin
Result := AnsiCompareText(TCellSortInfo(Item1).Text, TCellSortInfo(Item2).Text);
end;
function CompareCellsACS(Item1, Item2: Pointer): Integer;
begin
Result := AnsiCompareStr(TCellSortInfo(Item1).Text, TCellSortInfo(Item2).Text);
end;
function CompareCellsD(Item1, Item2: Pointer): Integer;
begin
Result := -AnsiCompareText(TCellSortInfo(Item1).Text, TCellSortInfo(Item2).Text);
end;
function CompareCellsDCS(Item1, Item2: Pointer): Integer;
begin
Result := -AnsiCompareStr(TCellSortInfo(Item1).Text, TCellSortInfo(Item2).Text);
end;
{------------------------------------------------------------------------------}
function CreateSortedTable(rv: TCustomRichView; table: TRVTableItemInfo;
Column: Integer; Ascending, IgnoreCase: Boolean): TRVTableItemInfo;
var r,c: Integer;
SortList: TRVList;
SortItem: TCellSortInfo;
Stream: TMemoryStream;
SourceCell, DestCell: TRVTableCellData;
Color: TColor;
RVFOptions: TRVFOptions;
begin
Result := nil;
if (Column<0) or (Column>=table.ColCount) or not CanSortTable(table) then
exit;
SortList := TRVList.Create;
try
// preparing sort list
SortList.Capacity := table.RowCount;
for r := 0 to table.RowCount-1 do begin
SortItem := TCellSortInfo.Create;
SortItem.Row := r;
if table.Cells[r, Column]<>nil then
SortItem.Text := GetRVDataText(table.Cells[r, Column]);
SortList.Add(SortItem);
end;
// sorting
if Ascending then
if IgnoreCase then
SortList.Sort(CompareCellsA)
else
SortList.Sort(CompareCellsACS)
else
if IgnoreCase then
SortList.Sort(CompareCellsD)
else
SortList.Sort(CompareCellsDCS);
// creating new table
Result := TRVTableItemInfo.CreateEx(table.RowCount, table.ColCount,
table.Cells[0,0].GetParentData);
Result.AssignProperties(table);
// copying rows from the old table in the sort order
Color := clNone;
RVFOptions := rv.RVFOptions;
rv.RVFOptions := RVFOptions-[rvfoSaveTextStyles, rvfoSaveParaStyles];
try
for r := 0 to SortList.Count-1 do begin
SortItem := TCellSortInfo(SortList.Items[r]);
for c := 0 to table.ColCount-1 do begin
SourceCell := table.Cells[SortItem.Row, c];
if SourceCell<>nil then begin
if SourceCell.ColSpan>1 then
Result.MergeCells(r, c, SourceCell.ColSpan, 1, True);
DestCell := Result.Cells[r, c];
DestCell.AssignAttributesFrom(table.Cells[SortItem.Row, c], True, 1, 1);
Stream := TMemoryStream.Create;
try
SourceCell.GetRVData.SaveRVFToStream(Stream, False, clNone, nil, nil);
Stream.Position := 0;
DestCell.LoadRVFFromStream(Stream, Color, nil, nil);
finally
Stream.Free;
end;
end;
end;
end;
finally
rv.RVFOptions := RVFOptions;
end;
finally
SortList.Free;
end;
end;
{------------------------------------------------------------------------------}
function SortCurrentTable(rve: TCustomRichViewEdit;
Column: Integer; Ascending, IgnoreCase: Boolean): Boolean;
var rvet: TCustomRichViewEdit;
table: TRVTableItemInfo;
ItemNo, p: Integer;
begin
Result := False;
if not rve.GetCurrentItemEx(TRVTableItemInfo, rvet, TCustomRVItemInfo(table)) then
exit;
ItemNo := table.GetMyItemNo;
table := CreateSortedTable(rvet, table, Column, Ascending, IgnoreCase);
if table=nil then
exit;
rvet.BeginUndoGroup(rvutModifyItem);
rvet.SetUndoGroupMode(True);
try
p := rve.RootEditor.VScrollPos;
SendMessage(rve.Handle, WM_SETREDRAW, 0, 0);
rvet.SetSelectionBounds(ItemNo, 0, ItemNo, 1);
rvet.InsertItem(rvet.GetItemText(ItemNo), table);
rve.RootEditor.VScrollPos := p;
SendMessage(rve.Handle, WM_SETREDRAW, 1, 0);
rve.RefreshAll;
finally
rvet.SetUndoGroupMode(False);
end;
Result := True;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -