VB.net table iteration - vb.net

I have this code now. But it fails at three steps. Can you help me figure this out??
I have listed the three points where it fails.
Also please validate for me If I'm doing it right?
Retrieve the string from the tb_metatags textbox
Dim s As String
s = Me!tb_metaatags
parse the string into substrings by looking for the commasDim arrLines() As String
Dim arrLines() As String
arrLines = Split(s, ",")
For each substring, check if the substring is in the MetaSearchTags table
Dim itm As Variant
For Each itm In arrLines
Dim strsql As String
Dim numrows As Integer
strsql = "SELECT COUNT(*) FROM MetaSearchTags WHERE SearchTag = " & itm & ""
Dim objcmd As New OleDbCommand(strsql, conn) "I get an error here
numrows = objcmd.ExecuteScalar
If numrows > 0 Then
MsgBox("Record Exists", vbInformation, "Add") "I get an error here
Else
Dim myadapter1 As New OleDbDataAdapter("INSERT INTO MetaSearchTags ( SearchTag) "VALUES ('" & itm & "')", conn) "I get an error here
Dim mytable1 As New DataTable
myadapter1.Fill (mytable1)
End If
if it is not already in the MetaSearchTags table, then add it to the table
get the primary key (ID) for the substring from the MetaSearchTags table
Add an row in the MetaSearchTagAssignments table for this search tag
using the projectID, and the substring ID from the MetaSearchTags table
Repeat this process for each substring entered in the field

OleDbCommand.ExecuteScalar returns
The first column of the first row in the result set, or a null
reference if the result set is empty.
You need to handle this null reference (in VB.NET this equates to Nothing) when no records are returned.
One way to do this is:
Dim numrows as String = String.Empty
numrows = objcmd.ExecuteScalar()
If numrows Is Nothing Then
'Do something with the error condition
Else
'Do something with numrows which contains a valid result.
End If
(I would rename numrows)
You are also attempting to insert a record into the table even though no results are returned. This wouldn't be an error, but you have indicated (although it is a little difficult to interpret) that SearchTag is a primary key, in which case it will be an error to attempt to insert a duplicate.
And, as mentioned, you need to correct the quotes and apostrophes for your INSERT statement.

You need to put single quotes around strings in SQL statements:
strsql = "SELECT COUNT(*) FROM MetaSearchTags WHERE SearchTag = " & itm & ""
Should be:
strsql = "SELECT COUNT(*) FROM MetaSearchTags WHERE SearchTag = '" & itm & "'"

Related

Simple way to convert dbNull to a string in VB.NET

I'm looking for a simpler way to check if a value is dbNull and to convert it to an empty string if so.
An example of a situation where I need this would be:
Dim dt As New DataTable
Dim conn As New OleDbConnection(someConnStr)
Dim adap As New OleDbDataAdapter(qryCSSInfo, cssConn)
adap.Fill(dt)
Dim someStr As String = "The first column of the first row returned: " & dt.rows(0).item(0)
Msgbox(someStr)
The problem is that if dt.rows(0).item(0) is null in the database it will be returned as a dbNull value, which can apparently not be appended to a string.
My solution to this problem has been using if statements to replace the value with blank strings:
Dim dt As New DataTable
Dim conn As New OleDbConnection(someConnStr)
Dim adap As New OleDbDataAdapter(qryCSSInfo, cssConn)
adap.Fill(dt)
If Not isDBNull(dt.rows(0).item(0)) then
Dim someStr As String = "The first column of the first row returned: " & dt.rows(0).item(0)
Else
Dim someStr As String = "The first column of the first row returned: " & ""
End If
Msgbox(someStr)
This works fine for my purposes, but it gets overwhelming if I have to make this check for every column I need to use in the table. Say I had 10 columns from the table that I wanted to display with this string. I'd have to make this check on each one to ensure they weren't null. Is there an easier or simpler way of doing so?
For string types you can directly use it this way dt.rows(0).item(0).ToString(), without the If condition
adap.Fill(dt)
Dim someStr As String = "The first column of the first row returned: " & dt.rows(0).item(0).ToString()
MsgBox(somestr)
i.e. you can completely omit the if statement. As per MSDN any DBNull value will be converted to EmptyString with .ToString()
Also check this SO post Conversion from type 'DBNull' to type 'String'
However, for non-string database column types such as integers, doubles you must apply checks using IsDBNull to avoid any exceptions.
You can leverage the If Operator to reduce a few lines of code:
Dim someStr As String = "The first column of the first row returned: " & _
If(dt.rows(0).item(0) Is DbNull.Value, String.Empty, dt.rows(0).item(0))
You should be able to concatenate a null field with a string - it should convert to an empty string. That said row.IsNull(index) is a good test to use.
SQL = "Select top 10 Region, CompanyName FROM Suppliers"
Dim dt As DataTable = Gen.GetDataTable(SQL, scon)
For Each row As DataRow In dt.Rows
MsgBox(row("companyName") & " region: " & row("Region")) ' null allowed
If row.IsNull("region") Then ' .Net test for Null
MsgBox(row("companyName") & " region is null")
Else
'continue
End If
Next
You can also resolve this in the query - covert nulls to useful (or empty) strings. The example query is from SQL Server, I don't know if your DB supports COALESCE.
MsgBox("COALESCE") ' SQL Server - may not be the same in ODBC databases
SQL = "Select top 10 COALESCE(Region,'na') Region, CompanyName FROM Suppliers"
dt = Gen.GetDataTable(SQL, scon)
For Each row As DataRow In dt.Rows
MsgBox(row("companyName") & " region: " & row("Region"))
Next
Some coding notes:
Dim dt As New DataTable
Dim conn As New OleDbConnection(someConnStr)
Dim adap As New OleDbDataAdapter(qryCSSInfo, cssConn)
adap.Fill(dt)
If Not IsDBNull(dt.Rows(0).Item(0)) Then ' in OP
'...
End If
' save some typing if you know there will be only one record
' will throw exception is no rows are returned, check for expected count
Dim row As DataRow = dt.Rows(0)
If Not IsDBNull(row(0)) Then
'...
End If
' or
If Not row.IsNull(0) Then
'...
End If
' note the fields can be accessed by name so you can avoid hard coding field position
If Not row.IsNull("FieldName") Then
'...
End If
The simplest way to do it is just add a "" after the field or string.
Eg.:
dim EmptyString as string = Nullfield() & ""
if EmptyString = ""
' in the sample, it should.
end if
So, in your code you can use:
If dt.rows(0).item(0) & "" = "" then
' it should be...
end if
I got some null data into cells of a datagrid; to correctly retrieve that data
I concatenate the "" string to the cell value:
Dim readVal As String = "" & row.Cells(2).Value

Mass-Update Form w/VBA & SQL - ID not pulling correctly, records not being written to temp table

Edited since original posting: I realized that I had declared the volId variable as an Integer, but it's being read as a string. Once I changed the declaration to "Dim volId As String" the SQL code appears to be getting generated properly. Now I just need help in figuring out why the records are not being inserted into the temporary table.
I am trying to create a form that will allow the user to create multiple work records without having to re-enter the date, hours, and category information. (Ex: 10 people worked the same shift at the holiday party.) The way I plan to do this is to create a temp table, write a complete record to the table for each volunteer selected, then do an INSERT query to select everything from the temp table and insert the records into the real Work_Records table. (This second portion is not done yet. I'm debugging as I go, and have gotten stuck with the first part.)
The problem is that my records do not appear to actually be getting inserted into the temp table. I'm guessing that something is wrong with my SQL code.
Thanks!
My code:
Private Sub qryAppendMassWorkRecords_Click()
On Error Resume Next
DoCmd.RunSQL "DROP TABLE Tmp"
'Declare Vars
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Dim rstRecords As Recordset
Dim dynamicSQL As String
Dim strSQL As String
Dim strTable As String
Dim hrsWorked As Integer
Dim DateWorked As Date
Dim pgmWorked As Integer
Dim volId As String
'Set initial values
Set db = CurrentDb
Set qdf = db.QueryDefs("qryTempAppendTable")
'Create new temp table to hold values from the form
strSQL = "CREATE TABLE Tmp (VolunteerID VARCHAR(20), DateWorked DATETIME, HoursWorked INT, WorkCategory INT);"
db.Execute strSQL
'Grab the values for the static vars and assign them
For Each ctl In Me.Controls
If ctl.Properties("Name") = "DateWorked" Then
DateWorked = ctl.Value
End If
If ctl.Properties("Name") = "HoursWorked" Then
hrsWorked = ctl.Value
End If
If ctl.Properties("Name") = "WorkCategory" Then
pgmWorked = ctl.Value
End If
Next ctl
'If combo box length > 0, create an INSERT statement to add the record to the temp table
For Each ctl In Me.Controls
If ctl.ControlType = acComboBox Then
'Category is the only combo box other than the ones for volunteer names; make sure it's not getting picked up
If ctl.Properties("Name") <> "WorkCategory" Then
'Verify that the field contains a name
If Len(ctl.Value) > 0 Then
volId = ctl.Value
'Reset the dynamicSQL to the initial code & add form values
dynamicSQL = "INSERT INTO Tmp VALUES (" _
& "'" & volId & "', #" & DateWorked & "#, " & hrsWorked & ", " & pgmWorked & ");"
db.Execute dynamicSQL
End If
End If
End If
qdf.SQL = dynamicSQL
Next ctl
DoCmd.OpenTable "Tmp", acViewPreview
End Sub
Try this:
dynamicSQL = "INSERT INTO Tmp VALUES ('" _
& volId & "', #" & DateWorked & "#, " & hrsWorked & ", " & pgmWorked & ");"
It will get a good Access SQL string:
INSERT INTO Tmp VALUES ('15', #12/02/2013#, 5, 3);
In Access Database, Datetime must be quoted with sharp #, like: #mm/dd/yyyy hh:mm:ss#,
or #yyyy-mm-dd hh:mm:ss#...
#12/02/2013#
More your VolunteerID is a string, so single quote like this:
'15'
Please notify, Access can only execute one single "INSERT" instruction, not multiple INSERT's as in MySQL. If you have many records, you must do a loop using VBA.
And run it to insert into Tmp, that you have not done:
db.Execute dynamicSQL
For example, this worked for me:
Sub qryAppendMassWorkRecords_Click()
On Error Resume Next
Dim strSQL As String
Dim db
'Set initial values
Set db = CurrentDb
strSQL = "CREATE TABLE Tmp (VolunteerID VARCHAR(20), DateWorked DATETIME, HoursWorked INT, WorkCategory INT);"
db.Execute strSQL
strSQL = "INSERT INTO Tmp VALUES ('242013', #12/2/2013#, 4, 39);"
db.Execute strSQL
DoCmd.OpenTable "Tmp", acViewPreview
End Sub

Update in new column after inserting into 2 columns in a db

I am using following code to insert records into a table from another table....
Private Sub InsDuplicateDB()
Dim strInsDup As String = "INSERT INTO Duplicate_srno(Sr_no,chalan_no) SELECT sr_no,chaln_no FROM Vendor_Machine where sr_no=#srno"
Dim comm_InsDup As OleDb.OleDbCommand = New OleDb.OleDbCommand(strInsDup, cnnOLEDB)
comm_InsDup.Parameters.AddWithValue("#srno", cmbSn_no.Text)
comm_InsDup.ExecuteNonQuery()
Dim strUpdDup As String = "UPDATE Duplicate_srno SET sr_no = #srno,chaln_no =#chn_no,Problem=#problemWHERE sr_no = #srno AND chalan_no=#chn_no"
Dim comm_Update As OleDb.OleDbCommand = New OleDb.OleDbCommand(strUpdDup, cnnOLEDB)
comm_Update.Parameters.AddWithValue("#srno", cmbSn_no.Text)
comm_Update.Parameters.AddWithValue("#chn_no", cmbChal_no.Text)
comm_Update.Parameters.AddWithValue("#problem",strProb)
comm_Update.ExecuteNonQuery()
End Sub
Here strProb is a string whose value is assigned in anoter sub function..
Here it gives error as "No values given for one or more required parameter.."
Please resolve my problem
I don't know if this is a typo or not, but the update string lacks of a space between the parameter name #problem and the WHERE clause
Dim strUpdDup As String = "UPDATE Duplicate_srno SET sr_no = #srno,chaln_no =#chn_no," & _
"Problem=#problem WHERE sr_no = #srno AND chalan_no=#chn_no"
^
However the update string could be simplified because you are updating two fields with the same values used in the where clause
Dim strUpdDup As String = "UPDATE Duplicate_srno SET Problem=#problem " & _
"WHERE sr_no = #srno AND chalan_no=#chn_no"
Apart from the missing space the error message says that the engine expects more parameters.
In OleDb the parameters are not recognized by their name. You need the same number of parameter that are defined by the placeholders in the string. In your original text, you have 5 placeholders but you add only 3 parameters. It doesn't matter if two of them are the same.
The revised code coould be the following
Dim strUpdDup As String = "UPDATE Duplicate_srno SET Problem=#problem " & _
"WHERE sr_no = #srno AND chalan_no=#chn_no"
Dim comm_Update As OleDb.OleDbCommand = New OleDb.OleDbCommand(strUpdDup, cnnOLEDB)
comm_Update.Parameters.AddWithValue("#problem",strProb)
comm_Update.Parameters.AddWithValue("#srno", cmbSn_no.Text)
comm_Update.Parameters.AddWithValue("#chn_no", cmbChal_no.Text)
Notice how I have added the #problem parameter as first in the collection. Now, the parameter collection is in the same order in which the placeholders are present in the command text.

insert values with different delimiter

i want to insert values into a table, with an INSERT INTO statement but i would like to use a different delimiter (not a comma) how do i do this?
i dont want to use a comma for the following reason:
the data is in this format:
|something|somethingelse|something3 ,moretextinsamefield|
field1 = "something"
field2 = "somethingelse"
field3 = "something3 ,something4"
Why don't you use the Split function which lets you specify a delimiter:
Dim aValues As Variant
aValues = Split("|something|somethingelse|something3 ,something4", "|")
ADDITION
Here is some sample code in VBA.
Public Sub AppendValues()
Const SOURCE_VALUES = "|something|somethingelse|something3 ,moretextinsamefield|"
Dim aValues As Variant
aValues = Split(SOURCE_VALUES, "|")
Dim oDB As DAO.Database
Dim oRS As DAO.Recordset
Set oDB = DBEngine.Workspaces(0).Databases(0)
Set oRS = oDB.OpenRecordset("Table1", dbOpenTable)
oRS.AddNew
oRS("Col1") = aValues(1)
oRS("Col2") = aValues(2)
oRS("Col3") = aValues(3)
oRS.Update
Set oRS = Nothing
Set oDB = Nothing
End Sub
Writing SQL to do this will get very complicated very quickly, with a bunch of nested Mid() and InStr() functions.
Instead, I'd do it with a function that uses Split().
Public Function SplitField(varInput As Variant, strDelimiter As String, lngItemRequested As Long) As Variant
Dim varTemp As Variant
Dim arrInput() As String
varTemp = varInput
If Left(varTemp, 1) = strDelimiter Then
varTemp = Mid(varTemp, 2)
End If
If right(varTemp, 1) = strDelimiter Then
varTemp = Left(varTemp, Len(varTemp) - 1)
End If
arrInput = Split(varTemp, strDelimiter)
If lngItemRequested - 1 <= UBound(arrInput()) Then
SplitField = arrInput(lngItemRequested - 1)
If SplitField = vbNullString Then
SplitField = Null
End If
Else
SplitField = Null
End If
End Function
Then in SQL, you'd call it thus:
INSERT INTO TargetTable( Field1, Field2, Field3, Field4 )
SELECT SourceTable.SourceField, SplitField([SourceField],"|",1),
SplitField([SourceField],"|",2),
SplitField([SourceField],"|",3),
SplitField([SourceField],"|",4)
FROM SourceTable
Note that the function I wrote can be used even when there is a variable number of subparts in the source field. That is, if some have 4 parts and some 2, it doesn't matter, as the function returns Null for the parts that aren't there.
Would it be easier to do a pre-insert operation and clean up the data? Replace the |'s with ,'s, and enclose all values in quotes (or something like that)?
If not, I think if you format the data in a text file, you can use Access to import text and specify that | is the delimiter, rather than ,.
Check out this article: Pipe Delimited File into access database
Try this code.
The approach is as given below.
Import the data from the text file to a temporary table ('Import')
Update existing records in the table ('Dest') by joining the imported
table and the existing table
Select the records from the 'Import' table which are not present
in the 'Dest' table
Insert these new records to the 'Dest'
You need to modify the queries as per
your table structure.
Dim conn As New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=G:\VBNET\Access\bin\dest.mdb")
'Import data to a temporary table
Dim cmd As New OleDbCommand("SELECT * INTO [import] FROM [Text;FMT=Delimited;Database=G:\VBNET\Access\bin;Hdr=Yes].[Students.txt]", conn)
conn.Open()
cmd.ExecuteNonQuery()
'Update Existing records
Dim updateQuery As String = "UPDATE Dest INNER JOIN Import ON Dest.id = Import.F1 set Dest.Name = Import.F2"
Dim queryCmd As New OleDbCommand(updateQuery, conn)
queryCmd.ExecuteNonQuery()
Dim selectQuery = "select F1, F2, F3 from Import where F1 not in (select Id from Dest) "
queryCmd = New OleDbCommand(selectQuery, conn)
Dim dataReader As OleDbDataReader
dataReader = queryCmd.ExecuteReader()
Dim appendrecords As New ArrayList()
Dim insertQuery As String
While dataReader.Read()
Dim F1 As String = dataReader.GetString(0).ToString()
Dim F2 As String = dataReader.GetString(1).ToString()
Dim F3 As Integer = dataReader.GetInt32(2).ToString()
insertQuery = "insert into Dest values ('" & F1 & "', '" & F2 & "', " & F3 & ")"
appendrecords.Add(insertQuery)
End While
dataReader.Close()
Dim i As Integer
For i = 0 To appendrecords.Count - 1
Dim insertCmd As OleDbCommand = New OleDbCommand(appendrecords(i), conn)
insertCmd.ExecuteNonQuery()
Next
conn.Close()
If you prefer to do this with an INSERT statement, it's simple. Call the subroutine like this:
Call InsertValues("|something|somethingelse|something3 ,moretextinsamefield|")
Uncomment the Execute line to actually do the INSERT instead of just displaying the statement.
Public Sub InsertValues(ByVal pstrInput As String)
Dim i As Integer
Dim strSql As String
Dim strValList As String
Dim varValues As Variant
varValues = Split(pstrInput, "|")
'first and last array members are empty strings; skip them '
For i = 1 To 3
strValList = strValList & ", " & Chr(34) & varValues(i) & Chr(34)
Next i
'strip off leading comma and space '
strValList = Mid(strValList, 3)
strSql = "INSERT INTO YourTable (field1, field2, field3)" & _
vbNewLine & "Values (" & strValList & ");"
Debug.Print strSql
'CurrentDb.Execute strSql, dbFailOnError '
End Sub

How do I store the results of my select statement in a variable?

My code so far is this. The last line gives me a compile error: "expected end of statement".
Dim strSql As String
Dim groupId As String
strSql = "Select ID from RevenueGroup where description = '" & ListO.Value & "'"
groupId = CurrentProject.Connection.Execute strSql
You are looking at something kinda like this
Dim strSql As String
Dim groupId As String
strSql = "Select ID from RevenueGroup where description = '" & ListO.Value & "'"
Dim rec As Recordset
set rec= CurrentProject.Connection.Execute strSql
groupId = rec(0)
You need to set the results of the query to a recordset and then pull the first value from its results. Without all the defined variable, I cannot get this to fully compile but this should be a good template to start from.