⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gridsort.pas

📁 多线程IP扫描程序
💻 PAS
字号:
unit GridSort;

interface

uses Classes,SysUtils,Grids;

//Sorting Stuff
type
  TSortStyle = (ssAutomatic, ssAlphabetic, ssNumeric, ssDate);
  TSortDirection = (sdAscending, sdDescending);
  
  {**************************************************************}
  {*** NOTE: These are the options you can set to affect sorting.}
  TSortOptions = record
      SortStyle: TSortStyle;
      SortDirection: TSortDirection;
      SortCaseSensitive: Boolean;
  end;

  TSortedListEntry = record
      Str: String;
      RowNum: Longint;
  end;
  PSortedListEntry = ^TSortedListEntry;

  TSortedList = class(TList)
    public
        function GetItem(const i: Integer): PSortedListEntry;
        procedure Reset;
    end;

procedure SortGrid(grd:TStringGrid;ACol:integer);

var GlobalSortOptions: TSortOptions;

implementation

var SortedList: TSortedList;

type
    TCustGridEnh=class(TCustomGrid)
      public
        function SelectCell(ACol, ARow: Longint): Boolean;
        procedure MoveColRow(ACol, ARow: Longint; MoveAnchor, Show: Boolean);
    end;

function TCustGridEnh.SelectCell(ACol, ARow: Longint): Boolean;
begin
     inherited SelectCell(ACol, ARow);
end;

procedure TCustGridEnh.MoveColRow(ACol, ARow: Longint; MoveAnchor, Show: Boolean);
begin
     inherited MoveColRow(ACol, ARow, MoveAnchor, Show);
end;

//Sorting
function StringCompare(const Str1, Str2: String): Integer;
begin
     if Str1 < Str2 then Result:=-1
     else if Str2 < Str1 then Result:=1
     else Result:=0;
end;

function DateCompare(const Str1, Str2: String): Integer;
var
   Val1, Val2: TDateTime;
begin
     try
        Val1:=StrToDateTime(Str1);
        Val2:=StrToDateTime(Str2);
        if Val1 < Val2 then
           Result:=-1
          else
           if Val2 < Val1 then
              Result:=1
             else
              Result:=0;
     except
        on EConvertError do Result:=0;
     end;
end;

function NumericCompare(const Str1, Str2: String): Integer;
var
   Val1, Val2: Extended;
begin
     try
        if str1='' then
           Val1:=0
          else
           Val1:=StrToFloat(Str1);
        if str2='' then
           Val2:=0
          else
           Val2:=StrToFloat(Str2);
        if Val1 < Val2 then
           Result:=-1
          else
           if Val2 < Val1 then
              Result:=1
             else
              Result:=0;
     except
        on EConvertError do Result:=0;
     end;
end;

function Compare(Item1, Item2: Pointer): Integer;
var
   Entry1, Entry2: PSortedListEntry;
begin
     Entry1:=Item1;
     Entry2:=Item2;

     //Handle Case-Insensitivity.
     if not GlobalSortOptions.SortCaseSensitive then
        begin
             Entry1^.Str:=Uppercase(Entry1^.Str);
             Entry2^.Str:=Uppercase(Entry2^.Str);
        end;

     //Determine compare type and do the comparison.
     case GlobalSortOptions.SortStyle of
          ssNumeric: Result:=NumericCompare(Entry1^.Str, Entry2^.Str);
          ssDate: Result:=DateCompare(Entry1^.Str, Entry2^.Str);
     else
         Result:=StringCompare(Entry1^.Str, Entry2^.Str);
     end;

     //Now, make sure we don't swap the rows if the Keys are equal.
     //If they're equal then we sort by row number.
     if Result = 0 then
        begin
             if Entry1^.RowNum < Entry2^.RowNum then
                Result:=-1
               else
                if Entry1^.RowNum > Entry2^.RowNum then
                   Result:=1
                  else
                   Result:=0; //Sometimes an item does get compared to itself.
        end
       else //Reverse polarity if descending sort.
        if GlobalSortOptions.SortDirection = sdDescending then
            Result:=-1*Result;
end;

{******************************************************************************}
{** Public Members for TSortedList                                           **}
{******************************************************************************}

function TSortedList.GetItem(const i: Integer): PSortedListEntry;
begin
     //Cast the pointer.
     Result:=PSortedListEntry(Items[i]);
end;

procedure TSortedList.Reset;
var
   i: Integer;
begin
     //Dispose of anything in the list first.
     for i:=0 to Count-1 do
         if Items[i] <> nil then
            Dispose(Items[i]);

     //Now clear the list.
     Clear;
