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

📄 ukingfilter1.pas

📁 delphi源码 delphi源码 delphi源码 delphi源码 delphi源码
💻 PAS
📖 第 1 页 / 共 2 页
字号:
unit uKingFilter;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  Buttons, StdCtrls, DB, ExtCtrls, ComCtrls, ku, ADODB, siComp,EhlibAdo;

type

  {
    '等于;不等于;大于;大于或等于;小于;小于或等于;始于;并非起始于;' +
    '止于;并非结束于;包含;不包含';
  }

  TFilterLogical = (flAnd, flOr);

  TFilterCondition = (fcEqual, fcNotEqual, fcGreat, fcGreatEqual,
    fcLess, fcLessEqual, fcBeginWith, fcNotBeginWith, fcEndWith, fcNotEndWith,
    fcContain, fcNotContain);

  { Forward declare }

  TKingFilterDialog = class;

  { TKingFilterForm }

  TKingFilter = class(TForm)
    gbDefineCondition: TGroupBox;
    cbFields: TComboBox;
    Label1: TLabel;
    cbConditions: TComboBox;
    Label2: TLabel;
    Label3: TLabel;
    cbLink: TComboBox;
    cbValue: TComboBox;
    GroupBox1: TGroupBox;
    btNew: TSpeedButton;
    btDel: TSpeedButton;
    btOk: TSpeedButton;
    btCancel: TSpeedButton;
    btClear: TSpeedButton;
    btReplace: TSpeedButton;
    gbFilterConditions: TGroupBox;
    lbFilter: TListBox;
    Panel1: TPanel;
    Label4: TLabel;
    btAddtodb: TSpeedButton;
    btDelFromDb: TSpeedButton;
    cbSavedList: TComboBox;
    siLang1: TsiLang;
    procedure lbFilterDrawItem(Control: TWinControl; Index: Integer;
      Rect: TRect; State: TOwnerDrawState);
    procedure lbFilterDblClick(Sender: TObject);
    procedure edtValueChange(Sender: TObject);
    procedure btNewClick(Sender: TObject);
    procedure btDelClick(Sender: TObject);
    procedure btOkClick(Sender: TObject);
    procedure btCancelClick(Sender: TObject);
    procedure btClearClick(Sender: TObject);
    procedure btReplaceClick(Sender: TObject);
    procedure cbSavedListChange(Sender: TObject);
    procedure btAddtodbClick(Sender: TObject);
    procedure btDelFromDbClick(Sender: TObject);
    procedure cbFieldsChange(Sender: TObject);
    procedure checkValueType(Sender: TObject);
  private
    { Private declarations }
    FFilterDialog: TKingFilterDialog;
  public
    DataSet: TDataSet;
    procedure LoadDBCondition;

    { Public declarations }
    constructor Create(AOwner: TComponent); override;
  end;

  { TKingFilterDialog }

  TKingFilterDialogOption = (dfdOnlyBuildFilter);
  TKingFilterDialogOptions = set of TKingFilterDialogOption;

  //  TFilterStrings = class(TStrings)

  TKingFilterDialog = class(TComponent)
  private
    FFilterStrings: TStrings;
    FFilterFields: string;
    //    FFieldTypes: array of TFieldType;
    FDataSet: TDataSet;
    FConditions: TStrings;
    FTitle: string;
    FSaveOnFilterRecord: TFilterRecordEvent;
    FSaveFiltered: Boolean;
    FPreFiltered: Boolean;
    FOptions: TKingFilterDialogOptions;
    //    function GetDataSet: TDataSet;
    function GetFilterFields: string;
    procedure SetTitle(const Value: string);
    procedure SetDataSet(Value: TDataSet);
    procedure SetFilterFields(const Value: string);
    function CanUseFilterCondition(Field: TField; FilterCondition:
      TFilterCondition): Boolean;
    procedure FilterStringsChange(Sender: TObject);
  protected
    //    procedure InitFieldTypes;
    procedure DataSetFilterRecord(DataSet: TDataSet; var Accept: Boolean);
      virtual;
    //    property DataSet: TDataSet read GetDataSet;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    function Execute: Boolean;
    function GetFilter: string; virtual;
    procedure GetFilterDescriptions(List: TStrings);
    property FilterStrings: TStrings read FFilterStrings;
  published
    property DataSet: TDataSet read FDataSet write SetDataSet;
    property FilterFields: string read GetFilterFields write SetFilterFields;
    property Title: string read FTitle write SetTitle;
    property Options: TKingFilterDialogOptions read FOptions write FOptions;
  end;

procedure ShowFilterForm(Dataset: TDataset);

var
  SaveTempFilterStr: TStringList; //保存临时的各个DATASETFILTER的记录

