I am creating an ADODB connection to a Sybase database, executing an SQL statement into a recordset, and then using the CopyFromRecordset method to paste the contents of the recordset to a range. This has been working fine but I recently moved PC's at work and now one of the columns is returning nothing.
When I run the same SQL in SQuirreL the column is not blank.
If I pause the VBA and try to look at one of the values in the column / field in question (ie ?rst.fields(1).value in the immediate Window) I get the following error message:
Run-time error '-2147467259 (80004005)': Unspecified error.
In the Squirrel results Metadata tab the column in question is described as:
ColumnIndex 2
getColumnName CommentText
getColumnTypeName text
getPrecision 2147483647
getScale 0
isNullable 0
getTableName xxxxxxx
getSchemaName
getCatalogName
getColumnClassName java.sql.Clob
getColumnDisplaySize 2147483647
getColumnLabel CommentText
getColumnType 2005
isAutoIncrement FALSE
isCaseSensitive FALSE
isCurrency FALSE
isDefinitelyWritable FALSE
isReadOnly FALSE
isSearchable FALSE
isSigned FALSE
isWritable TRUE
The code in question is below, but, as stated the code does not seem to be the problem as it has worked previously - any ideas?
Sub ImportComments()
Dim wsData As Worksheet
Dim rng As Range
Dim cn As ADODB.Connection
Dim rst As ADODB.Recordset
Dim x As Long
Dim rngSQL As Range
Dim cell As Range
Dim sSQL As String
Dim sProvider As String
Dim sDS As String
Dim sDataSource As String
Dim sUser As String
Dim sCatalog As String
Dim sPassword As String
Dim rngDS As Range
Dim rngThisDS As Range
Dim sConnect As String
Dim sInstance As String
Dim fSuccess As Boolean
Dim sError As String
On Error GoTo ProcExit
'delete previous comments if they exist
If SheetExists("Comments_Data_Import", ThisWorkbook) = True Then
Application.DisplayAlerts = False
ThisWorkbook.Sheets("Comments_Data_Import").Delete
Application.DisplayAlerts = True
End If
'create comments sheet
Set wsData = ThisWorkbook.Worksheets.Add(After:=ThisWorkbook.Sheets("EWI_Data_Import"))
wsData.Name = "Comments_Data_Import"
'build sql string
Set rngSQL = Range(ThisWorkbook.Sheets("SQL").Range("A2"), _
ThisWorkbook.Sheets("SQL").Range("A2").End(xlDown))
For Each cell In rngSQL
sSQL = sSQL & cell.Value & " "
Next cell
'define login components
Set rngDS = ThisWorkbook.Worksheets("Login").Range("rngInstance").CurrentRegion
Set rngDS = rngDS.Offset(1, 0).Resize(rngDS.Rows.Count - 1)
sProvider = "Provider=ASEOLEDB.1;"
sUser = "User ID=" & ThisWorkbook.Worksheets("Login").Range("rngUsername").Value & ";"
sPassword = "Password=" & ThisWorkbook.Worksheets("Login").Range("rngPassword").Value
'try to log in to each instance exiting when succesful
Set cn = New ADODB.Connection
cn.CommandTimeout = 600
'turn off error hadling to allow for connection errors On Error Resume Next
For Each rngThisDS In rngDS.Rows
'complete connect string
Err = 0
sInstance = rngThisDS.Cells(1, 1)
sDS = "Data Source=" & rngThisDS.Cells(1, 2) & ";"
sCatalog = "Initial Catalog=" & rngThisDS.Cells(1, 3) & ";"
sConnect = sProvider & sDS & sUser & sCatalog & sPassword
'attempt to open
cn.Open sConnect
'If successful Then
If Err = 0 Then
'flag success
fSuccess = True
'execute SQL
On Error GoTo ProcError
Set rst = cn.Execute(sSQL)
'copy data into comments sheet
wsData.Range("A2").CopyFromRecordset rst
'Put in the headers
Set rng = wsData.Range("A1")
For x = 1 To rst.Fields.Count
rng.Offset(0, x - 1).Value = rst.Fields(x - 1).Name
Next x
FormatComments
Exit For
End If
Next rngThisDS
If fSuccess = False Then
MsgBox ("Unable to connect to Insight")
Else
MsgBox "Connected to and exported data from " & sInstance
End If
ProcExit:
Set wsData = Nothing
Set rng = Nothing
Set cn = Nothing
Set rst = Nothing
Set rngSQL = Nothing
Set cell = Nothing
Set rngDS = Nothing
Set rngThisDS = Nothing
Exit Sub
ProcError:
MsgBox "Error: " & Err.Description
Resume ProcExit
End Sub
According to the CopyFromRecordset() MSDN:
When this method copies the recordset to the worksheet, the results
will be truncated if you do not specify a range that is large enough
to hold the contents of the recordset.
Consider specifying the range with MoveFirst command reset:
' Copy data into comments sheet
rst.MoveLast
rst.MoveFirst
wsData.Range("A2:Z500").CopyFromRecordset rst
Or entire worksheet (starting at A1, of course inserting row for column headers)
wsData.Cells.CopyFromRecordset rst
But even then, CopyFromRecordset() is sensitive to data and cursory types even memory (since you pull all data and dump at once), so consider altogether replacing the method and iterate through records for the rows. Even other languages (PHP, Python, Java, etc.) run queries this way, opening cursor and iterating through resultset.
' Put in the headers
Set rng = wsData.Range("A1")
For x = 1 To rst.Fields.Count
rng.Offset(0, x - 1).Value = rst.Fields(x - 1).Name
Next x
' Put in rows
Dim col As Integer, row As Integer
rst.MoveLast
rst.MoveFirst
Set rng = wsData.Range("A2")
row = 0
Do While Not rst.EOF
For col = 0 To rst.Fields.Count - 1
rng.Offset(row, col).Value = rst(col)
Next col
row = row + 1
rst.MoveNext
Loop
Related
I have a command button in excel to insert the records to access table. Here's my vba code.
Option Explicit
Sub AddRecordsIntoAccessTable()
Dim accessFile As String
Dim accessTable As String
Dim sht As Worksheet
Dim lastRow As Long
Dim lastColumn As Integer
Dim con As Object
Dim rs As Object
Dim sql As String
Dim i As Long
Dim j As Integer
'Disable the screen flickering.
Application.ScreenUpdating = False
'Specify the file path of the accdb file. You can also use the full path of the file like this:
'AccessFile = "C:\Users\Christos\Desktop\Sample.accdb"
accessFile = ThisWorkbook.Path & "\" & "Database daily activity - Beta 6.accdb"
'Ensure that the Access file exists.
If FileExists(accessFile) = False Then
MsgBox "The Access file doesn't exist!", vbCritical, "Invalid Access file path"
Exit Sub
End If
'Set the name of the table you want to add the data.
accessTable = "DAILY_ACTIVITY"
'Set the worksheet that contains the data.
On Error Resume Next
Set sht = ThisWorkbook.Sheets("Daily Activity")
If Err.Number <> 0 Then
MsgBox "The given worksheet does not exist!", vbExclamation, "Invalid Sheet Name"
Exit Sub
End If
Err.Clear
'Find the last row and last column in the given worksheet.
With sht
lastRow = .Cells(.Rows.Count, "B").End(xlUp).Row
lastColumn = .Cells(1, .Columns.Count).End(xlToLeft).Column
End With
'Check if there are data in the worksheet.
If lastRow < 2 Or lastColumn < 1 Then
MsgBox "There are no data in the given worksheet!", vbCritical, "Empty Data"
Exit Sub
End If
'Create the ADODB connection object.
Set con = CreateObject("ADODB.connection")
'Check if the object was created.
If Err.Number <> 0 Then
MsgBox "The connection was not created!", vbCritical, "Connection Error"
Exit Sub
End If
Err.Clear
'Open the connection.
con.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & accessFile
'Create the SQL statement to retrieve the table data (the entire table).
sql = "SELECT * FROM " & accessTable
'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 con = Nothing
MsgBox "The recordset was not created!", vbCritical, "Recordset Error"
Exit Sub
End If
Err.Clear
'Set the necessary recordset properties.
rs.CursorType = 1 'adOpenKeyset on early binding
rs.LockType = 3 'adLockOptimistic on early binding
'Open the recordset.
rs.Open sql, con
'Add the records from Excel to Access by looping through the rows and columns of the given worksheet.
'Here the headers are in the row 1 and they are identical to the Access table headers.
'This is the reason why, for example, there are no spaces in the headers of the sample worksheet.
For i = 2 To lastRow
rs.AddNew
For j = 1 To lastColumn
'This is how it will look like the first time (i = 2, j = 1):
'rs("FirstName") = "Bob"
rs(sht.Cells(1, j).Value) = sht.Cells(i, j).Value
Next j
rs.Update
Next i
'Close the recordet and the connection.
rs.Close
con.Close
'Release the objects.
Set rs = Nothing
Set con = Nothing
'Re-enable the screen.
Application.ScreenUpdating = True
'Inform the user that the macro was executed successfully.
MsgBox lastRow - 1 & " rows were successfully added into the '" & accessTable & "' table!", vbInformation, "Done"
End Sub
Function FileExists(FilePath As String) As Boolean
'--------------------------------------------------
'Checks if a file exists (using the Dir function).
'--------------------------------------------------
On Error Resume Next
If Len(FilePath) > 0 Then
If Not Dir(FilePath, vbDirectory) = vbNullString Then FileExists = True
End If
On Error GoTo 0
End Function
As an example, I create 2 records in excel. It says that those 2 rows had successfully added into my access table. Yet, the added rows are not found in the access table.
Is there something to do in how I linked the excel and access?
I have a command button in excel to insert the records to access table. Here's my vba code.
Option Explicit
Sub AddRecordsIntoAccessTable()
Dim accessFile As String
Dim accessTable As String
Dim sht As Worksheet
Dim lastRow As Long
Dim lastColumn As Integer
Dim con As Object
Dim rs As Object
Dim sql As String
Dim i As Long
Dim j As Integer
'Disable the screen flickering.
Application.ScreenUpdating = False
'Specify the file path of the accdb file. You can also use the full path of the file like this:
'AccessFile = "C:\Users\Christos\Desktop\Sample.accdb"
accessFile = ThisWorkbook.Path & "\" & "Database daily activity.accdb"
'Ensure that the Access file exists.
If FileExists(accessFile) = False Then
MsgBox "The Access file doesn't exist!", vbCritical, "Invalid Access file path"
Exit Sub
End If
'Set the name of the table you want to add the data.
accessTable = "DAILY_ACTIVITY"
'Set the worksheet that contains the data.
On Error Resume Next
Set sht = ThisWorkbook.Sheets("Daily Activity")
If Err.Number <> 0 Then
MsgBox "The given worksheet does not exist!", vbExclamation, "Invalid Sheet Name"
Exit Sub
End If
Err.Clear
'Find the last row and last column in the given worksheet.
With sht
lastRow = .Cells(.Rows.Count, "B").End(xlUp).Row
lastColumn = .Cells(1, .Columns.Count).End(xlToLeft).Column
End With
'Check if there are data in the worksheet.
If lastRow < 2 Or lastColumn < 1 Then
MsgBox "There are no data in the given worksheet!", vbCritical, "Empty Data"
Exit Sub
End If
'Create the ADODB connection object.
Set con = CreateObject("ADODB.connection")
'Check if the object was created.
If Err.Number <> 0 Then
MsgBox "The connection was not created!", vbCritical, "Connection Error"
Exit Sub
End If
Err.Clear
'Open the connection.
con.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & accessFile
'Create the SQL statement to retrieve the table data (the entire table).
sql = "SELECT * FROM " & accessTable
'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 con = Nothing
MsgBox "The recordset was not created!", vbCritical, "Recordset Error"
Exit Sub
End If
Err.Clear
'Set the necessary recordset properties.
rs.CursorType = 1 'adOpenKeyset on early binding
rs.LockType = 3 'adLockOptimistic on early binding
'Open the recordset.
rs.Open sql, con
'Add the records from Excel to Access by looping through the rows and columns of the given worksheet.
'Here the headers are in the row 1 and they are identical to the Access table headers.
'This is the reason why, for example, there are no spaces in the headers of the sample worksheet.
Application.ScreenUpdating = True
On Error GoTo 0
For i = 2 To lastRow
rs.AddNew
For j = 1 To lastColumn
'This is how it will look like the first time (i = 2, j = 1):
rs(sht.Cells(1, j).Value) = sht.Cells(i, j).Value
Next j
rs.Update
Next i
'Close the recordet and the connection.
rs.Close
con.Close
'Release the objects.
Set rs = Nothing
Set con = Nothing
'Re-enable the screen.
Application.ScreenUpdating = True
'Inform the user that the macro was executed successfully.
MsgBox lastRow - 1 & " rows were successfully added into the '" & accessTable & "' table!", vbInformation, "Done"
End Sub
Function FileExists(FilePath As String) As Boolean
'--------------------------------------------------
'Checks if a file exists (using the Dir function).
'--------------------------------------------------
On Error Resume Next
If Len(FilePath) > 0 Then
If Not Dir(FilePath, vbDirectory) = vbNullString Then FileExists = True
End If
On Error GoTo 0
End Function
This code can only add new records, and it will be error if there is duplicate.
How do I fix the code with the condition:
Update existing access table for the records that is duplicate.
Add the records that is non duplicate
Could do a Find on recordset to determine if data already exists. If it does, focus will be on that record, otherwise pointer will be at recordset EOF.
For i = 2 To lastRow
rs.Find "some field=" & cell reference, , , 1
If rs.EOF Then
rs.AddNew
Else
rs.Edit
End If
For j = 1 To lastColumn
'This is how it will look like the first time (i = 2, j = 1):
rs(sht.Cells(1, j).Value) = sht.Cells(i, j).Value
Next j
rs.Update
Next i
Here is what I am trying to do:
Pick up SQL script from a worksheet(script has comments and queries)
Assign it to a string variable with the value of range of cells(where the scripts are pasted) from the worksheet
Execute the script by passing the string variable to ADODB connection I made before as a recordset
Paste the results of the script executed in the Oracle Database in a new sheet
So far what I have achieved:
Database connection was successful
I am able to assign the range values to a variant but not a string (Error: Type Mismatch)
If I change the variable to a variant then I am not able to execute it as a recordset.
(Error: arguments are of the wrong type, are out of acceptable range or are in conflict with one another)
I know the approach I am using is not that easy therefore I need suggestions on how I may be able to achieve this.
Private Sub RunValidation_Click()
Dim ws As Worksheet
Dim sheet As Variant
Dim StrSQL As Variant
Dim sheetnumber As Integer
Dim irow As Integer
Dim rs As ADODB.Recordset
Dim elementcount As Integer
Call OptimizeCode_Begin
Call Start_DBConnect
irow = ScriptExecutor.Range("A" & Rows.count).End(xlUp).row
elementcount = irow - 13
StrSQL = ScriptExecutor.Range("A14: A" & irow).Value
Set rs = New ADODB.Recordset
rs.Open StrSQL, cn, adOpenDynamic, adLockReadOnly, adCmdText
If Not rs.EOF Then
rs.MoveFirst
End If
i = 1
sheetnumber = Application.Sheets.count - i
Set ws = Sheets.Add(After:=Sheets(Sheets.count))
ws.name = "Extracts-" & sheetnumber
Sheets("Extracts-" & sheetnumber).Range("A2").CopyFromRecordset rs
rs.Close
Set rs = Nothing
End Sub
Try joining each row in the range with CRLF to create a string. The array assigned from the range is a single column with many rows. The JOIN function needs a single row many columns array hence the transpose function.
Dim StrSQL As String, arLines As Variant
arLines = ScriptExecutor.Range("A14: A" & irow).Value
StrSQL = Join(Application.Transpose(arLines), vbCrLf)
If you have to ignore the --comments including those on the same line as a statement (and the blank lines) then building the string one line at a time is probably the simplest method.
Dim cell As Range, sLine As String, StrSQL As String
With ScriptExecutor.Range("A14: A" & irow)
For Each cell In .Cells
sLine = Trim(cell.Value)
' remove any comments --
i = InStr(1, sLine, "--", vbTextCompare)
If i > 0 Then
sLine = Left(sLine, i - 1)
End If
If len(sLine) = 0 Then
' skip blank lines
Else
If Len(StrSQL) > 0 Then sLine = vbCrLf & sLine
StrSQL = StrSQL & sLine
End If
Next
End With
Debug.Print StrSQL
With multiple queries in the same script you get multiple record sets so try using .nextRecordSet method.
Set ws = Sheets.Add(After:=Sheets(Sheets.Count))
ws.Name = "Extracts-" & sheetnumber
Set rs = oCon.Execute(sql)
iRow = 2
Do Until rs Is Nothing
With ws
.Range("A" & iRow).CopyFromRecordset rs
iRow = .Range("A" & Rows.Count).End(xlUp).Row + 2
End With
Set rs = rs.nextRecordSet
Loop
I am able to achieve the above question with a slightly different approach. The only precondition is that the user will have to remove the comments from the script.
The script looks something like this:
Sample Script.
and the code is as follows:
Private Sub RunValidation_Click()
Dim ws As Worksheet
Dim sheet As Variant
Dim sheetnumber As Integer
Dim irow As Integer
Dim rs As ADODB.Recordset
Dim fld As ADODB.field
Dim elementcount As Integer
Dim sqlscript As Variant
Dim StrSQL As String
Dim commands As Variant
Dim cmd() As Variant
Dim i As Integer
Dim j As Integer
Dim k As Integer
Dim results As String
Dim rownum As Integer
Dim col As Integer
On Error GoTo UserForm_Initialize_Err
If ScriptExecutor.TextUser = vbNullString Then
MsgBox ("Please enter User ID.")
GoTo UserForm_Initialize_Exit
End If
If ScriptExecutor.TextPwd = vbNullString Then
MsgBox ("Please enter Password.")
GoTo UserForm_Initialize_Exit
End If
Call OptimizeCode_Begin
Call Start_DBConnect
' Figuring out the last row with data
irow = ScriptExecutor.Range("A" & Rows.count).End(xlUp).row
elementcount = irow - 13
' Assigning range to a Variant variable
sqlscript = ScriptExecutor.Range("A14: A" & irow).Value
'Converting into String
StrSQL = Join(Application.Transpose(sqlscript), vbCrLf)
' Break the script into semi-colon
commands = Split(StrSQL, ";")
' Transfer values from array with empty values to array with empty values in the end
ReDim cmd(0 To 0)
j = 0
For i = LBound(commands) To UBound(commands)
If commands(i) <> "" Then
j = j + 1
cmd(UBound(cmd)) = commands(i)
ReDim Preserve cmd(0 To UBound(cmd) + 1)
End If
Next i
'remove that empty array field at the end
If UBound(cmd) > 0 Then
ReDim Preserve cmd(0 To UBound(cmd) - 1)
End If
Set rs = New ADODB.Recordset
' Open new sheet to paste results
k = 2
sheetnumber = Application.Sheets.count - k
Set ws = Sheets.Add(After:=Sheets(Sheets.count))
ws.name = "Extracts-" & sheetnumber
' Copy results in new sheet with field names
rownum = 1
For i = LBound(cmd) To UBound(cmd)
rs.Open cmd(i), cn, adOpenDynamic, adLockOptimistic, adCmdText
rs.MoveFirst
col = 1
For Each fld In rs.Fields
With ws.Cells(rownum, col)
.Value = fld.name: .HorizontalAlignment = xlLeft: .VerticalAlignment = xlTop: .EntireColumn.AutoFit: .Font.Bold = True: .Borders.Color = vbBlack
End With
col = col + 1
Next
rownum = ws.Range("A" & Rows.count).End(xlUp).row + 1
With ws.Range("A" & rownum)
.CopyFromRecordset rs:
.Borders.Color = vbBlack
rownum = ws.Range("A" & Rows.count).End(xlUp).row + 2
End With
rs.Close
Next
Set rs = Nothing
UserForm_Initialize_Exit:
On Error Resume Next
Call OptimizeCode_End
Call End_DBConnect
Exit Sub
UserForm_Initialize_Err:
MsgBox Err.number & vbCrLf & Err.Description, vbCritical, "Error!"
Resume UserForm_Initialize_Exit
End Sub
This seems to be working perfectly at the moment but I am testing it with different scenarios.
I am using an Access Db to export some information to an Excel Workbook. I am using an input form to add dates to the query that creates the sheet. If I create 1 sheet the export works. If I create more than one sheet once the query goes to the second sheet the focus stays on the excel spreadsheet. If you enter a date it goes on cell A1 of the spreadsheet instead of the input box. Any help is appreciated.
Public Function ExportSpreadSheet(path As String)
Dim xlPath As String, I As Integer
Dim DB As Database
Dim myrs As Recordset ' Create a recordset to hold the data
Dim strSQL As String
Dim myExcel As New Excel.Application ' Create Excel with Early binding
Dim wrkbk As Object
Dim wrksht As Object
Dim targetworkbook As Excel.Workbook
Dim FileRange, name As String
Dim extraChar, queryForTransfer, searchSheet As String
Dim objXL As Object
Dim objAC As Object
Dim x As Integer
Dim myFileName As String
Dim sheetDate As String
Dim sheetName As String
Dim amtofsheets As Long
Dim s As Long
Dim ctlCurrentControl As Control
Dim strAnswer As String
On Error GoTo Err_ExportSpreadSheet
DoCmd.SetWarnings False
xlPath = path
amtofsheets = InputBox("Enter amount of sheets", "Amount of Sheets")
Set DB = CurrentDb
Set objAC = CreateObject("Access.application", "")
For s = 1 To amtofsheets
strAnswer = Forms("Browse1").txtFileSelection
sheetDate = InputBox("Enter Trade Date of Entries ex 10/04/2017", "Trade Date")
If s = 1 Then Set objXL = CreateObject("Excel.application", "")
If s = 1 Then objXL.Visible = True
If s = 1 Then objXL.DisplayAlerts = True
If s = 1 Then Set targetworkbook = objXL.Workbooks.Add
'Add worksheet if need more than three worksheets
strSQL = "SELECT FXOpenDeals.city, FXOpenDeals.[As of Date], FXOpenDeals.[Cnt Pty name], FXOpenDeals.[deal number], FXOpenDeals.value, FXOpenDeals.ccy1, FXOpenDeals.[ccy1 amt], FXOpenDeals.ccy2, FXOpenDeals.[ccy2 amt], FXOpenDeals.[unrealized G/L_PV] " _
& " FROM [A1-Internal_Customers] INNER JOIN FXOpenDeals ON [A1-Internal_Customers].[counterparty number] = FXOpenDeals.[counterparty number] " _
& " WHERE FXOpenDeals.[trade] = #" & Format(sheetDate, "mm/dd/yyyy") & "#" _
& " ORDER BY FXOpenDeals.[Cnt Pty name];"
Set myrs = DB.OpenRecordset(strSQL)
If amtofsheets = 1 Or amtofsheets = 2 Then
For I = 1 To targetworkbook.Worksheets.Count
sheetName = "Sheet" & I
Select Case sheetName
Case "Sheet2"
targetworkbook.Sheets("Sheet2").Delete
Case "Sheet3"
targetworkbook.Sheets("Sheet3").Delete
End Select
Next I
End If
If s > 3 Then
With targetworkbook
.Sheets.Add After:=Sheets(Worksheets.Count)
ActiveSheet.name = "Sheet" & s
End With
End If
'Get spreadsheet headers
x = 0
For Each Field In myrs.Fields 'RS being my Recordset variable
targetworkbook.Worksheets("Sheet" & s).Range("A1").Offset(0, x).Value = Field.name
x = x + 1
Next Field
targetworkbook.Worksheets("Sheet" & s).Range("A2").CopyFromRecordset myrs
targetworkbook.Worksheets("Sheet" & s).Columns("A:K").AutoFit
'Name Worksheet
sheetName = Format(sheetDate, "mm-dd")
targetworkbook.Sheets("Sheet" & s).name = sheetName
Next s
DoCmd.SetWarnings False
myFileName = "Internal Customer FX Deals"
targetworkbook.SaveAs FileName:=xlPath & myFileName, FileFormat:=xlWorkbookNormal
targetworkbook.Close SaveChanges:=False
DoCmd.SetWarnings True
If Not objXL Is Nothing Then
objXL.Quit
objXL.DisplayAlerts = True
Set objXL = Nothing
Set myrs = Nothing
End If
MsgBox "Internal Customer FX Deals Data successfully Exported", vbOKOnly
Exit_ExportSpreadSheet:
Exit Function
Err_ExportSpreadSheet:
Err.Clear
Resume Exit_ExportSpreadSheet
End Function
Seems to me that you are doing a whole lot of work for nothing. There's not need to automate Excel unless you want to do some formatting. Simply export the query to Excel via TransferSpreadsheet. Instead of the input box, use a parameter in the query, or better yet, a small form with a textbox.
DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel12Xml, "yourQueryName", "FileName", True, "SheetName"
To import data into an excel file, QueryTable is quite convenient when the source is a .csv file, e.g. Import csv with quoted newline using QueryTables in Excel , however it does not work with excel sources.
Importing an excel file can be done by VBA, just wonder, if there's something convenient as QueryTable, to import from a excel file, s.t. only need to specify the source file name, sheet name or range name?
Oh, I see. Ok, well, you can use VBA to import data from Worksheets into your Workbook.
' Get customer workbook...
Dim customerBook As Workbook
Dim filter As String
Dim caption As String
Dim customerFilename As String
Dim customerWorkbook As Workbook
Dim targetWorkbook As Workbook
' make weak assumption that active workbook is the target
Set targetWorkbook = Application.ActiveWorkbook
' get the customer workbook
filter = "Text files (*.xlsx),*.xlsx"
caption = "Please Select an input file "
customerFilename = Application.GetOpenFilename(filter, , caption)
Set customerWorkbook = Application.Workbooks.Open(customerFilename)
' assume range is A1 - C10 in sheet1
' copy data from customer to target workbook
Dim targetSheet As Worksheet
Set targetSheet = targetWorkbook.Worksheets(1)
Dim sourceSheet As Worksheet
Set sourceSheet = customerWorkbook.Worksheets(1)
targetSheet.Range("A1", "C10").Value = sourceSheet.Range("A1", "C10").Value
' Close customer workbook
customerWorkbook.Close
Or, you can use the Query tool to import data from another Excel file.
http://dailydoseofexcel.com/archives/2004/12/13/parameters-in-excel-external-data-queries/
I'm guessing you are importing data from Access into excel. I don't think you specified your source, or I couldn't make it out. My eyes are not as good as they used to be...
Anyway, consider this option.
Sub ADOImportFromAccessTable(DBFullName As String, _
TableName As String, TargetRange As Range)
' Example: ADOImportFromAccessTable "C:\FolderName\DataBaseName.mdb", _
"TableName", Range("C1")
Dim cn As ADODB.Connection, rs As ADODB.Recordset, intColIndex As Integer
Set TargetRange = TargetRange.Cells(1, 1)
' open the database
Set cn = New ADODB.Connection
cn.Open "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" & _
DBFullName & ";"
Set rs = New ADODB.Recordset
With rs
' open the recordset
.Open TableName, cn, adOpenStatic, adLockOptimistic, adCmdTable
' all records
'.Open "SELECT * FROM " & TableName & _
" WHERE [FieldName] = 'MyCriteria'", cn, , , adCmdText
' filter records
RS2WS rs, TargetRange ' write data from the recordset to the worksheet
' ' optional approach for Excel 2000 or later (RS2WS is not necessary)
' For intColIndex = 0 To rs.Fields.Count - 1 ' the field names
' TargetRange.Offset(0, intColIndex).Value = rs.Fields(intColIndex).Name
' Next
' TargetRange.Offset(1, 0).CopyFromRecordset rs ' the recordset data
End With
rs.Close
Set rs = Nothing
cn.Close
Set cn = Nothing
End Sub
Or, this.
Sub RS2WS(rs As ADODB.Recordset, TargetCell As Range)
Dim f As Integer, r As Long, c As Long
If rs Is Nothing Then Exit Sub
If rs.State <> adStateOpen Then Exit Sub
If TargetCell Is Nothing Then Exit Sub
With Application
.Calculation = xlCalculationManual
.ScreenUpdating = False
.StatusBar = "Writing data from recordset..."
End With
With TargetCell.Cells(1, 1)
r = .Row
c = .Column
End With
With TargetCell.Parent
.Range(.Cells(r, c), .Cells(.Rows.Count, c + rs.Fields.Count - 1)).Clear
' clear existing contents
' write column headers
For f = 0 To rs.Fields.Count - 1
On Error Resume Next
.Cells(r, c + f).Formula = rs.Fields(f).Name
On Error GoTo 0
Next f
' write records
On Error Resume Next
rs.MoveFirst
On Error GoTo 0
Do While Not rs.EOF
r = r + 1
For f = 0 To rs.Fields.Count - 1
On Error Resume Next
.Cells(r, c + f).Formula = rs.Fields(f).Value
On Error GoTo 0
Next f
rs.MoveNext
Loop
.Rows(TargetCell.Cells(1, 1).Row).Font.Bold = True
.Columns("A:IV").AutoFit
End With
With Application
.StatusBar = False
.Calculation = xlCalculationAutomatic
.ScreenUpdating = True
End With
End Sub