Excel to VB: Can't read the zero behind - vb.net

I'm doing a connection with excel and I have a problem when I try to use an ID that have 0 behind...
I'm using a ListBox and add the IDs from the excel's worksheet as items. IDs have 9 numbers, like "123456789" or "098765430". So that I remove the last 4 characters to search the IDs with the same 5 numbers and add in another ListBox. It works fine, except with the codes with 0 (zero) behind.
Dim ConnectionString As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0; Data Source=" & Application.StartupPath & "\Tabela_Precos.xlsx; Extended Properties=Excel 12.0;")
ConnectionString.Open()
Dim ds As New DataSet
Dim dt As New DataTable
ds.Tables.Add(dt)
Dim da
For i = 0 To Form1.ListBox1.Items.Count - 1
Dim str As String = Compras.ListBox1.Items(i).ToString
Dim prod As String = str.Remove(str.Length - 4)
da = New OleDbDataAdapter("SELECT * FROM [Sheet1$] WHERE ID like '%" & prod & "%'", ConnectionString)
ListBox1.Items.Add(dt.Rows(i).Item(0))
Next

Your Excel file has the ID column entered as integer values, but is formatted for left-zero padding to present as a nine character field. Your Excel db connection is reading the values as numbers (type Double, even-though they are integers). Your original select statement is implicitly convert ID to a string for the Like comparison; however, this conversion does not now you want left-zero padding. To use this type of comparison, you need to format ID yourself.
Select * From [sheet1$] Where (Format([ID], ""000000000"") Like '" & prod & "%')"
As you have indicated in the comments above, this works. However, it is not the most efficient in terms of speed. Since ID is numeric, it should be faster to do a numeric comparison. You have already defined a String variable named prod and the following solution uses that variable to prepare a numeric value for use in constructing an alternate select based on your criteria.
Dim prodNum As Int32 = Int32.Parse(prod) * 10000I
Then the Select statement would become:
"Select * From [sheet1$] Where ((([ID]\10000) * 10000)=" & prodNum.ToString & ")"
These examples use a concatenated select statement, and ideally you would not do it this way, but rather use a parameterized statement with replacement values. I'll leave that exercise up to you to perform.

Related

How to cast DB2 Timestamp to vb.net date?

When I populate my vb.net gridview using DB2 SQL, it displays DB2 Timestamp as:
2020-08-25-14.59.11.000000
^ What's the cleanest way to cast that as a vb.net Date? FWIW, this works:
Dim mydate As Date = CDate("2020-08-25 14:59:11.000000")
But, the colons in 14:59:11 do not exist, the string I'm working with has 14.59.11
Any help greatly appreciated.
Edit:
As requested,
screenshot of what data looks like when queried in AS400
Edit2:
Dim strSelect As String = "" &
"SELECT SUBMITTIME " &
"FROM MYTABLE " &
"WHERE EFYEAR=" & Now.Year & " AND EFMONTH=" & Now.Month
Dim dt As DataTable = SQL.Get_DataTable(strSelect)
grv.DataSource = dt
grv.DataBind()
Get_DataTable is just using OleDbConnection, OleDbCommand, OleDbDataAdapter, etc to fill a DataTable.
You can't cast something as a type that it isn't. The whole point of casting is that you don't change the object but rather the way you access the object. If you're changing the object then it is a conversion, not a cast.
If you want to convert something then the first step is to know what you're converting from. If you are converting from a String of a known format to a DateTime then you would use Date.ParseExact.
If the data is in a DataTable, add a new column with the appropriate data type, do the conversion in a loop and then, if appropriate, remove the original column.
myDataTable.Columns.Add("DataColumn", GetType(Date))
For Each row As DataRow In myDataTable.Rows
row("DateColumn") = Date.ParseExact(CStr(row("TextColumn")), "yyyy-MM-dd-HH.mm.ss.ffffff", Nothing)
Next
myDataTable.Columns.Remove(myDataTable.Columns("TextColumn"))

How to write a query that uses a number as parameter and number type field?

