0

我有一个 adotable,我想从多个组合框应用多个过滤器,每个组合框都将一个过滤器应用于该表。我的问题是,每当我从组合框 1 中选择一个项目时,它都会应用其过滤器,但是当我从下一个组合框(组合框 2)中选择另一个项目时,它会删除前一个过滤器(组合框 1)并应用组合框 2 中的过滤器。我的问题是:如何使 adotable 保留来自 combobox1 或 combobox2 甚至两者的先前过滤器,但还添加来自 combobox3 的第三个过滤器以进行更深入的排序?提前致谢。这是我到目前为止所做的:

procedure TForm1.ComboBox1Change(Sender: TObject);
begin
ADOTable1.Filtered:=false;
ADOTable1.filter:='`enter code here`field1='+ QuotedStr(ComboBox1.Text);
ADOTable1.Filtered:=true;
end;

procedure TForm1.ComboBox2Change(Sender: TObject);
begin
ADOTable1.Filtered:=false;
ADOTable1.filter:=adotable1.Filter+'and field2='+ QuotedStr(ComboBox1.Text);
ADOTable1.Filtered:=true;
end;

procedure TForm1.ComboBox3Change(Sender: TObject);
begin
ADOTable1.Filtered:=false;
ADOTable1.filter:=adotable1.Filter+'and field3='+ QuotedStr(ComboBox1.Text);
ADOTable1.Filtered:=true;
end;
4

2 回答 2

1

以上代码多次修改后报错,每次都需要重新组合过滤文本

procedure TForm1.ComboBox1Change(Sender: TObject);
begin
    ComboBoxChange();
end;

procedure TForm1.ComboBox2Change(Sender: TObject);
begin
    ComboBoxChange();
end;

procedure TForm1.ComboBox3Change(Sender: TObject);
begin
    ComboBoxChange();
end;


procedure TForm1.ComboBoxChange();
var
    count: integer;
    sFilter: string;
begin
    count := 0;
    sFilter := '`enter code here`';
    
    if(ComboBox1.Text <> '') then
    begin
        sFilter := 'field1=' + ComboBox1.Text;
        Inc(count);
    end;
    if(ComboBox2.Text <> '')then
    begin
        if count > 0 then
            sFilter := sFilter + 'and field2=' + ComboBox2.Text
        else
            sFilter := sFilter + ' field2=' + ComboBox2.Text
        Inc(count);
    end;
    if(ComboBox3.Text <> '')then
    begin
        if count > 0 then
            sFilter := sFilter + 'and field3=' + ComboBox3.Text
        else
            sFilter := sFilter + ' field3=' + ComboBox3.Text
        Inc(count);
    end;
    ADOTable1.Filtered:=false;
        ADOTable1.filter:=sFilter;
    ADOTable1.Filtered:=true;
end;
于 2021-02-01T01:12:36.073 回答
0

免责声明:此答案中的解决方案需要支持泛型,因此它不能在旧版本的 Delphi 中工作(你不应该)

  1. 您可以应用Tag属性来存储字段索引,您将使用该索引在过滤器生成中获取字段名称。 标签设置

  2. 要存储每个过滤器的值,您可以使用FormTDictionary的私有字段。

    uses 
      { here all other modules }, System.Generics.Collections;
    
    type
      TForm1 = class(TForm)
        { here all components declaration }
      strict private
        Filters: TDictionary<Integer, string>;
    

    我们应该Filters在 App 启动时进行初始化。您可以在执行初始设置的任何地方执行此操作(OnCreateOnShowForm; 部分的任何其他事件initialization;等)。我将使用OnCreate事件处理程序作为示例。您可以通过双击 OnCreate 附近的空单元格在 Object Inspector的Event选项卡中生成空处理程序并将其自动附加到 Form :OnCreate 事件处理程序

    Filters所以现在我们应该在这个事件处理程序中初始化:

    procedure TForm1.FormCreate(Sender: TObject);
    begin
      { here all your previous setup (if exist) }
      Filters := TDictionary<Integer, string>.Create;
    end;
    

    如果需要,您还应该在那里初始化过滤器的默认值。如果您TextObject Inspector中设置默认值并希望它们用于过滤查询,则必须这样做,因为这些值不会自动保存到我们Filters的事件中,因为没有OnChange触发事件。

  3. 现在让我们定义将值存储到的通用OnChange事件处理程序:TComboBoxFilters

    首先,我们应该将事件处理程序的签名添加到Form类的公共部分。由于 public 是类中的默认访问修饰符,您可以在组件列表或其他处理程序(如果存在)下添加您的函数:

    type
      TForm1 = class(TForm)
        { here all components declaration }
        procedure ComboBoxChange(Sender: TObject);
    

    然后你可以将光标指向这个声明并按ShiftCtrlCwhich 应该让 IDE 生成如下的空函数:

    procedure TForm1.ComboBoxChange(Sender: TObject);
    begin
    
    end;
    

    我们已经Tag为每个 ComboBox 定义了唯一值,因此我们可以将其用作键。事件处理程序非常简单:

    procedure TForm1.ComboBoxChange(Sender: TObject);
    begin
      with Sender as TComboBox do
        Filters.AddOrSetValue(Tag, Text);
    end;
    

    最后,您应该将此事件处理程序添加到每个 ComboBox。复制函数名称并将其粘贴到Object Inspector的Events选项卡附近OnChange的一个空单元格中,对要用于过滤的每个 ComboBox 重复此操作: OnChange 事件处理程序

  4. 最后一步是编写函数,该函数将生成过滤器查询并更新我们的事件处理程序以使用 ADOTable。让我们在 Form 类的私有部分定义我们的函数:

    type
    TForm1 = class(TForm)
      { here all components declaration }
    strict private
      Filters: TDictionary<Integer, string>;
      function GetFilterQuery(SkipEmptyValues: Boolean = False): string;
    

    ShiftCtrlC生成函数。Filters在函数中,我们将使用for ... in循环进行迭代,string.Format用于为每个元素创建过滤器字符串Filtersstring.Join连接所有创建的字符串(我已用作TList<string>临时数据容器)

    function TForm1.GetFilterQuery(SkipEmptyValues: Boolean): string;
    var
      Pair: TPair<Integer, string>;
      Conditions: TList<string>;
    begin
      result := string.Empty;
      Conditions := TList<string>.Create;
    
      for Pair in Filters do
        with Pair do
          if (not SkipEmptyValues) or (not Value.IsEmpty) then
            Conditions.Add(string.Format('field%d=%s', [Key, Value.QuotedString]));
    
      if Conditions.Count > 0 then
        result := string.Join(' and ', Conditions.ToArray);
    
      Conditions.Free;
    end;
    

    最后,我们应该在我们的OnChange事件处理程序中调用这个函数:

    procedure TForm1.ComboBoxChange(Sender: TObject);
    var
      Query: string;
    begin
      with Sender as TComboBox do
        Filters.AddOrSetValue(Tag, Text);
    
      Query := GetFilterQuery(True);
      if not Query.IsEmpty then
      begin
        ADOTable1.Filtered := False;
        ADOTable1.Filter := Query;
        ADOTable1.Filtered := True;
      end;
    end;
    
于 2021-02-01T14:06:41.723 回答