![](/img/trans.png)
[英]Visual Studio 2015 VB.net How to find record in MS Access database and disable button in form?
[英]How to Create a New Record in an Access Database using Visual Studio 2019 (VB.NET) Button Click
免責聲明:我對編碼和編程非常陌生; 抱歉,如果編碼低於標准。
我的目標是讓我的 Visual Studio 2019 項目(名為 Detailing Error Log)根據選中的復選框將新記錄/行添加到我的 Microsoft Access 數據庫表(名為 Database1 的 accdb 文件,名為 Data Collection 的表)中。 每當單擊“導入”按鈕時,我只想添加行,而不是刪除行。 然后將保存數據庫,並且取消選中我的 Visual Studio 項目中的復選框。 數據庫將用於存儲該數據,直到協調的 Visual Studio 程序使用它來計算特定月份內特定文本的出現次數。 從那里它將以圖表的形式顯示。
我已經使用 Excel 成功地做到了這一點; 但是每當有多個條目時都會經歷太多的延遲。
我的問題是我從我的“ dsnewrow ”變量中得到這個錯誤:
System.NullReferenceException:“對象引用未設置為 object 的實例。” System.Data.DataTableCollection.this[string].get 沒有返回任何內容。
所以我在谷歌和編程論壇上四處尋找,我並沒有真正找到任何我認為與我想要完成的工作相匹配的帖子:每次單擊“導入”按鈕時添加一條新記錄。 我添加新記錄的代碼是否正確? 我看到了幾種“添加”新記錄的不同方式,但是通過查看類似的帖子,我認為這是我最好的選擇。
以下是我的代碼,感謝您的幫助::
NEATOL = 記錄時沒有條目
Private Sub ConnectionPrep(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim dbProvider As String
Dim dbSource As String
Dim sql As String
Dim inc As Integer
Dim MaxRows As Integer
Dim con As New OleDb.OleDbConnection
dbProvider = "PROVIDER=Microsoft.ACE.OLEDB.12.0;"
dbSource = "Data Source = S:\software\Melton System\DPD & DEL (KPI)\Database1.accdb; Persist Security Info = False"
con.ConnectionString = dbProvider & dbSource
con.Open()
End Sub
Private Sub InputInformation(sender As System.Object, e As System.EventArgs) Handles ImporttBUT.Click
Dim con As New OleDb.OleDbConnection
Dim ds As New DataSet
Dim da As OleDb.OleDbDataAdapter
Dim cb As New OleDbCommandBuilder()
Dim dsnewrow As DataRow
dsnewrow = ds.Tables("Data Collection").NewRow()
dsnewrow.Item("M/Y OF LOG") = Me.MonthList2021.SelectedItem
dsnewrow.Item("TIME OF LOG") = DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss")
dsnewrow.Item("USER") = UserName
dsnewrow.Item("STOCK NUMBER") = Me.StockNumberTXTB.Text
If MissedPartCHKB.Checked = True Then
dsnewrow.Item("MISSED PART") = Me.MissedPartCHKB.Text
ElseIf MissedPartCHKB.Checked = False Then
dsnewrow.Item("MISSED PART") = "NEATOL"
End If
If NotInEpicorCHKB.Checked = True Then
dsnewrow.Item("NOT IN EPICOR") = Me.NotInEpicorCHKB.Text
ElseIf NotInEpicorCHKB.Checked = False Then
dsnewrow.Item("NOT IN EPICOR") = "NEATOL"
End If
If MissedBuyoutCHKB.Checked = True Then
dsnewrow.Item("MISSED BUYOUT") = Me.MissedBuyoutCHKB.Text
ElseIf MissedBuyoutCHKB.Checked = False Then
dsnewrow.Item("MISSED BUYOUT") = "NEATOL"
End If
If NonStockCHKB.Checked = True Then
dsnewrow.Item("MISSED NON STOCK ITEM") = Me.NonStockCHKB.Text
ElseIf NonStockCHKB.Checked = False Then
dsnewrow.Item("MISSED NON STOCK ITEM") = "NEATOL"
End If
If MissedSTKItemCHKB.Checked = True Then
dsnewrow.Item("MISSED STOCK ITEM") = Me.MissedSTKItemCHKB.Text
ElseIf MissedSTKItemCHKB.Checked = False Then
dsnewrow.Item("MISSED STOCK ITEM") = "NEATOL"
End If
If MissedAutomatedPartCHKB.Checked = True Then
dsnewrow.Item("MISSED AUTOMATED") = Me.MissedAutomatedPartCHKB.Text
ElseIf MissedAutomatedPartCHKB.Checked = False Then
dsnewrow.Item("MISSED AUTOMATED") = "NEATOL"
End If
If MissingPrintAfterQTYCHKB.Checked = True Then
dsnewrow.Item("MISSING PRINTS AFTER QUANTITY") = Me.MissingPrintAfterQTYCHKB.Text
ElseIf MissingPrintAfterQTYCHKB.Checked = False Then
dsnewrow.Item("MISSING PRINTS AFTER QUANTITY") = "NEATOL"
End If
If MissedPrintsNOTSentChadCHKB.Checked = True Then
dsnewrow.Item("MISSED PRINT NOT SENT TO CHAD") = Me.MissedPrintsNOTSentChadCHKB.Text
ElseIf MissedPrintsNOTSentChadCHKB.Checked = False Then
dsnewrow.Item("MISSED PRINT NOT SENT TO CHAD") = "NEATOL"
End If
If OtherCHKB.Checked = True Then
dsnewrow.Item("OTHER") = Me.OtherTXTB.Text
ElseIf OtherCHKB.Checked = False Then
dsnewrow.Item("OTHER") = "NEATOL"
End If
If AddedMissingDimCHKB.Checked = True Then
dsnewrow.Item("ADDED MISSING DIMENSION") = Me.AddedMissingDimCHKB.Text
ElseIf AddedMissingDimCHKB.Checked = False Then
dsnewrow.Item("ADDED MISSING DIMENSION") = "NEATOL"
End If
If FixedDimensionCHKB.Checked = True Then
dsnewrow.Item("FIXED DIMENSION") = Me.FixedDimensionCHKB.Text
ElseIf FixedDimensionCHKB.Checked = False Then
dsnewrow.Item("FIXED DIMENSION") = "NEATOL"
End If
ds.Tables("Counting").Rows.Add(dsnewrow)
da.Update(ds, "Counting")
MsgBox("Entry succesfully added to database.")
MissedPartCHKB.Checked = False
MissedAutomatedPartCHKB.Checked = False
NotInEpicorCHKB.Checked = False
NonStockCHKB.Checked = False
MissedSTKItemCHKB.Checked = False
MissedBuyoutCHKB.Checked = False
MissedPrintsNOTSentChadCHKB.Checked = False
MissingPrintAfterQTYCHKB.Checked = False
AddedMissingDimCHKB.Checked = False
FixedDimensionCHKB.Checked = False
OtherCHKB.Checked = False
OtherTXTB.Text = ""
MonthList2021.SelectedItem = False
End Sub
好的,你很接近。
所以,數據適配器 - 你想給它一個 VALID sql - 而不僅僅是一個表名。
sqlCommand builder - 你聲明它 - 但它與 NOTHING ELSE 相關聯!
所以,你需要這個:
Dim con As New OleDb.OleDbConnection(My.Settings.TestDB)
因此,您創建了連接 object - 但沒有提供連接的詳細信息。 我建議您在設置中創建該連接 - 使用連接構建器。
Dim da As OleDb.OleDbDataAdapter
您創建此適配器 - 但需要連接,更重要的是,它還需要一些 sql。
因為我們只打算添加行,所以讓我們給適配器一個 sql 語句——但它不會返回任何記錄——但我們仍然需要填寫這個適配器。
所以,使用這個:
Dim da As OleDb.OleDbDataAdapter("SELECT * from [Data Collection] WHERE ID = 0",con)
接下來,您創建了一個命令構建器(這很好),但是您忽略了它與其他任何東西的連接或關聯,因此您需要/想要這個:
Dim cb As New OleDbCommandBuilder()
變成這樣:
Dim cb As New OleDbCommandBuilder(da)
當您執行上述操作時,將為您構建插入、刪除、更新和 select 命令(很好。!)。
現在,要添加一個新的數據行?
完成上述所有操作后,我們需要加載我們的數據表(同樣,它只是坐在那里 - 沒有連接到任何東西)。 所以,這樣做:
但是,你有
Dim ds As New DataSet
不,我們不需要“一組”桌子——你需要一張桌子。
所以把上面改成
將 ds 暗淡為新數據表
現在,讓我們填充(更重要的是)將我們的表與我們的數據連接對象相關聯。
da.Fill(ds)
現在您可以在 ds 中編輯行(但我們沒有。!!)。
現在我們可以創建一個全新的單獨行 object (就像你做的那樣),但我傾向於這樣做:
With ds.Rows.Add
.item("Some Field Name") = "your value goes here"
.etc .etc
End With
但是,如果您希望創建一個全新的單獨行,則可以。 同樣,該行在這里不能只是“完全獨立”。
因此,您可以這樣創建空白行:
Dim myRow As DataRow = rstTable.Rows.Add
或者在您的情況下: dsnewrow = ds.Rows.Add
添加一行或幾行之后?
然后您必須將這些新行發送回數據庫。
da.Update(ds)
現在請注意我是如何使用“ds”的,但它是一個數據表而不是數據集。 您“可以”使用數據集 - 但實際上,您不需要數據集。
另外,最后但並非最不重要的是?
那么,適配器、閱讀器、object 和 sql 的連接?
您可以使用包含以上所有 3 個的 object。 這將節省您的手指,以及幾個變量。
所以,我建議這種設置 - 因為連接 object 和 sql 和 sql 命令都在一個 ZA8CFDE6331BD54B66AC96F8911C 中。
所以,這是我使用的“模板”:
Using cmdSQL As New OleDbCommand("SELECT * from tblHotels WHERE ID = 0",
New OleDbConnection(My.Settings.TestDB))
Dim da As New OleDbDataAdapter(cmdSQL)
Dim sqlBuild As New OleDbCommandBuilder(da)
Dim rstTable As New DataTable
da.Fill(rstTable)
With rstTable.Rows.Add
.Item("HotelName") = "The zoo Hotel."
End With
' add one more row - but with row var
Dim MyOneRow As DataRow = rstTable.Rows.Add
MyOneRow("HotelName") = "The Barn Hotel"
MyOneRow("City") = "My City"
' write BOTH ROWS back to database - all data rows were AND ARE added to rstTable
da.Update(rstTable)
End Using
編輯 - 評論問題的答案
您將 cmdSQL 定義為什么?
我有這個:
Dim cmdSQL As New OleDbCommand
or I have this
Dim cmdSQL As OleDbCommand = New OleDbCommand
兩者等同於同一件事。 注意在某些情況下我使用了 OleDb.OleDbCommand,在某些情況下我使用了 OleDBcommand(我省略了 OleDB)
我能夠節省一些手指和打字,而不必使用 OleDB。 作為前綴,因為在模塊的頂部(在任何代碼之前)我有這個:
Imports System.Data.OleDb
如果我忽略了上面的內容,那么我必須使用 OleDb。但是有了上面的導入,我可以自由地忽略 OleDB。 (OleDB(點)前綴)。
>>Fill" 不是 OleDbDataAdapter() 的成員,
它應該是。 我假設你這樣做:
Using cmdSQL As OleDbCommand = New OleDbCommand("SELECT * from tblHotels WHERE ID = 0",
New OleDbConnection(My.Settings.TestDB))
Dim da As New OleDbDataAdapter(cmdSQL)
當然,上面(聲明)了“使用”中的 cmdSQL object。 因此,您不能在 using/end using 塊之外使用 cmdSQL。
>>得到許多與我的變量“da”相關的錯誤; BC3031 類型“OleDbDataAdapter()”的值無法轉換為“OleDbDataAdapter”
您將 da 聲明為
請注意,在這種情況下,我如何在上面獲取/擁有“填充”作為 da 的方法。
由於您注意到我的最后一個“使用”示例有效,因此您的代碼中出現了一些問題。
例如,你有這個:
Private Sub ConnectionPrep(.............
好的,但是該代碼是 100% 獨立的,並且與您的代碼所在的第二個例程 100% 隔離。 第二個例程看不到,也不使用(也沒有)與第二個發布的例程有任何關系。
那么如何、何時、何地使用第一個例程?
並且幾乎不需要將該連接字符串設置放入代碼中。
為此使用項目設置。
例如這個頁面:
那么,當您使用上述連接構建器時呢? 然后,所有提供程序和設置現在都可以在代碼中的任何地方使用。
您可以使用
My.Settings.TestDB
因此,上面將返回一個有效的工作連接字符串 - 在這種情況下為 oleDB。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.