implementation

uses StrUtils;

{$R *.DFM}

function ExtractSubStr(const Str: string; var Pos: Integer; Delimiter: Char =
  ';'): string;
var
  I: Integer;
begin
  I := Pos;
  while (I <= Length(Str)) and (Str[I] <> Delimiter) do
    Inc(I);
  Result := Copy(Str, Pos, I - Pos);
  if (I <= Length(Str)) and (Str[I] = Delimiter) then
    Inc(I);
  Pos := I;
end;

function IndexOfFieldName(const Fields: string; Index: Integer): string;
var
  I, J, Pos: Integer;
begin
  Pos := 1;
  I := Pos;
  J := -1;
  while I <= Length(Fields) do
  begin
    if Fields[I] = ';' then
    begin
      Inc(J);
      if (J = Index) or (Index = -1) then
        Break;
      Pos := I + 1;
    end;
    Inc(I);
  end;
  Result := Trim(Copy(Fields, Pos, I - Pos));
  //  if (I <= Length(Fields)) and (Fields[I] = ';') then Inc(I);
end;

procedure ShowFilterForm(Dataset: TDataset);
var
  kFilter: TKingFilterDialog;
begin
  kFilter := TKingFilterDialog.Create(nil);
  try
    kFilter.DataSet := Dataset;
    kFilter.Execute;
  finally
    FreeAndNil(kFilter);
  end;
end;

{ TKingFilterForm }

constructor TKingFilter.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  if AOwner is TKingFilterDialog then
    FFilterDialog := AOwner as TKingFilterDialog;
end;

procedure TKingFilter.lbFilterDrawItem(Control: TWinControl;
  Index: Integer; Rect: TRect; State: TOwnerDrawState);
const
  Offset = 2;
var
  I: Integer;
  S, Temp: string;
begin
  with (Control as TListBox) do
  begin
    Temp := Items[Index];
    I := 1;
    if Index <> 0 then
    begin
      if ExtractSubStr(Temp, I, ';') = '0' then
        S := CS('并且')
      else
        S := CS('或者');
    end
    else
      ExtractSubStr(Temp, I);
    //取得字段的DisplayLabel
    S := S + ' ' + DataSet.FieldByName(ExtractSubStr(Temp, I)).DisplayLabel;
    //    S := S + ' ' + TField(Items.Objects[Index]).DisplayLabel;
        //[StrToInt(ExtractSubStr(Temp, I))];
    S := S + ' ' + cbConditions.Items[StrToInt(ExtractSubStr(Temp, I))];
    S := S + ' ' + ExtractSubStr(Temp, I) + ' ;';
    Canvas.FillRect(Rect);
    Canvas.TextOut(Rect.Left + Offset, Rect.Top, S);
  end;
end;

procedure TKingFilter.lbFilterDblClick(Sender: TObject);
var
  I: Integer;
  Temp: string;
begin
  Temp := lbFilter.Items[lbFilter.ItemIndex];
  I := 1;
  cbLink.ItemIndex := StrTointdef(ExtractSubStr(Temp, I), 0); //连接符,and=0 or 1

  cbFields.ItemIndex :=
    cbFields.Items.IndexOfObject(DataSet.FieldByName(ExtractSubStr(Temp, I)));
  // cbFields.ItemIndex :=
  //   cbFields.Items.IndexOfObject(lbFilter.Items.Objects[lbFilter.ItemIndex]);
   // StrToInt(ExtractSubStr(Temp, I));
  cbFields.OnChange(cbFields);
  cbConditions.ItemIndex := cbConditions.Items.IndexOfObject(
    TObject(StrToInt(ExtractSubStr(Temp, I))));
  //  case nbValue.PageIndex of
  //    0: edtValue.Text := ExtractSubStr(Temp, I);
  //    1: cbValue.ItemIndex := cbValue.Items.IndexOf(ExtractSubStr(Temp, I));
  //    2: dtpDate.Date := StrToDateTime(ExtractSubStr(Temp, I));
  //  end;
  cbValue.Text := ExtractSubStr(Temp, I);
end;

procedure TKingFilter.edtValueChange(Sender: TObject);
begin
  //  btnAddToList.Enabled := TEdit(Sender).Text <> '';
end;

{ TKingFilterDialog }

