How do I override the Header for field naming? - sql

Using SQL to query an Excel worksheet without a header row echos the information I have found in all my research. But that isn't what I am getting. Has there been a change in Excel 2016, or is my implementation wrong?
Sub vndrrst()
Dim cn As Object
Set cn = CreateObject("adodb.connection")
strfilename = ThisWorkbook.Path
cn.ConnectionString = _
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & strfilename & _
";Extended Properties=""text;HDR=NO;imex=1"";"
cn.Open
Set rs = cn.Execute("select * from My_Text_File.txt where F2='04-62425'")
Set rs = Nothing
Set cn = Nothing
End Sub
The error message reads "No value given for one or more required parameters." at the Set rs statement. When I change F2 to MFGID (the actual field name given in the header of this text file), it both runs and gives accurate output in the debug window... even though HDR=No.
So, how can I use the F field names if the file has a header this time? The reason this becomes interesting is because I have many text/csv/delimited files sent to my FTP, some have headers, some don't, and some have headers sometimes.
Edit: the schema.ini file reads
[My_Text_File.txt]
Format=TabDelimited
in case it matters.
A different related question is ADO Recordset to Excel spreadsheet opens properly in Excel 2007, has a missing parameter in Excel 2013, but the motivation/project of the OP is different, and therefore the answer is irrelevant.

Related

My oledb connection works on a workbook but not on the other

So i have this code in two different workbooks, two different files. They are even in the same folder in the same computer.
strFile = "Z:\service\climatizacion.mdb"
strCon = "Provider=Microsoft.ACE.OLEDB.12.0; Data Source=" & strFile
Set cn = CreateObject("ADODB.Connection")
cn.Open strCon
strSQL = "SELECT codigorep, cantidad, precio, descripcion FROM cotizacion WHERE codigorep = " & lngInput & ";"
Set rs = CreateObject("ADODB.RECORDSET")
rs.Open Source:=strSQL, ActiveConnection:=cn, CursorType:=adOpenDynamic, LockType:=adLockOptimistic
In one of the workbooks it works perfect, it selects all the data i need from the database.
On the other it gives me the Runtime error 3001 (The application is using arguments that are of the wrong type, are out of acceptable range, or are in conflict with one another) when I try to open the recordset.
I figured through this code that the connection was the problem (I may be wrong)
If cn.State = adStateOpen Then
MsgBox "connected"
Else
MsgBox "not connected"
End If
I cannot find the difference between these workbooks that can make this connection or the entire code work or make it stop working.
All the variables are declared, the tables exist, i can open them through access with no problems, the database is located on a pc on my local network.
The database is an mdb file, from access 97. And i'm running this on excel 2003, both workbooks, and both were created by me with the same excel 2003.
Thank you in advance for taking the time to read this :D

How do I write a sql query in vba to filter data while importing an excel file?

I have an excel file (raw data) which I have to import to another excel file (visualization interface). But, before importing the raw data file, I have to filter out the data of some columns. Can I write an sql query within my import file vba code?
For instance, I want to filter out the blank values from one column and see only numbers greater than 10 from another column.
This is possible. In your Visualization interface file (viz.xls) create a new module and add the
Microsoft ActiveX Data Objects 2.8 Library
Using Tools >> References
The following code will get you in the ballpark:
Sub getFromRawData()
Dim rawFile As String
Dim adoConn As ADODB.Connection
Dim adoRS As ADODB.Recordset
Dim strSQL As String
'The xlsx file to treat as a database
rawFile = "c:\myFolder\myrawdatafile.xlsx"
'Open a connection to the workbook
adoConn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & rawFile & ";Extended Properties=""Excel 12.0 Xml;HDR=YES"";"
'Write the SQL necessary to get the data you want (assuming Sheet1 and making up column names, which will be the first row of the sheet by default)
strSQL = "SELECT * FROM [Sheet1$] WHERE [onecolumn] IS NOT NULL AND [anotherColumn] > 10;"
'Now we open up our recordset using the connection and the sql statement
adoRS.Open strSQL, adoConn
'Last, we dump the results in this viz sheet
ThisWorkbook.Sheet1.Range("A2").CopyFromRecordset adoRS
'If you want the header row, you'll have to get that from the recordset:
Dim adoField As ADODB.Field
Dim intHdrCol
'initial column to start writing header
intHdrCol = 1
'loop through the fields in the recordset and write the column
For Each adoField In adoRS.Fields
Sheet1.Cells(1, intHdrCol).Value = adoField.Name
intHdrCol = intHdrCol + 1
Next adoField
'Close the connection
adoRS.Close
adoConn.Close
End Sub
Depending on your version of Excel you'll have to fiddle with that Connection String. The SQL statement will have to modified as well, obviously.. but with some tinkering this thing is ready to rock and roll.

