如何仅基于TListbox项目显示指定的数据库结果?

时间:2015-12-30 00:42:51

标签: database sqlite delphi delphi-xe8

我有两种形式: frmMakeQuote frmQuoteTemp

frmMakeQuote 中有两个 TListboxes lboMtrlList lboSelectedMtrl

lboMtrlList 显示数据库中的产品描述列。

procedure TfrmMakeQuote.FormCreate(Sender: TObject);
begin
  con := TFDConnection.Create(nil);
  query := TFDQuery.Create(con);
  con.LoginPrompt := false;
  con.Open('DriverID=SQLite;Database=C:\Users\kasio\Documents\Embarcadero\' +
    'Studio\Projects\ProgramDatabase;');
  query.Connection := con;

  query.SQL.Text :=
    'SELECT [Material Description] FROM MtrlDatabase ORDER BY MtrlID';
  try
    query.Open;
    lboMtrlList.Items.Clear;
    while not query.EOF do
    begin
      lboMtrlList.Items.Add(query.Fields[0].AsString);
      query.Next;
    end;
  finally
    query.Close;
  end;
end;

当此人双击 lboMtrlList 中的任何“产品”时,它会移至 lboSelectedMtrl 。 (基本上,它显示了所选的'产品'。)

procedure TfrmMakeQuote.lboMtrlListDblClick(Sender: TObject);
begin
  lboSelectedMtrl.Items.Add(lboMtrlList.Items.Strings[lboMtrlList.ItemIndex]);
end;

我希望能够从数据库中显示产品描述 Price 列,只能从 lboSelectedMtrl 。它们应显示在 frmQuoteTemp 上名为 sgdMaterials 的TStringGrid中。

我写了这样的话:

procedure TfrmMakeQuote.performMtrlQuery;
var
  i: integer;
begin
   for i := 1 to frmMakeQuote.lboSelectedMtrl.ItemIndex do
   begin
  query.SQL.Text := 'SELECT [Material Description], Price FROM MtrlDatabase ' +
   'WHERE [Material Description] = "'
   + frmMakeQuote.lboSelectedMtrl.Items.Strings[1]
   + '" ORDER BY MtrlID';
  query.Open;
  query.First;
   end;
end;

它没有显示任何错误,但它不起作用并且什么也没显示,我知道它可能完全错误。

1 个答案:

答案 0 :(得分:4)

performMtrlQuery()内部的循环错误。如果lboSelectedMtrl中实际未选择任何内容,则其ItemIndex将为-1,并且循环不会遍历任何项目。不仅如此,即使选择了某个项目,您的循环也不会遍历所有可用项目。此外,当您索引到Strings[]属性时,您使用的是硬编码1而不是循环变量i

至于您的TStringGrid,为什么不使用TDBGrid,并将其绑定到正在按所需项目过滤数据库的DataSource?在任何情况下,performMtrlQuery()都没有做任何事情来填充网格,无论是直接将搜索结果存储在网格中,还是将结果存储在frmQuoteTemp可以的某个列表中从中读取。

请改为尝试:

procedure TfrmMakeQuote.performMtrlQuery;
var
  i: integer;
begin
  for i := 0 to frmMakeQuote.lboSelectedMtrl.Items.Count-1 do
  begin
    query.SQL.Text := 'SELECT [Material Description], Price FROM MtrlDatabase' +
      ' WHERE [Material Description] = "'
      + frmMakeQuote.lboSelectedMtrl.Items.Strings[i]
      + '" ORDER BY MtrlID';
    query.Open;
    query.First;
    // do something with query.Fields[0] and query.Fields[1] ...
    query.Close;
  end;
end;

话虽这么说,按照他们的描述搜索你的材料并不是最有效的搜索选项。您应该搜索他们的ID。我建议采用另一种方法来实现这一点 - 在虚拟模式(TListBox)中使用Style=lbVirtual控件,并将搜索结果存储在单独的TStringList对象中。这样,您可以将ID和描述一起存储在内存中,同时在UI中显示描述并在查询中使用ID。

尝试更像这样的事情:

procedure TfrmMakeQuote.FormCreate(Sender: TObject);
begin
  allmaterials := TStringList.Create;
  selectedmaterials := TStringList.Create;

  con := TFDConnection.Create(Self);
  con.LoginPrompt := false;
  con.Open('DriverID=SQLite;Database=C:\Users\kasio\Documents\Embarcadero\Studio\Projects\ProgramDatabase;');

  query := TFDQuery.Create(con);
  query.Connection := con;
  query.SQL.Text := 'SELECT MtrlID, [Material Description] FROM MtrlDatabase ORDER BY MtrlID';
  try
    query.Open;
    while not query.EOF do
    begin
      allmaterials.Add(query.Fields[0].AsString + '=' + query.Fields[1].AsString);
      query.Next;
    end;
  finally
    query.Close;
  end;

  lboMtrlList.Count = allmaterials.Count;
end;

procedure TfrmMakeQuote.FormDestroy(Sender: TObject);
begin
  allmaterials.Free;
  selectedmaterials.Free;
end;

// lboMtrlList OnData event handler
procedure TfrmMakeQuote.lboMtrlListData(Control: TWinControl; Index: Integer; var Data: string);
begin
  Data := allmaterials.ValueFromIndex[Index];
end;

// lboSelectedMtrl OnData event handler
procedure TfrmMakeQuote.lboSelectedMtrlData(Control: TWinControl; Index: Integer; var Data: string);
begin
  Data := selectedmaterials.ValueFromIndex[Index];
end;

procedure TfrmMakeQuote.lboMtrlListDblClick(Sender: TObject);
var
  Idx: Integer;
begin
  Idx := lboMtrlList.ItemIndex;
  if Idx = -1 then Exit;
  if selectedmaterials.IndexOfName(allmaterials.Names[Idx]) <> -1 then Exit;
  selectedmaterials.Add(allmaterials.Strings[Idx]);
  lboSelectedMtrl.Count := selectedmaterials.Count;
end;

procedure TfrmMakeQuote.performMtrlQuery;
var
  i: integer;
begin
  for i := 0 to selectedmaterials.Count-1 do
  begin
    query.SQL.Text := 'SELECT [Material Description], Price FROM MtrlDatabase' +
      ' WHERE MtrlID = '
      + selectedmaterials.Names[i];
    query.Open;
    query.First;
    // do something with query.Fields[0] and query.Fields[1] ...
    query.Close;
  end;
end;

最后,如果您切换到单个TCheckListBoxTListView控件而不是2个TListBox控件,则可以利用他们在每个项目上设置复选框的功能,然后您就可以#39;我们不再需要处理OnDblClick活动,也不需要在您的用户界面中显示两个材料副本。用户可以在调用performMtrlQuery()之前检查所需的项目。

我还建议对搜索结果使用虚拟TListView而不是TStringGrid。 UI看起来会更好(TStringGrid不是最好看的UI控件),并且您可以更有效地利用内存(如果您要显示大量数据,TStringGrid可能是内存耗费。)< / p>