I need to start a query to retrieve data from Access database using VBA which I want to use a variable number as a parameter. Is it possible?
like the:
field name: NMT field type (number)
table name: Orders
and the code is like the following:
Dim Con As New ADODB.Connection
Dim RS As New ADODB.Recordset
Dim X as Integer
X = me.textbox1.value
Con.Open "Provider= Microsoft.ACE.OLEDB.12.0;Data Source=" & U.Database01 & "\DB.accdb;Persist Security Info=False"
Rs.Open "select * from Orders where nmt = '" + X + "'", Con, adOpenDynamic, adLockPessimistic
Whenever I run this query, I get a run-time error '13' type mismatch.
Any suggestions ?
Multiple Issues
Type-mismatch in WHERE clause:
Your query (i.e. the WHERE clause) tries to compare a Number-column from database with a String-value (e.g. WHERE numberField = '123'). This will result in a runtime error Type mismatch (Error 13). See also similar question.
Unsafe to use + to concatenate Strings
When building the query you tried to concatenate the query-template with the number-parameter by a plus-sign. This works only when operating on numbers. See related question
Solution
remove single-quotes: you should compare the Number-column NMT with a number literal (e.g. WHERE nmt = 123)
use & to concatenate strings. This will also convert numbers to strings. Besides I explicitly used CStr function below.
Dim Con As New ADODB.Connection
Dim RS As New ADODB.Recordset
Dim strSQL As String
Dim nmtNumber as Integer ' you named it x before
nmtNumber = me.textbox1.value
strSQL = "SELECT * FROM Orders WHERE nmt = " & CStr(nmtNumber) ' removed single-quotes and used ampersand to concatenate with converted string
Con.Open "Provider= Microsoft.ACE.OLEDB.12.0;Data Source=" & U.Database01 & "\DB.accdb;Persist Security Info=False"
RS.Open strSQL, Con, adOpenDynamic, adLockPessimistic
Further improvement
I already extracted the SQL string (building) into a separate variable strSQL above.
Better would be to use predefined/prepared and parameterized queries:
QueryDef (DAO) where you can set the parameters (type-safe). See this question.
Command (ADODB) where you can set parameters (type-safe). See this question.
See also
What is ‘Run-time error ‘13’: Type mismatch’? And How Do You Fix It?
VBA Type Mismatch Error

Can't generate a StockID above 10

This is the code that tries to grab the largest StockID from the database (Access database) , but my problem is that it generates StockID's up to "S10", after this it simply doesn't increment any further. This is the subroutine that generates the StockID:
Sub generate_Stock_ID()
Dim Stock_start As String = "S"
Dim Stock_Gen As String = "SELECT MAX(StockID) FROM tblStock WHERE StockID LIKE '" & Stock_start & "%%%' "
Dim da As OleDbDataAdapter = New OleDbDataAdapter(Stock_Gen, conn)
Dim ds As DataSet = New DataSet
da.Fill(ds, "StockID")
Dim dt As DataTable = ds.Tables("StockID")
Dim count As Integer = ds.Tables("StockID").Rows.Count
If ds.Tables("StockID").rows.count = 0 Then
StockID = "S1"
Else
StockID = ds.Tables("StockID").Rows(0).Item(0)
StockID = StockID.Substring(1, (StockID.Length - 1))
StockID = Stock_start & (StockID + 1)
End If
End Sub
Screenshot of my database
Note* there are multiple ID's for various other subroutines which all share the same incrementation issue, so if i fix this i fix the other ones too. So at the moment i think my problem lies in the syntax of my SQL statement, but im open to suggestions.
Thanks!
Don't treat an Integer as String. Otherwese MAX or ORDER BY will use lexicographical instead of numerical order which means that S11 is "lower" than S2.
So you should make this column an int-column and prepend S only where you display it. Then MAX(StockID) returns an Integer, you just have to cast it and add 1:
Using conn As New OleDbConnection("Connection-String")
Using cmd As New OleDbCommand(Stock_Gen, conn)
conn.Open()
Dim stockIDObj As Object = cmd.ExecuteScalar()
If stockIDObj IsNot Nothing Then
Dim maxStockId As Int32 = DirectCast(stockIDObj, Int32)
maxStockId += 1
' ...... '
End If
End Using
End Using
You should also change OPTION STRICT to ON. Then this would never compile since the same variable cannot be used for an Object, String and Integer which is very good since it prevents errors.
If you want to keep it as string you have to cast the substring always in the database which is less readable and less efficient. I also don't know how to do it in access.
If you want to change the type of column in an already populated table you should first add a new column with a similar name which is of type int. If all have S at the beginning you could first remove that, then you can update the new column with the casted int value. Finally you can delete the old column and rename the new to the old.
The root of this issue that StockID is a STRING and 'S1'>'S10' so for all StockId > 10 you get max = 'S1'.
As a fast fix try to change MAX(StockID) to:
SELECT 'S'+CAST(MAX(CAST(SUBSTRING(StockID,2,100) as int)) as varchar(100))
For ACCESS DB try to use:
SELECT "S" & cstr(MAX(CINT(MID(StockID,2,100))))