constructor TKingFilterDialog.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FConditions := TStringList.Create;
  with FConditions do
  begin
    AddObject(CS('等于'), TObject(fcEqual));
    AddObject(CS('不等于'), TObject(fcNotEqual));
    AddObject(CS('大于'), TObject(fcGreat));
    AddObject(CS('大于或等于'), TObject(fcGreatEqual));
    AddObject(CS('小于'), TObject(fcLess));
    AddObject(CS('小于或等于'), TObject(fcLessEqual));
    AddObject(CS('始于'), TObject(fcBeginWith));
    AddObject(CS('并非起始于'), TObject(fcNotBeginWith));
    AddObject(CS('止于'), TObject(fcEndWith));
    AddObject(CS('并非结束于'), TObject(fcNotEndWith));
    AddObject(CS('包含'), TObject(fcContain));
    AddObject(CS('不包含'), TObject(fcNotContain));
  end;
  FTitle := CS('智能筛选');
  FFilterStrings := TStringList.Create;
  TStringList(FFilterStrings).OnChange := FilterStringsChange;
end;

destructor TKingFilterDialog.Destroy;
begin
  FConditions.Free;
  FFilterStrings.Free;
  FDataSet := nil;
  inherited;
end;

function TKingFilterDialog.CanUseFilterCondition(Field: TField;
  FilterCondition: TFilterCondition): Boolean;
begin
  case Field.DataType of
    ftUnknown, ftString, ftFixedChar, ftWideString, ftMemo, ftVariant, ftBlob,
      ftFmtMemo:
      Result := True;
    ftSmallint, ftInteger, ftWord, ftFloat, ftCurrency, ftBCD, ftBytes,
      ftVarBytes, ftAutoInc, ftLargeint:
      Result := FilterCondition in [fcEqual, fcNotEqual, fcGreat, fcGreatEqual,
        fcLess, fcLessEqual];
    ftBoolean: Result := FilterCondition in [fcEqual, fcNotEqual];
    ftDate, ftTime, ftDateTime:
      Result := FilterCondition in [fcEqual, fcNotEqual, fcGreat, fcGreatEqual,
        fcLess, fcLessEqual];
    {ftGraphic, ftParadoxOle, ftDBaseOle, ftTypedBinary, ftCursor, ftADT
    ftArray, ftReference, ftDataSet, ftOraBlob, ftOraClob, ftInterface,
    ftIDispatch, ftGuid}
  else
    Result := False;
  end;
end;

procedure TKingFilterDialog.DataSetFilterRecord(DataSet: TDataSet; var Accept:
  Boolean);

  function CompareFieldValue(Field: TField; Value: string): Double;
  begin
    case Field.DataType of
      //      ftUnknown, ftString, ftFixedChar, ftWideString, ftMemo, ftVariant, ftBlob,
      //      ftFmtMemo:
      //        Result := True;
      ftSmallint, ftInteger, ftWord, ftAutoInc, ftLargeint:
        Result := Field.AsInteger - StrToInt(Value);
      ftFloat, ftCurrency, ftBCD, ftBytes, ftVarBytes:
        Result := AnsiCompareStr(Trim(Field.DisplayText), Value);
      // Result := Field.AsFloat - StrToFloat(Value);
   //        Result := FilterCondition in [fcEqual, fcNotEqual, fcGreat, fcGreatEqual,
   //          fcLess, fcLessEqual];
      ftBoolean: if (Field.AsBoolean = StrToBoolDef(Value, True)) then
          Result := 0
        else
          Result := 1; //FilterCondition in [fcEqual, fcNotEqual];
      ftDate: Result := Trunc(Field.AsDateTime) - StrToDate(Value);
      ftDateTime: Result := Field.AsDateTime - StrToDateTime(Value);
      ftTime: Result := Frac(Field.AsDateTime) - StrToTime(Value);
      //        Result := FilterCondition in [fcEqual, fcNotEqual, fcGreat, fcGreatEqual,
      //          fcLess, fcLessEqual];
            {ftGraphic, ftParadoxOle, ftDBaseOle, ftTypedBinary, ftCursor, ftADT
            ftArray, ftReference, ftDataSet, ftOraBlob, ftOraClob, ftInterface,
            ftIDispatch, ftGuid}
    else
      Result := AnsiCompareStr(Trim(Field.DisplayText), Value);
    end;
  end;

var
  I, APos: Integer;
  Condition: TFilterCondition;
  FieldName, Value, Temp: string;
  e: TFilterRecordEvent;
  s: string; //用来存放Dataset的全局命称,如Form1.Dataset1
  st: TStringList; //用来存放当前DATASET的FILTER条件
begin
  //这个函数就厉害了,它是用数据集的onfilter事件做过滤的,而且还能保存其原有的过滤代码
  Accept := True;
  //  if Accept = False then ShowMessage('Accept');
//如果用户已经指定了数据集的过滤事件,则先调用

