我有两种形式: 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;
它没有显示任何错误,但它不起作用并且什么也没显示,我知道它可能完全错误。
答案 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;
最后,如果您切换到单个TCheckListBox
或TListView
控件而不是2个TListBox
控件,则可以利用他们在每个项目上设置复选框的功能,然后您就可以#39;我们不再需要处理OnDblClick
活动,也不需要在您的用户界面中显示两个材料副本。用户可以在调用performMtrlQuery()
之前检查所需的项目。
我还建议对搜索结果使用虚拟TListView
而不是TStringGrid
。 UI看起来会更好(TStringGrid
不是最好看的UI控件),并且您可以更有效地利用内存(如果您要显示大量数据,TStringGrid
可能是内存耗费。)< / p>