Can't compare vb.net item with access number

Edit: For anyone facing this problem, don't miss the tips about only using
parameters instead of inserting the values directly into the SQL queries.
i'm facing a big problem with my vb.net project, i'm stuck with this for a week
i've a combobox item that i need to compare with an access number which is my database to retrieve some information, but i just got an error, no matter what format i convert my combobox item, it says my datatype is inconpatible with the expression
Here's one of the SQL queries from my code:
Dim dt1 As New DataTable
'This query select some itens from a row that match with the selected combobox number
Dim find1 As New OleDb.OleDbDataAdapter("SELECT Product, Number," _
& " Customer, Quantity, ProductionDate, AskDay, Pack, Company FROM RegOPE" _
& " WHERE Number ='" & CInt(mycombobox.SelectedItem) & "'", cn)
'Ive tried SelectedItem, Item, Text, SelectedValue...
'For conversion i tried parse, tryparse, conversion...
cn.Open() 'Opens database connection
find1.Fill(dt1) <- I got the error here
cn.Close() 'Close database connect
mydatagrid.DataSource = dt1 'Show the result in datagridview
number criteria should be without quote
Dim find1 As New OleDb.OleDbDataAdapter("SELECT Product, Number, " _
& "Customer, Quantity, ProductionDate, AskDay, Pack, Company FROM RegOPE " _
& "WHERE Number =" & CInt(mycombobox.SelectedItem), cn)
But better always use parameters:
Dim comm = New OleDb.OleDbCommand("SELECT Product, Number, " _
& "Customer, Quantity, ProductionDate, AskDay, Pack, Company FROM RegOPE " _
& "WHERE Number =?", cn)
comm.Parameters.AddWithValue("unusedName", mycombobox.SelectedItem)
Dim find1 As New OleDb.OleDbDataAdapter(comm)
In your WHERE clause have you tried to remove the quotes ? They are not required if you are looking for a number.
First, I must mention that you really ought to be using parameters. You should not concatenate the values directly into the SQL command string like that. Your SQL command string should simply contain parameter name placeholders for those values and then you should specify the values for those parameters separately.
However, if you are going to concatenate the value with the command like that, the command is a string, not an integer. It makes little sense to use CInt to convert the item to an integer just before concatenating it with a string (which requires first converting it from the integer into a string). It would make more sense to simply call ToString to convert it to a string, instead of CInt. Also, if the Number column in your database is typed as a number, rather than as text, then you should not be surrounding the value with quotes.
I recommend trying this:
Dim find1 As New OleDb.OleDbDataAdapter("SELECT Product, Number," _
& " Customer, Quantity, ProductionDate, AskDay, Pack, Company FROM RegOPE" _
& " WHERE Number =" & mycombobox.SelectedItem.ToString(), cn)
Although, recommend is to strong a word, since I would never recommend doing it that way in the first place. Use parameterized queries!

Sorting numbers in Access and .NET

I have an Access table which has a Number field and a Text field.
I can run a query like this:
SELECT * FROM Table ORDER BY intID ASC
//outputs 1,2,3,10
But when I try to run the same query through the .NET OleDB client, like this:
Private Sub GetData()
Using cnDB As New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & Path)
cnDB.Open()
Dim SQL As String = "SELECT * FROM Table ORDER BY intID ASC"
Dim cmd As New OleDbCommand(SQL, cnDB)
Dim dr As OleDbDataReader = cmd.ExecuteReader()
While dr.Read()
lst.Items.Add(dr.Item("intID") & " - " & dr.Item("strName"))
End While
cnDB.Close()
End Using
End Sub
I get items in the order 1,10,2,3.
What's going on here, and how can I have the data sort "naturally" (1,2,3,10) in both places?
try
SELECT * FROM Table ORDER BY CInt(intID) ASC
to explicitly tell Access to treat this as an integer and not a string. Obviously, something in the OleDbClient is seeing this field as a string (text field) and sorting accordingly.
I suspect the problem is your connection string. If you're connecting to an Access database and include IMEX=1 in your connection string, the provider will treat all data as string. As such, the ordering will order by the string value, giving you 1, 10, 2, 3, as opposed to leaving the intID as an integer, and ordering it in numerical order.
It looks like you're getting a lexical (alphabetic) order. This will be correct if something in your database or query thinks that is a varchar/text column type instead of a numeric type.