end;

procedure GridMoveTo(Grd:TStringGrid;ACol, ARow: Longint);
begin
     with grd do
          begin
               if ACol < FixedCols then ACol:=FixedCols;
               if ARow < FixedRows then ARow:=FixedRows;
               if TCustGridEnh(grd).SelectCell(ACol, ARow) then
                  begin
                       Col:=ACol;
                       Row:=ARow;
                       TCustGridEnh(grd).MoveColRow(ACol, ARow, True, True);
                  end;
          end;
end;


//This function tries to determine the best sort style
//for a column.  If all the entries can be converted to
//numbers, a numeric sort is returned.  If they can all
//be converted to dates, a date sort is returned.
//Otherwise, an alphabetic sort is returned.
function DetermineSortStyle(grd:TStringGrid;const ACol: Longint): TSortStyle;
var
   i: Integer;
   DoNumeric, DoDate: Boolean;
begin
     with grd do
          begin
               DoNumeric:=True;
               DoDate:=True;
               //Note: We only go through the rows once.
               //This code depends on the fact that no
               //entry can be both a date and number.
               //If that fails to hold true, this will
               //return a numeric sort.
               for i:=FixedRows to RowCount-1 do
                   begin
                        if DoNumeric then
                           begin
                                try
                                   if Cells[ACol,i]<>'' then StrToFloat(Cells[ACol, i]);
                                except
                                   on EConvertError do
                                      begin
                                           DoNumeric:=False;
                                           if not DoDate then Break;
                                      end;
                                end;
                           end;
                        if DoDate then
                           begin
                                try
                                   StrToDateTime(Cells[ACol, i]);
                                except
                                   on EConvertError do
                                      begin
                                           DoDate:=False;
                                           if not DoNumeric then Break;
                                      end;
                                end;
                           end;
                   end;
               if DoNumeric then
                  Result := ssNumeric
                 else
                  if DoDate then
                     Result := ssDate
                    else
                     Result := ssAlphabetic;
          end;
end;

{Grid Sort}
procedure SortGrid(grd:TStringGrid;ACol:integer);
var
   i: Integer;
   Item: PSortedListEntry;
   BufferGrid: TStringGrid;
begin
     GlobalSortOptions.SortStyle:=DetermineSortStyle(grd,ACol);
     with grd do
          begin
               try
                  //Get rid of any old entries in the sorted list.
                  SortedList.Reset;

                  //Set the sort options for the list.
                  //"Compare" can only look at GlobalSortOptions.
                  //GlobalSortOptions:=SortOptions;

                  //Insert the Row Number and Key (Str) into
                  for i:=FixedRows to RowCount-1 do
                      begin
                           New(Item);
                           Item^.RowNum:=i;
                           Item^.Str:=Cells[ACol, i];
                           SortedList.Add(Item);
                      end;

                  //Quick Sort the list by key string.
                  //Then the row numbers will indicate where
                  //each row should be placed.
                  //E.g. If list item 0 contains a RowNum of 4 then
                  //row 4 should be the first row (position 0).
                  SortedList.Sort(Compare);

                  //Now rearrange the rows of the grid in sorted order.
                  //This is a fast but space inefficient way to do it.
                  //First, create a buffer grid and size it correctly.
                  BufferGrid:=TStringGrid.Create(nil);
                  try
                     BufferGrid.ColCount:=ColCount;
                     BufferGrid.RowCount:=RowCount;
                     //Copy the rows to the buffer grid in sorted order.
                     for i:=0 to SortedList.Count-1 do
                         begin
                              Item:=SortedList.GetItem(i);
                              BufferGrid.Rows[i+FixedRows].Assign(Rows[Item^.RowNum]);
                         end;
                     //Now put the rows back into the original grid.
                     for i:=FixedRows to RowCount-1 do
                         begin
                              Rows[i].Assign(BufferGrid.Rows[i]);
                         end;
                  finally
                     BufferGrid.Free;
                  end;

                  //Now put the selection back on the right row.
                  for i:=0 to SortedList.Count-1 do
                      begin
                           Item:=SortedList.GetItem(i);
                           if Item^.RowNum = Row then
                              begin
                                   GridMoveTo(grd,Col, i+FixedRows);
                                   Break;
                              end;
                      end;
               finally
               end;
          end;
end;

initialization
begin
     SortedList:=TSortedList.create;
     with GlobalSortOptions do
          begin
               SortDirection:=sdAscending;
               SortCaseSensitive:=false;
          end;
end;

finalization
begin
     SortedList.free;
end;

end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -