I am trying to read data from an Excel table into a DataSet however I get an error: "No value given for one or more required parameters." I've done some research and learned that this error usually occurs when a required value is empty ("" in the case of a string) or null. Below is my code.
cnExcel = New System.Data.OleDb.OleDbConnection( _
"provider=Microsoft.Jet.OLEDB.4.0; " & _
"data source=" & FileName & "; " & _
"Extended Properties=Excel 5.0;")
cdImport = New System.Data.OleDb.OleDbDataAdapter( _
"select * from [" & cSheetName & "$] order by StoreID, ItemID", cnExcel)
dsImport = New System.Data.DataSet
cdImport.Fill(dsImport)
cnExcel.Close()
The error is occuring on cdImport.Fill(dsImport) presumably because there is nothing to fill dsImport with.
After doing some debugging I find that the Server Version field of cnExcel is: error: an excpetion of type: {System.InvalidOperationException} occured
What am I doing wrong?
Just in case anyone was wondering about how this got resolved:
I wound up just sending the excel file as a csv to my server. The server then runs a stored procedure on the file which returns a table to my application. A dataset is then filled from this table.
You may need to put additional quotes around the Extended Properties=Excel 5.0; part of your connection string (see connectionstrings.com for more information)
Related
I am trying to bulk load from a CSV file to an SQL Server (both Excel and SQL Server are sitting on my laptop). I am doing this via Excel VBA using the "bulk insert" statement. I keep getting a run-time error of invalid object name for my table.
I have tested the SQL in studio management and it works fine
The table name is definitely correct
I have tested using the different file formats and I get same error
"insert into..." statement works fine from Excel VBA just not the "BULK INSERT"
connServer.Open "Provider=SQLOLEDB;Data Source=" & pstrServer & ";Initial Catalog=" & pstrDBS & ";integrated security=sspi;"
strSQLQuery = "BULK INSERT tbl_q_member " & _ "FROM 'C:\test\bulk.csv' " & _ "WITH (FIRSTROW = 2, FIELDTERMINATOR = ',',ROWTERMINATOR = '\n', TABLOCK)"
connServer.Execute strSQLQuery
The runtime error is
'-2147217865 (800440e37)
Invalid object name 'tbl_q_member'
I have the following code in vb.net to sort a SQL Server table alphanumerically. It works in SQL Server Management Studio, but when I run the code in vb.net nothing happens.
Do I need to update the SQL Server table and how? Can I even do this directly from vb.net?
Dim opdragsorteeraplhanumeries As New SqlCommand
konneksie.ConnectionString = "Data Source=GIDEON-E-LAPTOP\SQLEXPRESS2014;Initial Catalog=SkeduleringDatabasis;Integrated Security=True"
konneksie.Open()
opdragsorteeraplhanumeries.Connection = konneksie
opdragsorteeraplhanumeries.CommandText = "SELECT * FROM Oesskattings " & _
"ORDER BY " & _
"CASE WHEN ISNUMERIC(blokno) = 1 THEN right(Replicate('0',21) + blokno, 21) " & _
"WHEN ISNUMERIC(blokno) = 0 then Left(blokno + Replicate('',21), 21) " & _
" ELSE blokno " & _
" End "
opdragsorteeraplhanumeries.ExecuteNonQuery()
konneksie.Close()
MsgBox("Alphanumeries gesorteer")
Regards
There's no sorting of a table going on there. Whether that code is executed in SSMS or not, what it is doing is getting the data from the table and sorting it. The table remains exactly as it was. If it is your intention to actually change the order of the data in the table then you'd have to move the data from original table into a temp table and then back again, doing the ordering on one of the two steps.
Would there really be any point to that though? Why exactly do you think you need the table sorted a particular way and, if that's really what you need, why isn't it like that to begin with? More likely you should simply sort the data when you retrieve it or perhaps create a view that does the sorting and get your data from there.
I'm using ADO in Excel 2007 VBA to return data from SQL Server. I'm aggregating lots of Select statements using Union All.
It's working fine for up to 110 aggregated Select statements, but at 115 of them I get the ADO error "Unspecified Error". At 110 Select statements it's returning about 7,000 rows and 255 columns, so its not an unusually large ADO recordset.
I thought ADO was probably passing on an error from SQL Server just as Excel VBA passed it on from ADO (I know that the error is from ADO, not VBA, because the error is shown in the ADO Connection object's Errors collection), so I sent the problem SQL statement with the 115 Select statements to my colleague who owns the SQL Server database being queried and asked her if she could tell me what SQL Server didn't like. However, it ran fine for her in the SQL Server query tool, and returned the expected data.
So it seems it's just ADO that doesn't like it when I go to the 115 Select statements; the SQL Server database itself is fine with it.
BTW I haven't tested with 111 - 114 Select statements; I've just narrowed it down to working fine with 110 and breaking on 115.
Any idea what the problem might be and what I can do about it?
For now I'm going to chunk it into sets of 50 Select statements as a workaround, but if it's possible to send it all at once I'd like to.
Here's the relevant code:
Public Const SQL_UNION_ALL_OPERATOR As String = " UNION ALL "
(the loop that aggregates the Select statements starts here)
stSQL = _
"select * from LikeItemExtract" & _
" where Dept = " & varLikeDept & "" & _
" and sup_name = '" & varLikeSupp & "'" & _
" and VPN = '" & varLikeVPN & "'" & _
" and Loc_Key = " & varCADLoc & "" & _
" and SUPP_COLOR = '" & varLikeColor & "'"
stSQLAll = stSQLAll & stSQL & SQL_UNION_ALL_OPERATOR
(end loop here)
'remove the final " UNION ALL ":
If Right(stSQLAll, Len(SQL_UNION_ALL_OPERATOR)) = SQL_UNION_ALL_OPERATOR Then
stSQLAll = Left(stSQLAll, Len(stSQLAll) - Len(SQL_UNION_ALL_OPERATOR))
End If
If CBool(rs1.State And adStateOpen) = True Then rs1.Close
rs1.Open stSQLAll, con, adOpenStatic, adLockReadOnly, adCmdText
iRecordsetRowCount = shAggData.Cells(1).CopyFromRecordset(rs1)
Thanks,
Greg
This code currently is using a DROP TABLE to transfer data from Access to SQL Server, that is when it was intended for one person to use. Now it is going to be used by multiple people so I need to alter the code to APPEND. I am trying to figure out how to get it to check the destination table to see if the record already exists, if it does it will skip over it, if not it will write that employees data to the table. The SQL table is prebuilt and it has a ROW ID column and TIME STAMP column that the access table does not have in order to keep track of the records being entered.
The code currently looks like:
Public Function Update()
Dim cdb As DAO.Database, qdf As DAO.QueryDef
Dim err As DAO.Error
Const DestinationTableName = "AC_CDData"
Const ConnectionString = _
"ODBC;" & _
"Driver={SQL Server Native Client 10.0};" & _
"Server=SERVER;" & _
"Database=DB;" & _
"UID=ID;" & _
"PWD=PW;"
Set cdb = CurrentDb
Set qdf = cdb.CreateQueryDef("")
qdf.Connect = ConnectionString
qdf.SQL = _
"IF EXISTS " & _
"(" & _
"SELECT * FROM INFORMATION_SCHEMA.TABLES " & _
"WHERE TABLE_NAME='" & DestinationTableName & " '" & _
") " & _
"DROP TABLE [" & DestinationTableName & "]"
qdf.ReturnsRecords = False
On Error GoTo Update_qdfError
qdf.Execute dbFailOnError
On Error GoTo 0
Set qdf = Nothing
Set cdb = Nothing
DoCmd.TransferDatabase _
acExport, _
"ODBC Database", _
ConnectionString, _
acTable, _
"CDData", _
DestinationTableName, _
False
Exit Function
Update_qdfError:
For Each err In DAO.Errors
MsgBox err.Description, vbCritical, "Error " & err.Number
Next
End Function
The DoCmd.TransferDatabase does a complete transfer of the data from the Access table, to the SQL Server database. This function can not do partial inserts based on existing records.
What you can do, however, is export the data into a temporary new table (without dropping the existing table), followed by executing an SQL MERGE statement, to incorporate the new records of the temporary table, with the existing table.
You'll need to know how to perform SQL queries from VBA against your SQL database, and you'll need to know how to use the SQL MERGE statement. A google search will quickly give you the answer to both.
Just setup a simple standared linked table to SQL server in Access.
Since the column of the existing record is a primary key (or simply an index set = unique), then you only need ONE LINE of code to append your data.
This will work:
CurrentDb.Execute "INSERT INTO AC_CDData SELECT * FROM CDData;"
Any row that already exists will be ignored due to key (or index) violation. Thus only new non existing records will be appended with the above one line of code.
Edit:
As for the target table being a SQL linked table? Your application on startup does not care if you have some linked tables. Your application does not use nor care about such linked tables unless you use them.
The assuming here is you have a local data table. The linked table ONLY comes into play when you going to do the export. As noted you cannot export unless you are connected to SQL server. The “code” or testing if you are connected is not dealt with in this question but even if it was part of the question in both cases you still have to test for a connection and once again when you do finally determine you have a connect and you decide to export then again the linked table as per above will work.
So there is really no reason I can think of as to why having a linked table that is ONLY used during the append to the SQL table will be any kind of issue or problem.
As stated, then the one line of VBA code should suffice here.
In case of concurrent usage the process need to be changed:
DestinationTableName must be unique per session (thread) and need to be changed (from constant to variable)
Tabel with DestinationTableName neame need and need to be dropped before the export data (as it was in current solution).
DoCmd.TransferDatabase will not change - the data will be exported into the unique temp table.
For simplifying the Merge process the stored procedure can be written on the SQL Server side (with all needed to APSERT logic) with the source table name as parameter. This SP need to be called after the DoCmd.TransferDatabase completion
In this case the flow will be the following:
DestinationTableName unique name generation
Dropping this table on the SQL Server side (qdf.Execute ...)
Export data to the temp table (DoCmd.TransferDatabase ...)
Merge data in the SQL Server side (call to created SP with needed logic of update / insert)
Started getting this error it seems since we upgraded to SQL Server 2008.
When inserting into the db and then returning the identity i get a 'Item cannot be found in the collection corresponding to the requested name or ordinal' error.
Here is the code:
SQL = "INSERT INTO PageFeatures(nPageFeatureFlagId,nPageFeatureFeatureId,nPageFeaturePageId) VALUES(" & nTemplateFlagId & "," & nFeatureId & "," & nPageId & "); SELECT SCOPE_IDENTITY() As nPageFeatureId;"
objrs.open SQL,objConn,1,1
nPageFeatureId = objrs("nPageFeatureId")
objrs.close
The insert is working as the record is in the db. It's not returning the id for some reason. It works fine and returns the id when running in SSMS. But ASP can't see the returned id so some reason.
Any help would be greatly appreciated!
You may have to try moving the recordset on? e.g.
SQL = "INSERT INTO PageFeatures(nPageFeatureFlagId,nPageFeatureFeatureId,nPageFeaturePageId) VALUES(" & nTemplateFlagId & "," & nFeatureId & "," & nPageId & "); SELECT SCOPE_IDENTITY() As nPageFeatureId;"
objrs.open SQL,objConn,1,1
objrs.NextRecordset
nPageFeatureId = objrs("nPageFeatureId")
objrs.close
Raj's comment about SQL injection is still relevant. :)
EDIT: Elaboration is that there are two recordsets in play here. The first is an empty one created by the insert statement, the second one is caused by everything after the semi-colon ;. This is the field you want. So initially, your objrs is attached to the first of its collection of recordsets (not rows in a recordset), you move to the NextRecordset - and you can then deal with that how you please.
Sorted:
SQL = "INSERT INTO PageFeatures(nPageFeatureFlagId,nPageFeatureFeatureId,nPageFeaturePageId) VALUES(" & nTemplateFlagId & "," & nFeatureId & "," & nPageId & ");"
objConn.execute(SQL)
Set oReturnValueRS = objConn.Execute("SELECT SCOPE_IDENTITY()")
nPageFeatureId = oReturnValueRS(0).Value
oReturnValueRS.close : set oReturnValueRS = nothing