我正在開發一個銷售訂單應用程式。我正在使用 datagridview 來填寫銷售訂單。
我的datagridview中的欄位如下
ItemCode - ItemDescription - 數量 - 價格
描述欄位是一個組合框。
我想要的是當用戶輸入 ItemCode 時,它??會自動檢查我的資料庫并給我 Itemdescription
我還希望用戶能夠從作為組合框的 ItemDescription 中選擇一個專案,它會自動更新我的 Itemcode。
Private Sub salesorder_dgv_CellValueChanged(sender As Object, e As DataGridViewCellEventArgs) Handles salesorder_dgv.CellValueChanged
If salesorder_dgv.Rows.Count > 0 Then
If e.ColumnIndex = 0 Then
Dim READER As SqlDataReader
conn.Open()
Dim query As String
query = "select * from item where code = '" & salesorder_dgv.Rows(e.RowIndex).Cells(0).Value & "'"
cmd = New SqlCommand(query, conn)
READER = cmd.ExecuteReader
If READER.Read Then
salesorder_dgv.Rows(e.RowIndex).Cells(1).Value = READER.GetString(2)
End If
conn.Close()
End If
If e.ColumnIndex = 1 Then
Dim READER As SqlDataReader
conn.Open()
Dim query As String
query = "select * from item where description = '" & salesorder_dgv.Rows(e.RowIndex).Cells(1).Value & "'"
cmd = New SqlCommand(query, conn)
READER2 = cmd.ExecuteReader
If READER.Read Then
salesorder_dgv.Rows(e.RowIndex).Cells(0).Value = READER.GetString(1)
End If
conn.Close()
End If
End If
End Sub
有沒有辦法讓這段代碼作業?我收到“連接未關閉”
uj5u.com熱心網友回復:
那里有很多錯誤,所以我將首先解決您必須清理它的問題,然后解決您應該如何做的問題。
正如評論中所建議的,您應該在需要它們的地方創建所有 ADO.NET 物件,包括連接。您可以在最窄的范圍內創建、使用和銷毀。此外,如果您只想要來自單個列的資料,請不要使用SELECT *. 僅檢索您需要的列。由于您只從一行的一列中檢索資料,因此您應該使用ExecuteScalar而不是ExecuteReader.
接下來,您應該熟悉 DRY 原則,即不要重復自己。您有兩個幾乎相同的代碼塊,因此您應該提取公共部分并只撰寫一次并傳遞不同的部分。
最后,不要使用字串連接將值插入 SQL 代碼。始終使用引數。它避免了許多問題,最重要的是 SQL 注入,這在您的情況下很可能,因為用戶正在輸入自由文本。考慮到所有這些,您擁有的代碼將被重構如下:
Private Sub salesorder_dgv_CellValueChanged(sender As Object, e As DataGridViewCellEventArgs) Handles salesorder_dgv.CellValueChanged
If salesorder_dgv.RowCount > 0 Then
Dim sourceColumnIndex = e.ColumnIndex
Dim targetColumnIndex As Integer
Dim query As String
Select Case sourceColumnIndex
Case 0
targetColumnIndex = 1
query = "SELECT description FROM item WHERE code = @param"
Case 1
targetColumnIndex = 0
query = "SELECT code FROM item WHERE description = @param"
Case Else
Return
End Select
Dim row = salesorder_dgv.Rows(e.RowIndex)
Dim sourceValue = row.Cells(sourceColumnIndex).Value
Using connection As New SqlConnection("connection string here"),
command As New SqlCommand(query, connection)
command.Parameters.AddWithValue("@param", sourceValue)
connection.Open()
row.Cells(targetColumnIndex).Value = command.ExecuteScalar()
End Using
End If
End Sub
現在來看看你應該怎么做。如果您要使用所有描述填充組合框列,那么您必須首先在資料庫中查詢它們。您應該做的是檢索初始查詢中的描述和代碼。這樣,您永遠不必回傳資料庫。您可以使用代碼和描述填充 a DataTable,然后將為您完成大部分作業。
對于下面的示例,我首先在設計器中設定表單,這意味著在網格中添加和配置適當的列并添加BindingSource組件。這還包括設定DataPropertyName每個網格列的屬性,使其系結到適當的源列。我也在此處手動填充專案資料,但您將從資料庫中獲取該資料。
Private itemTable As New DataTable
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
LoadItemData()
LoadSaleData()
End Sub
Private Sub LoadItemData()
With itemTable.Columns
.Add("code", GetType(String))
.Add("description", GetType(String))
End With
With itemTable.Rows
.Add("123", "First Item")
.Add("abc", "Second Item")
.Add("789", "Third Item")
.Add("xyz", "Fourth Item")
.Add("01a", "Fifth Item")
End With
itemBindingSource.DataSource = itemTable
With itemDescriptionColumn
.DisplayMember = "Description"
.ValueMember = "Description"
.DataSource = itemBindingSource
End With
End Sub
Private Sub LoadSaleData()
Dim saleTable As New DataTable
With saleTable.Columns
.Add("ItemCode", GetType(String))
.Add("ItemDescription", GetType(String))
.Add("Quantity", GetType(Integer))
.Add("Price", GetType(Decimal))
End With
saleBindingSource.DataSource = saleTable
salesorder_dgv.DataSource = saleBindingSource
End Sub
Private Sub salesorder_dgv_CellValidating(sender As Object, e As DataGridViewCellValidatingEventArgs) Handles salesorder_dgv.CellValidating
If e.RowIndex >= 0 AndAlso
e.ColumnIndex = 0 AndAlso
Not String.IsNullOrEmpty(e.FormattedValue) Then
'Check that the code entered by the user exists.
e.Cancel = (itemBindingSource.Find("code", e.FormattedValue) = -1)
If e.Cancel Then
MessageBox.Show("No such item")
End If
End If
End Sub
Private Sub salesorder_dgv_CellValueChanged(sender As Object, e As DataGridViewCellEventArgs) Handles salesorder_dgv.CellValueChanged
Dim rowIndex = e.RowIndex
Dim sourceColumnIndex = e.ColumnIndex
If rowIndex >= 0 And sourceColumnIndex >= 0 Then
Dim sourceColumnName As String
Dim targetColumnName As String
Dim targetColumnIndex As Integer
Select Case sourceColumnIndex
Case 0
sourceColumnName = "code"
targetColumnName = "description"
targetColumnIndex = 1
Case 1
sourceColumnName = "description"
targetColumnName = "code"
targetColumnIndex = 0
Case Else
Return
End Select
Dim itemRow = itemBindingSource(itemBindingSource.Find(sourceColumnName, salesorder_dgv(sourceColumnIndex, rowIndex).Value))
Dim code = CStr(itemRow(targetColumnName))
salesorder_dgv(targetColumnIndex, rowIndex).Value = code
End If
End Sub
您首先填充專案并將該資料系結到組合框列,然后DataTable為銷售創建一個空白并將其系結到網格。該代碼檢查任何手動輸入的代碼是否確實與專案匹配,并且它將在手動輸入代碼時設定描述,并在從串列中選擇描述時設定代碼。它通過BindingSource每次回溯包含專案資料來做到這一點,因此沒有額外的查詢。您可能還需要考慮檢索每個專案的價格資料,并根據該資料和數量計算該行的價格。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/459302.html