//if Assigned(FSaveOnFilterRecord) then
//  FSaveOnFilterRecord(DataSet, Accept);

  s := DataSet.Owner.Name + '.' + DataSet.Name;
  st := TStringList.Create;
  try
    st.Text := SaveTempFilterStr.Values[s];
    s := s + '=' + st.Text;
    TMethod(e).Code := SaveTempFilterStr.Objects[SaveTempFilterStr.IndexOf(s)];
    if Assigned(E) then
    begin
      e(DataSet, Accept);
    end;

    if Accept then
      for I := 0 to st.Count - 1 do
      begin
        // Temp := SaveTempFilterStr.Values[DataSet.Owner.Name + '.' + DataSet.Name];
         //      ShowMessage(Temp);
        temp := st[i];

        APos := 1;
        if I <> 0 then
        begin
          if ExtractSubStr(Temp, APos, ';') = '0' then // Logic AND
          begin
            if not Accept then
              Break
          end
          else if Accept then
            Break;
        end
        else
          ExtractSubStr(Temp, APos, ';');
        // FieldName := TField(FFilterStrings.Objects[I]).FieldName;
        FieldName := ExtractSubStr(Temp, APos, ';');
        //ExtractFieldName(Temp, APos);//IndexOfFieldName(FFilterFields, StrToInt(ExtractFieldName(Temp, APos)));
        Condition := TFilterCondition(StrToInt(ExtractSubStr(Temp, APos, ';')));
        Value := ExtractSubStr(Temp, APos, ';');
        //      if DataSet.FieldByName(FieldName).DataType in [ftDate, ftDateTime] then
        //        Value := DateToStr(StrToDate(Value));
        case Condition of
          fcEqual: Accept := CompareFieldValue(DataSet.FieldByName(FieldName),
              Value) = 0;
          fcNotEqual: Accept :=
            CompareFieldValue(DataSet.FieldByName(FieldName),
              Value) <> 0;
          fcGreat: Accept := CompareFieldValue(DataSet.FieldByName(FieldName),
              Value) > 0;
          fcGreatEqual: Accept :=
            CompareFieldValue(DataSet.FieldByName(FieldName), Value) >= 0;
          fcLess: Accept := CompareFieldValue(DataSet.FieldByName(FieldName),
              Value) < 0;
          fcLessEqual: Accept :=
            CompareFieldValue(DataSet.FieldByName(FieldName),
              Value) <= 0;
          fcBeginWith: Accept :=
            LeftStr(DataSet.FieldByName(FieldName).AsString,
              Length(Value)) = Value;
          fcNotBeginWith: Accept :=
            LeftStr(DataSet.FieldByName(FieldName).AsString, Length(Value)) <>
              Value;
          fcEndWith: Accept := RightStr(DataSet.FieldByName(FieldName).AsString,
              Length(Value)) = Value;
          fcNotEndWith: Accept :=
            RightStr(DataSet.FieldByName(FieldName).AsString, Length(Value)) <>
              Value;
          fcContain: Accept := AnsiPos(Value,
              DataSet.FieldByName(FieldName).AsString) > 0;
          fcNotContain: Accept := AnsiPos(Value,
              DataSet.FieldByName(FieldName).AsString) = 0;
        end;
        //      ShowMessage(DataSet.FieldByName(FieldName).AsString + ' - ' + Value + ' = ' +
        //        FloatToStr(CompareFieldValue(DataSet.FieldByName(FieldName), Value)));
      end;
  finally
    FreeAndNil(st);
  end;
end;

//function TKingFilterDialog.GetDataSet: TDataSet;
//begin
//  if Assigned(FDataSource) then Result := FDataSource.DataSet
//  else Result := nil;
//end;

function TKingFilterDialog.GetFilter;

  function ValueToFilterText(const FieldName, Value: string): string;
  begin
    if Assigned(DataSet) then
      case DataSet.FieldByName(FieldName).DataType of
        ftSmallint, ftInteger, ftWord, ftAutoInc: Result := Value;
        ftFloat, ftCurrency, ftBCD, ftVarBytes, ftBytes, ftTypedBinary: Result
          := Value;
        //       ftDate, ftTime, ftDateTime:
        ftBoolean:
          if Value = CS('是') then
            Result := 'True'
          else
            Result := 'False';
      else
        Result := '''' + Value + '''';
      end
    else
      Result := Value;
  end;

var
  Temp, FieldName: string;
  I, Pos: Integer;
begin
  Result := '';
  for I := 0 to FFilterStrings.Count - 1 do
  begin
    Temp := FFilterStrings[I];
    Pos := 1;
    if I <> 0 then
    begin
      if ExtractSubStr(Temp, Pos, ';') = '0' then
        Result := Result + ' AND '
      else
        Result := Result + ' OR ';
    end

⌨️ 快捷键说明

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