Excel VBA Late Bind to Access and SQL Insert

I am having a frustrating issue with late binding to MS Access from Excel VBA to execute a DML statement like Insert or Update. All of the data I use in vba comes from user defined Classes. I can query just fine but writing to the DB gets different errors each time I try a different way to do the same thing. Below are some links to the same/similar issues, however each is slightly out of context and therefore I could not get passed my problem.
Microsoft.ACE.OLEDB.12.0 Current Recordset does not support updating error received when trying to update access
Operation must use an Updateable Query / SQL - VBA
Update an excel sheet using VBA/ADO
Operation must use an updatable query. (Error 3073) Microsoft Access
https://msdn.microsoft.com/en-us/library/bb220954%28v=office.12%29.aspx?f=255&MSPPError=-2147217396
http://www.access-programmers.co.uk/forums/showthread.php?t=225063
My end goal is to simply execute a DML string statement and it has to use late binding. Mainly I get the 3251 error saying my connection is 'Read Only' or a missing ISAM when I add ReadOnly=0 to the connection string. Fyi, getProjectFile just returns a path to a file starting from the parent folder of my project. I am pretty sure I can just use the connDB.Execute so I only need SQL Insert, I don't want to query first because the queries will get fat quick. I also think something might be wrong with the enum params because the ExecuteOptions want bitmasks instead of just a Long and I don't really know how to do that. From most of my research, I kept getting referred to the LockType and/or cursor not being right. For my environment; Windows 8.1 64bit, MS Office 2010 32bit(required). Does anyone see what is wrong here?
Sub ADO_Tester()
Dim strSQL, strFile, strConnection As String
Dim connDB As Object
'late bind to the ADODB library and get a connection object
Set connDB = CreateObject("ADODB.Connection")
'Connect to the DB
strFile = Application.ActiveWorkbook.Path & "\" & "PortfolioDB.accdb"
strConnection = "Provider = Microsoft.ACE.OLEDB.12.0; data source=" & strFile & ";"
connDB.Open strConnection
'insert statement for a test record
strSQL = "INSERT INTO underlying_symbol (symbol) VALUES ('xyz')"
'execute the
connDB.Execute strSQL, , 2, 1 + 128
'clear the object
connDB.Close
Set connDB = Nothing
End Sub
Edit:
Early binding:
connDB.Execute strSQL, , adCmdText + adExecuteNoRecords
Late Binding: How to enter the value for adExecuteNoRecords? On msdn it is 0x80 and another post says &H0001,either way it gives a syntax error. It says enter a bitmask for this enum value.
connDB.Execute strSQL, , 1 + 0x80
Edit: Now the correct way -
adExecuteNoRecords (the ADO enum value) = 0x80 (a binary value) = 128 (a decimal value)
connDB.Execute strSQL, , 1 + 128
Edit: Now the issue gets even deeper. When I execute the code in a test spreadsheet into a test database, it works. When I copy and paste into the actual project spreadsheet and point to actual project db, I get the error: operation must use an updateable query . . . again. Same db name, same dml, same table name. The only difference is the actual DB is a product of a split to separate it from the forms and code in Access. Could this have changed some setting to make it read only?
Edit: It just gets deeper and deeper. The issue causing it not to work in the project db is because I have some Excel Tables querying the db. I made these through the Excel UI, Ribbon -> External Data -> Access -> etc. . . It has now become obvious these are causing me to be unable to insert DML because they are probably set to read only. How can I change the tables connections permissions? Is there another way I could be making these tables so that I can provide the connection? How to get Tables to be friendly with DML in VBA?
This worked for me:
Option Explicit
Private Const acCmdText As Integer = 1
Sub ADO_Tester()
On Error GoTo ErrorHandler
Dim strSQL As String
Dim strFile As String
'Dim adoRecSet As Object
Dim connDB As Object
'late bind to the ADODB library and get a connection object
Set connDB = CreateObject("ADODB.Connection")
'Connect to the DB
strFile = getProjectFile("core", "PortfolioDB.accdb")
connDB.Open connectionString:="Provider = Microsoft.ACE.OLEDB.12.0; data source=" & strFile & ";"
'If State = 1, db connection is okay.
MsgBox "ADO Connection State is " & connDB.State & "."
'SQL to get the whole [underlying_symbol] table
'strSQL = "underlying_symbol" 'if options 2
'strSQL = "SELECT * FROM underlying_symbol" 'if options 1
strSQL = "INSERT INTO underlying_symbol (symbol) VALUES ('xyz')"
'late bind to adodb and get recordset object
'Set adoRecSet = CreateObject("ADODB.Recordset")
'&H0001 = bitmask for aCmdText
connDB.Execute strSQL, , acCmdText
'With adoRecSet
' .Open Source:=strSQL, _
' ActiveConnection:=connDB, _
' CursorType:=1, _
' LockType:=3, _
' Options:=&H1
'.AddNew
'.fields("symbol") = "XYZ"
'.Update
'End With
'------------------
'close the objects
'adoRecSet.Close
connDB.Close
'destroy the variables
'Set adoRecSet = Nothing
Set connDB = Nothing
ExitMe:
Exit Sub
ErrorHandler:
MsgBox Err.Number & ": " & Err.Description
GoTo ExitMe
End Sub
Added some error handling, a constant that defines acCmdText (Why just not add a reference to ADO library? Up to you, though.), and a message box to check the connection state to the database, as I can't test your getProjectFile function. Late binding doesn't seem to be the issue here, I think the key line is:
connDB.Execute strSQL, , 2, &H1
Can really say what's going on here as I've never done it like this (code doesn't even compile), but changing it to
connDB.Execute strSQL, , acCmdText
worked for me.

EXCEL ADODB Query on local worksheet not Including newly inserted records

I am using ADODB to query data form a worksheet in the Active workbook. The data resides on it's own sheet, and has column headers. I've defined the table as an excel ListObject - excel's automatic table formatting construct.
I open the connection like this:
Set cn = CreateObject("ADODB.Connection")
Set rs = CreateObject("ADODB.Recordset")
strCon = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & ThisWorkbook.Path & "\" & _
ThisWorkbook.Name & ";Extended Properties=""Excel 8.0;HDR=Yes;IMEX=1"";"
cn.Open strCon
Then I can fetch a recordset using a simple SQL statement:
strSQL = "SELECT * from [sheet1$]
rs.Open strSQL, cn, 0, 1 'cursortype = adOpenForwardOnly, locktype = adOpenReadonly
This all works fine... until I insert a new row in the table on sheet1. The new row is not included in subsequent queries, even if I close, set to nothing, and re-open both the connection and recordset variables in my code.
If I save and close the workbook, and then re-open it, the new records ARE included in the query, which leads me to believe this might be a caching issue. I've searched for ADODB Cache Flush etc, but most results appear to be related to PHP or Access. I've also tried a variety of other options for Cursor Type and Lock Type, with no difference.
Can anyone suggest how I can ensure that each time I run my query I get all the rows, even after I insert new rows in the table?
Figured out a solution:
Since I'm using Excel 2010, I discovered that I can use a newer version of ADODB.
So, instead of defining my connection string like this:
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source="...
I changed it to this:
"Provider=Microsoft.ACE.OLEDB.12.0;Data Source="...
and the problem is solved. New inserts and edits are now showing up immediately after I make them. This also removes the issue of the known memory leak in OLEDB.4.0, so that's a bonus.

Validate data before uploading through SSIS

I have a SSIS package to upload data from Excel file into an Sql Server 2005 table.
The excel file will have varied lines of data ranging from 20k - 30k lines.
The upload works fine, when all the data are correct. But obviously fails when there is a small problem even in a single row. Examples like mandatory values presented null, inconvertable values (data type mismatch) etc.
I want to validate the excel file before the upload and want to tell the user which row and column has got the error...
Any idea as to how to accomplish this, without consuming much time and resources.
Thanks
It might be easiest to load into a temporary table that does not have any mandatory values etc and check that before appending it to the main table.
EDIT re comment
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
''This is not necessarily the best way to get the workbook name
''that you need
strFile = Workbooks(1).FullName
''Note that if HDR=No, F1,F2 etc are used for column names,
''if HDR=Yes, the names in the first row of the range
''can be used.
''This is the Jet 4 connection string, you can get more
''here : http://www.connectionstrings.com/excel
strCon = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & strFile _
& ";Extended Properties=""Excel 8.0;HDR=Yes;IMEX=1"";"
Set cn = CreateObject("ADODB.Connection")
Set rs = CreateObject("ADODB.Recordset")
cn.Open strCon
''Note that HDR=Yes
''Pick one:
strSQL = "SELECT Frst, Secnd FROM TheRange WHERE SomeField Is Null" ''Named range
strSQL = "SELECT Frst, Secnd FROM [Sheet1$C3:C67] WHERE Val(Secnd)=0" ''Range
strSQL = "SELECT Frst, Secnd FROM [Sheet1$] WHERE First<Date()" ''Sheet
rs.Open strSQL, cn
Sheets("Sheet2").Cells(2, 1).CopyFromRecordset rs
I have recently been working on a number of similar packages in SSIS and the only way that I have been able to get around this is to have a holding table similar Remou's suggestion.
This table is extremely generic, where all fields are NULLable and VARCHAR(255). I then have a validation Stored Procedure that checks things such as typing, the existance of data etc before I move the data into a "live" situation. Although it may not be the most elegant of solutions, it gives you alot of control of the way you check the data and also means that you shouldn't have to worry about converting the file(s) to .CSV first.