In my Excel VBA code, I open a connection with other workbook.
With CreateObject("ADODB.Connection")
.CommandTimeout = 500
.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" _
& path & ";" & "Extended Properties=""Excel 12.0;HDR=NO;Readonly=true"";"
.Open
I want to do this kind of line :
ThisWorkbook.Worksheets("Test").Range("H306:307").CopyFromRecordset .Execute("select * from [values$S8:S8]")
But, it is possible that the sheet "values" doesn't exist, it is why I want to do this line only if there are no erros or if "values" exist, but I don't know how do that.
If your idea is to check whether a worksheet exists, then do it. And forget about the SQL, it is non-relevant:
Public Function worksheetExists(wb As Workbook, sh As Worksheet) As Boolean
worksheetExists = IsError(wb.sh.Range("A1"))
End Function
And if you want to put the openning of the file in the function, then:
Public Function worksheetExists(path As String, sh As Worksheet) As Boolean
On Error GoTo worksheetExists_Error
Dim wb As Workbook
Set wb = Workbooks.Open(path)
worksheetExists = IsError(wb.sh.Range("A1"))
wb.Close False
On Error GoTo 0
Exit Function
worksheetExists_Error:
MsgBox "Error " & Err.Number & " (" & Err.Description & ") "
End Function
Another option is to use On Error Resume Next really carefully, because it would ignore any error. However, you can do it on one line and put On Error GoTo 0, which stops the action. At the end, before assigning values to the new worksheet, check whether rs is not Nothing:
Public Sub TestMe()
Dim path As String: path = "C:\Source.xlsx"
Dim rs As Object
With CreateObject("ADODB.Connection")
.CommandTimeout = 500
.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" _
& path & ";" & _
"Extended Properties=""Excel 12.0;HDR=NO;Readonly=true"";"
.Open
On Error Resume Next
Set rs = .Execute("SELECT * FROM [Sheet12$A1:B4]")
On Error GoTo 0
End With
If Not rs Is Nothing Then
With ThisWorkbook.Worksheets(1).Range("A1")
.CopyFromRecordset rs
End With
End If
End Sub
Related
I use below code to copy data from closed workbook ("Sheet1") using ADO to read and write data in Excel workbooks .
the data copied successfully as my specified requirements except Last Header cell.
I tried to change HDR=NO to HDR=Yes in ADO connection , But the same problem.
As always: great thanks for your help.
Public Sub GetData(SourceFile As Variant, SourceSheet As String, _
SourceRange As String, TargetRange As Range, Header As Boolean, UseHeaderRow As Boolean)
Dim rsCon As Object, rsData As Object
Dim szConnect As String, szSQL As String
Dim lCount As Long
szConnect = "Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=" & SourceFile & ";" & _
"Extended Properties=""Excel 12.0;HDR=NO"";"
If SourceSheet = "" Then 'Workbook level name
szSQL = "SELECT * FROM " & SourceRange$ & ";"
Else
' worksheet level name or range
szSQL = "SELECT * FROM [" & SourceSheet$ & "$" & SourceRange$ & "];"
End If
On Error GoTo SomethingWrong
Set rsCon = CreateObject("ADODB.Connection")
Set rsData = CreateObject("ADODB.Recordset")
rsCon.Open szConnect
rsData.Open szSQL, rsCon, 0, 1, 1
If Not rsData.EOF Then ' Check to make sure we received data and copy the data
If Header = False Then
TargetRange.Cells(1, 1).CopyFromRecordset rsData
Else
End If
Else: MsgBox "No records returned from : " & SourceFile, vbCritical
End If
rsData.Close ' Clean up our Recordset object.
Set rsData = Nothing
rsCon.Close
Set rsCon = Nothing
Exit Sub
SomethingWrong:
MsgBox "The file name, Sheet name or Range is invalid of : " & SourceFile, _
vbExclamation, "Error"
On Error GoTo 0
End Sub
Sub GetData_Example4() 'Select one file with GetOpenFilenamewhere
Dim SaveDriveDir As String, MyPath As String
Dim FName As Variant
SaveDriveDir = CurDir
MyPath = Application.DefaultFilePath
ChDrive MyPath
ChDir MyPath
FName = Application.GetOpenFilename(filefilter:="Excel Files, *.xl*")
If FName = False Then
'do nothing
Else
GetData FName, "Sheet1", "A1:D5", Sheets("Sheet1").Range("A1"), False, False
End If
ChDrive SaveDriveDir
ChDir SaveDriveDir
End Sub
That header is likely missing because ADO has decided that column is numeric and so the header gets auto-converted to null because it's not numeric. You're telling ADO that row1 is part of the data when you use HDR=No.
You can try moving it's position in the source data and it should still show that behavior.
You really don't want ADO to treat your headers like they're part of your dataset, so you need to either skip them in your SQL (by excluding the header row from the range you supply) or use HDR=Yes in the connection.
If using HDR=Yes then you'll need to add some code to your sub to read each field name in the recordset and populate a header row on the results sheet before using CopyFromRecordSet.
I have an Access 365 database that has Invoice Numbers, Due Dates, and Amounts Due. I'm trying to create an Excel UDF, whereby I input the Due Date and Invoice Number, and the function queries the database and returns the Amount Due.
The formula result is #Value and there's no compiler error, though there appears to be an error when it attempts to open the record set (I set up a error message box for this action). Perhaps there's an issue with my SQL? I'd appreciate any assistance with this matter.
I've found several discussions of similar topic, but I've been unable to get this code to work. I'd appreciate any assistance with this matter.
https://www.mrexcel.com/board/threads/need-help-creating-user-defined-functions-in-excel-to-query-from-a-database.943894/
Here's the code:
Function CLLData(inpDate As Long, inpInvoiceNum As String)
Dim conn As Object
Dim rs As Object
Dim AccessFilePath As String
Dim SqlQuery As String
Dim sConnect As String
'Disable screen flickering.
Application.ScreenUpdating = False
'Specify the file path of the accdb file.
AccessFilePath = ThisWorkbook.Path & "\" & "CRDD.accdb"
'Create the connection string.
sConnect = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & AccessFilePath
On Error Resume Next
'Create the Connection object.
Set conn = CreateObject("ADODB.Connection")
'Check if the object was created.
If Err.Number <> 0 Then
MsgBox "Connection was not created!", vbCritical, "Connection Error"
'Exit Sub
End If
On Error GoTo 0
On Error Resume Next
'Open the connection.
conn.Open sConnect
'Check if the object was created.
If Err.Number <> 0 Then
MsgBox "Connection was not opened!", vbCritical, "Connection Open Error"
'Exit Sub
End If
On Error GoTo 0
'SQL statement to retrieve the data from the table.
SqlQuery = "SELECT [Value] FROM tblRawCallData WHERE (([DueDate] = '" & inpDate & "') AND ([Invoice] = '" & inpInvoiceNum & "'));"
On Error Resume Next
'Create the ADODB recordset object
Set rs = CreateObject("ADODB.Recordset")
'Check if the object was created.
If Err.Number <> 0 Then
Set rs = Nothing
Set conn = Nothing
MsgBox "Recordset was not created!", vbCritical, "Recordset Error"
'Exit Sub
End If
On Error GoTo 0
On Error Resume Next
'Open the recordset.
rs.Open SqlQuery, conn
'Check if the recordset was opened.
If Err.Number <> 0 Then
Set rs = Nothing
Set conn = Nothing
MsgBox "Recordset was not opened!", vbCritical, "Recordset open error"
'Exit Sub
End If
On Error GoTo 0
' Check there is data.
If Not rs.EOF Then
' Transfer result.
CLLData = rs!Value
MsgBox "Records: ", vbCritical, "Records"
' Close the recordset
Else
'Not found; return #N/A! error
CLLData = CVErr(xlErrNA)
MsgBox "No records in recordset!", vbCritical, "No Records"
End If
rs.Close
' Clean up
If CBool(conn.State And adStateOpen) Then conn.Close
Set conn = Nothing
Set rs = Nothing
'Enable the screen.
Application.ScreenUpdating = True
End Function
You need two or three corrections, as date values always should be handled as DateTime, and your invoice number most likely is numeric:
Function CLLData(inpDate As Date, inpInvoiceNum As String)
' <snip>
'SQL statement to retrieve the data from the table.
SqlQuery = "SELECT [Value] FROM tblRawCallData WHERE (([DueDate] = #" & Format(inpDate, "yyyy\/mm\/dd") & "#) AND ([Invoice] = " & inpInvoiceNum & "));"
Edit for numeric "date" and alpha-numeric invoice:
SqlQuery = "SELECT [Value] FROM tblRawCallData WHERE (([DueDate] = #" & Format(inpDate, "####\/##\/##") & "#) AND ([Invoice] = '" & inpInvoiceNum & "'));"
Seems like your function could be significantly less complex.
Comment out the error handler until you get it working when called from a Sub.
Function CLLData(inpDate As Long, inpInvoiceNum As String)
Dim conn As Object
Dim rs As Object
Dim AccessFilePath As String
Dim SqlQuery As String
Dim sConnect As String
AccessFilePath = ThisWorkbook.path & "\" & "CRDD.accdb"
sConnect = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & AccessFilePath
On Error GoTo haveError
Set conn = CreateObject("ADODB.Connection")
conn.Open sConnect
SqlQuery = "SELECT [Value] FROM tblRawCallData WHERE [DueDate] = " & inpDate & _
" AND [Invoice] = '" & inpInvoiceNum & "'"
Set rs = CreateObject("ADODB.Recordset")
rs.Open SqlQuery, conn
If Not rs.EOF Then
CLLData = rs.Fields("Value").Value
Else
CLLData = CVErr(xlErrNA)
End If
rs.Close
Exit Function
haveError:
CLLData = "Error:" & Err.Description
End Function
I am getting data from AS400 via Excel add-in and I'm trying to find an automated to do this because I have to do this many times with various source files and it's annoying to constantly to having to log in whenever I use a new source file.
For instance, for the source file "bond.tto" I would do this to download it:
In Excel,
go to "Add-Ins" --> "Transfer Data from iSeries." A "Transfer Request" window pops up and from there I choose "create a new file"... the path and the file name is c:\bond.tto.
"starting cell position" I chose column A and row 1 and click "include column headings." I press "OK."
then I enter my credentials which let's say my user name is "abc" and pw is "abc." The server...let's call it "BLUE.TOR.MCFLY.COM."
Could somebody suggest code to automate this? Please and thank you.
The macro recorder doesn't give me any lines of code to work with.
No errors as the macro recorder doesn't work.
As a side note, you can also use open JT400 in java to use DB2 SQL to query your tables.
Using VBA you can also use queries as follows:
The code I am using here is primarily from VBA New Database Connection.
However, of importance to you is your database connection string.
This is using the Client Access ODBC driver to connect to an IBM i DB2 database on a server with the name POWER7 and other options. The "translate" option I believe takes it from the 65535 CSSID and converts it to something nice from EBDIC.
Sub DbConnection()
Dim cn As Object ' ADODB.Connection
Set cn = CreateObject("ADODB.Connection") ' New ADODB.Connection
Dim rs As Object ' ADODB.Recordset
Dim strConn As String
strConn = "DRIVER={Client Access ODBC Driver (32-bit)};" & _
"Database=<myDataBase>;" & _
"Hostname=<POWER7>;" & _
"Port=1234;" & _
"Protocol=TCPIP;" & _
"Uid=<USERID>;" & _
"Pwd=<PASSWORD>;" & _
"SYSTEM=<POWER7>;" & _
"DBQ=QGPL <YOUR BASE LIBRARY> <ANOTHER>;" & _
"DFTPKGLIB=QGPL;" & _
"LANGUAGEID=ENU;" & _
"PKG=QGPL/DEFAULT(IBM),2,0,1,0,512;QRYSTGLMT=-1;" & _
"TRANSLATE=1;" & _
"CONNTYPE=2;" & _
"REGIONAL=NO;"
cn.Open strConn
Dim queryArr, i
queryArr = Array("SELECT * FROM <LIBRARY>.<TABLE>")
For i = LBound(queryArr) To UBound(queryArr)
ExecuteQuery queryArr(i), cn, rs
Next i
cn.Close
Set cn = Nothing
End Sub
Private Sub ExecuteQuery(query As Variant, ByRef cn As Object, ByRef rs As Object)
Set rs = CreateObject("ADODB.Recordset") ' New ADODB.Recordset
With rs
.ActiveConnection = cn
.Open CStr(query)
Sheets("Sheet1").Range("A1").CopyFromRecordset rs
.Close
End With
Set rs = Nothing
End Sub
test this:
Option Explicit
Option Base 1
Sub Firmennamen()
On Error GoTo ERRORHANDLER
Dim sSQLFirmen As String
Dim objListObj As ListObject
Dim objListCols As ListColumns
Set WB = ThisWorkbook
Set ws_Einstellungen = WB.Worksheets("Einstellung") ' tab name in excel
Set objListObj = ws_Einstellungen.ListObjects("FirmenNamen") ' table name in excel
Set objListCols = objListObj.ListColumns
ws_Einstellungen.Range("FirmenNamen").ClearContents ' clear table
sconnect = "PROVIDER=IBMDA400;Data Source=server_name;USER ID=username;PASSWORD=Password;"
conn.ConnectionTimeout = 30
conn.Open sconnect
Set mrs.ActiveConnection = conn
sSQLFirmen = " SELECT t.col1 AS Nr, t.col2 AS Firma " & _
" From server_name.schema_name.table_name t " & _
" WHERE t.col2='010' " & _
" ORDER BY t.col1 "
mrs.Open sSQLFirmen, conn
For i = 0 To mrs.fields.count - 1
objListCols(i + 1).Name = mrs.fields(i).Name
Next i
ws_Einstellungen.Range("FirmenNamen").CopyFromRecordset mrs
mrs.Close
conn.Close
Set mrs = Nothing
Set conn = Nothing
Exit Sub
'get out before the Error Handler kicks in
'//////////////////////////////////////////////////////////
ERRORHANDLER:
Call ERROR
End
End Sub
Private Sub Workbook_Open()
Call Firmennamen ' when excel open --> query update
End Sub
Sub ERROR()
Select Case Err.Number
Case -2147217843
msg = "Sie müssen Ihre User ID und Password eintragen: " & Err.Number _
& " oder Ihre user ID und Password sind nicht correct."
MsgBox msg, vbOKOnly
Case 13
msg = "You have text data in a numeric field (" & BadField & "). Fix and re-Upload"
MsgBox msg, vbOKOnly
Case 1004
msg = "Firma fehlt oder ist ungültig !"
MsgBox msg, vbOKOnly
Case Else
msg = "DIe Fehler ist: " & Err.Number & " / " & Err.Description & vbCrLf & vbCrLf & " Bitte sich bei IT melden (mit Screenshot dieser Meldung) !! :( "
MsgBox msg, vbOKOnly
End Select
Err.Clear
'Set GetConnection = Nothing
End Sub
I already have the query that retrieves me the data in a correct way, this is my code.
Sub Main()
Dim sDBPath As String
sDBPath = "C:\Users\ges\Documents\ExploWR.mdb"
Call Query_Access_to_excel(sDBPath, "Explo1", "SELECT eipl.MOD_CODE, eipl.BOM_KEY, eipl.DIF, eipl.PART_NO, eipl.PART_DESC, eipl.QTY_PER_CAR, eipl.INTERIOR_COLOUR, eipl.EXTERIOR_COLOUR, eipl.SOURCE_CODE, eipl.SHOP_CLASS," & _
" eipl.PART_CLASS, eipl.PROCESS_CODE, eipl.OPERATION_NO, eipl.DESIGN_NOTE_NO, eipl.WIP, eipl.PART_ID_CODE, eipl.ADOPT_DATE_Y2K,eipl.ABOLISH_DATE_Y2K, ipo_Modelos.EIM, ipo_Modelos.DEST, ipo_Modelos.MY " & _
" FROM eipl, explo, ipo_Modelos" & _
" WHERE explo.MOD_CODE = eipl.MOD_CODE And explo.MY = ipo_Modelos.MY" & _
" And explo.PLANT = ipo_Modelos.PLANT And eipl.ADOPT_DATE_Y2K <= explo.ADOP " & _
" And explo.DEST = ipo_Modelos.DEST And explo.EIM = ipo_Modelos.EIM")
End Sub
Sub Query_Access_to_excel(sBd As String, sHoja As String, sSQL As String)
On Error GoTo error_handler
Dim rs As ADODB.Recordset
Dim conn As String
Dim Range_Destino As Range
Set Range_Destino = ActiveWorkbook.Sheets(sHoja).Cells(6, 1)
conn = "Provider=Microsoft.ACE.OLEDB.12.0;" & "Data Source= " & sBd & ";"
Set rs = New ADODB.Recordset
Call rs.Open(sSQL, conn, adOpenForwardOnly, adLockReadOnly)
If Not rs.EOF Then
Range_Destino.Offset(1, 0).CopyFromRecordset rs
DoEvents
MsgBox "Import Complete", vbInformation
Else
MsgBox "No registers to import", vbInformation
End If
If Not rs Is Nothing Then
If rs.State = adStateOpen Then
rs.Close
End If
Set rs = Nothing
End If
If Not Range_Destino Is Nothing Then
Set Range_Destino = Nothing
End If
Exit Sub
error_handler:
MsgBox Err.Description, vbCritical
End Sub
What I want to do is to correctly place the data in the cells, something like this.
And what I have is something like this. I want to place the data in the correct cells, I'm talking about the last 3 fields to be properly placed in the columns like the first image. I have no idea how to do this without affecting my query.
So as far as exporting the data into excel you have several options:
SQL do command:
https://msdn.microsoft.com/en-us/library/office/ff844793.aspx
Same command but in VBA:
Using Excel VBA to export data to MS Access table
You could iterate through the table and create an array then print that array into a spreadsheet
Once you have the data in excel you're just looking at formatting -- adding some filters, changing the text align, ect.. you can use the "Record Macro" function to perform those tasks and clean the code.
So I guess for clarification - what do you mean 'affecting your query?'
I have a class ADOConnector for creating an ADODB connection to a workbook and querying the workbook:
Private objconnection As New ADODB.Connection
Sub connect(workbookPath As String)
On Error GoTo errHandler
objconnection.CommandTimeout = 99999999
objconnection.Open "Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=" & workbookPath & ";" & _
"Extended Properties=""Excel 12.0 Xml;HDR=YES;IMEX=1"";"
Exit Sub
errHandler:
Err.Raise Err.Number, "ADOConnector.connect", Err.Description & _
" (" & workbookPath & ")"
End Sub
Function WorksheetQuery(selectSQL As String) As ADODB.Recordset
Dim objrecordset As New ADODB.Recordset
Const adOpenStatic = 3
Const adLockOptimistic = 3
Const adCmdText = &H1
objrecordset.Open selectSQL, _
objconnection, adOpenStatic, adLockOptimistic, adCmdText
If objrecordset.EOF Then
Set WorksheetQuery = Nothing
Exit Function
End If
Set WorksheetQuery = objrecordset
Exit Function
errHandler:
Err.Raise Err.Number, "ADOConnector.WorksheetQuery", Err.Description
Set WorksheetQuery = Nothing
End Function
I have a test method for WorksheetQuery:
Sub testADOcon()
Dim ac As New ADOConnector
Dim bkPath as string
bkPath = "U:\testFolder\testWorkbook.xlsx"
ac.connect bkPath
Dim rs As ADODB.Recordset
Set rs = ac.WorksheetQuery("select distinct * from [report$]")
End Sub
This method gives strangely inconsistent results:
If the workbook at bkPath is open, it fails with this error: The connection for viewing your linked Microsoft Excel worksheet was lost.
If the workbook at bkPath is closed, it executes successfully.
If bkPath is set as bkPath = ThisWorkbook.FullName, it executes successfully.
If the SQL is changed to "select * from [report$]", it executes successfully regardless of whether the workbook is open or closed.
How can I use distinct on another open workbook?