Importing from AS400 to CSV using Excel VBA - excel

I am trying to export data from an AS400 table/file directly to a CSV File using Excel VBA. So far I have the following but it writes the output to the CSV file line by line and the headers do not seem to be included in the output.
I can output the data to Excel and save it as a CSV, but as it exceeds 1 million rows I only end up with half of what is required.
How to bulk dump the data into CSV and include the headers?
Sub ExportCSV()
Set Conn = CreateObject("adodb.connection")
Set rcd = CreateObject("adodb.recordset")
Set outFile = CreateObject("Scripting.FileSystemObject").CreateTextFile("H:\myFile.csv")
cnnstr = "DRIVER={Client Access ODBC Driver (32-bit)};SYSTEM=TEST;USERID=123;PWD=123"
Conn.Open cnnstr
Set rcd.ActiveConnection = Conn
sqlstm = "SELECT TEST50,LTEST50 FROM TESTLIB.TEST Where TEST50 Is Not NULL And LTEST50 Is Not NULL Order By TEST50 ASC "
rcd.Open sqlstm
rcd.MoveFirst
Do
outFile.WriteLine rcd("TEST50") & "," & rcd("LTEST50")
rcd.MoveNext
Loop Until rcd.EOF
rcd.Close
con.Close
Set rcd = Nothing
Set Conn = Nothing
End Sub

Here is a brute force approach, I am certain there are more elegant ways to load large text files in to Excel, such as the one that Chip Pearson put together:
http://www.cpearson.com/excel/ImportBigFiles.aspx
Otherwise, brute force approach could get you started:
Sub ExportCSV()
Dim wb as Object 'Excel.Workbook
Dim ws as Object 'Excel.Worksheet
Dim r As Long 'row counter/iterator
Set Conn = CreateObject("adodb.connection")
Set rcd = CreateObject("adodb.recordset")
Set outFile = CreateObject("Scripting.FileSystemObject").CreateTextFile("H:\myFile.csv")
cnnstr = "DRIVER={Client Access ODBC Driver (32-bit)};SYSTEM=TEST;USERID=123;PWD=123"
Conn.Open cnnstr
Set rcd.ActiveConnection = Conn
sqlstm = "SELECT TEST50,LTEST50 FROM TESTLIB.TEST Where TEST50 Is Not NULL And LTEST50 Is Not NULL Order By TEST50 ASC "
rcd.Open sqlstm
rcd.MoveFirst
'Create a new/empty Excel file
Set wb = CreateExcelFile()
Set ws = wb.Worksheets(1)
r = 1
'write the headers
Call WriteData(ws, r, "TEST50,LTEST50")
'Write the data
Do
If Not r > ws.Rows.Count Then
Call WriteData(ws, r, rcd("TEST50") & "," & rcd("LTEST50"))
Else
'begin with r=1 on a new worksheet
Set ws = wb.Worksheets.Add(After:=wb.Worksheets.Count)
r = 1
Call WriteData(ws, r, "TEST50,LTEST50")
End If
rcd.MoveNext
Loop Until rcd.EOF
End Sub
Sub WriteData(ws as Object, r as Long, strData as String)
With ws.Range("A" & r & ":B" & r)
.Value = Split(strData, ",")
End With
End Sub
Function CreateExcelFile() As Object
Dim xlApp as Object
Dim ret as Object
On Error Resume Next
Set xlApp = GetObject(, "Excel.Application")
If Err.Number <> 0 Then Set xlApp = CreateObject("Excel.Application")
On Error GoTo 0
Set ret = xlApp.Workbooks.Add
Do Until ret.Worksheets.Count = 1
ret.Worksheets(ret.Worksheets.Count).Delete
Loop
Set CreateExcelFile = ret
End Function

Related

Importing data from Access to Excel using Access VBA

I'd like to ask you for the help with the Access VBA code, that would import all the data from 1 specified query table from the Access database (currently open database) to MS Excel (the file, that could be selected by the user).
I'm currently having this piece of code, but I'm getting the error message saying:
"Run-time error '-2147023170 (800706be)':
Automation error The remote procedure call failed."
Would any of you know how to fix the connection?
Option Explicit
Option Compare Database
Public Sub CopyRstToExcel_test()
'On Error GoTo CopyRstToExcel_Err
Dim sPath As String
Dim fd As FileDialog
Dim oExcel As Object
Dim oExcelWrkBk As Object
Dim oExcelWrSht As Object
Dim dbs 'Added
Dim qdfName As String
Dim fRecords As Boolean
Dim rst As dao.Recordset
Dim iCols As Integer
'-------------------------------------------------------------------------------------------------------------------------------------------------------------------
' Select the file and identify the path leading to the file
'-------------------------------------------------------------------------------------------------------------------------------------------------------------------
'Define database you want to work with
Set dbs = CurrentDb
'Select the Excel file you want to work with
Set fd = Application.FileDialog(msoFileDialogFilePicker)
'Define the path
If fd.Show = -1 Then
sPath = fd.SelectedItems(1)
End If
MsgBox sPath
'-------------------------------------------------------------------------------------------------------------------------------------------------------------------
' Defining names of variables
'-------------------------------------------------------------------------------------------------------------------------------------------------------------------
'Defining variables (queries/tables)
qdfName = "Query_1"
'------------------------------------------------------------------------------------------------
'Copying the data from Access into the new Excel
'------------------------------------------------------------------------------------------------
Set rst = CurrentDb.OpenRecordset(qdfName, dbOpenSnapshot)
fRecords = False
If rst.EOF = False Then
fRecords = True
Set oExcel = CreateObject("Excel.Application")
Set oExcelWrkBk = GetObject(sPath)
oExcel.Visible = True
oExcel.ScreenUpdating = False
Set oExcelWrSht = oExcelWrkBk.Sheets(1)
For iCols = 0 To rst.Fields.Count - 1
oExcelWrSht.Cells(9, iCols + 2).Value = rst.Fields(iCols).Name
Next
oExcelWrSht.Range(oExcelWrSht.Cells(9, 2), _
oExcelWrSht.Cells(9, rst.Fields.Count)).Font.Bold = True
oExcelWrSht.Range("B10").CopyFromRecordset rst
oExcelWrSht.Range(oExcelWrSht.Cells(9, 2), _
oExcelWrSht.Cells(rst.RecordCount + 9, rst.Fields.Count)).Columns.AutoFit
oExcelWrSht.Range("A1").Select
End If
'------------------------------------------------------------------------------------------------
CopyRstToExcel_Done:
On Error Resume Next
If fRecords = True Then
oExcel.Visible = True
oExcel.ScreenUpdating = True
End If
Set oExcelWrSht = Nothing
Set oExcelWrkBk = Nothing
Set oExcel = Nothing
Set rst = Nothing
''Error message:
'CopyRstToExcel_Err:
' MsgBox Err & ": " & Error, vbExclamation
' Resume CopyRstToExcel_Done
' Resume
'------------------------------------------------------------------------------------------------
End Sub
In this step, I only want to copy the data in the first sheet, but later on I would also like to specify the name of the sheet and I've got already prepared templates I want to copy the data over.
Thank you for your help!
Try to replace
Set oExcelWrkBk = GetObject(sPath)
by
Set oExcelWrkBk = oExcel.Workbooks.Open(sPath)
Also I'd recommend to replace
Set rst = CurrentDb.OpenRecordset(qdfName, dbOpenSnapshot)
by
Set rst = dbs.OpenRecordset(qdfName, dbOpenSnapshot)
Open specified worksheet:
Set oExcelWrSht = oExcelWrkBk.Sheets("MyWorksheetName")

Not able to pull records from access to excel, Probable connection issue

I using the below code to pull records from access to excel.
I am getting error at
connDB.Open ConnectionString:="Provider = Microsoft.ACE.OLEDB.12.0; data source=" & strDB
The error says"invalid sql statement, delete, insert,procedure,selet or update"
Kindly help as I am stuck and cannot move forward at all....
please help.
Sub automateAccessADO_9()
'Using ADO to Import data from an Access Database Table to an Excel worksheet (your host application).
'refer Image 9a to view the existing SalesManager Table in MS Access file "SalesReport.accdb".
'To use ADO in your VBA project, you must add a reference to the ADO Object Library in Excel (your host application) by clicking Tools-References in VBE, and then choose an appropriate version of Microsoft ActiveX Data Objects x.x Library from the list.
'--------------
'DIM STATEMENTS
Dim strMyPath As String, strDBName As String, strDB As String, strSQL As String
Dim i As Long, n As Long, lFieldCount As Long
Dim rng As Range
'instantiate an ADO object using Dim with the New keyword:
Dim adoRecSet As New ADODB.Recordset
Dim connDB As New ADODB.Connection
'--------------
'THE CONNECTION OBJECT
strDBName = "Computer.accdb"
strMyPath = ThisWorkbook.Path
strDB = strMyPath & "\" & strDBName
'Connect to a data source:
'For pre - MS Access 2007, .mdb files (viz. MS Access 97 up to MS Access 2003), use the Jet provider: "Microsoft.Jet.OLEDB.4.0". For Access 2007 (.accdb database) use the ACE Provider: "Microsoft.ACE.OLEDB.12.0". The ACE Provider can be used for both the Access .mdb & .accdb files.
connDB.Open ConnectionString:="Provider = Microsoft.ACE.OLEDB.12.0; data source=" & strDB
'--------------
'OPEN RECORDSET, ACCESS RECORDS AND FIELDS
Dim ws As Worksheet
'set the worksheet:
Set ws = ActiveWorkbook.Sheets("Sheet1")
'Set the ADO Recordset object:
Set adoRecSet = New ADODB.Recordset
'Opening the table named SalesManager:
strTable = "memory"
'--------------
'COPY RECORDS FROM ALL FIELDS OF A RECORDSET:
'refer Image 9d to view records copied to Excel worksheet
adoRecSet.Open Source:=strTable, ActiveConnection:=connDB, CursorType:=adOpenStatic, LockType:=adLockOptimistic
Set rng = ws.Range("A1")
lFieldCount = adoRecSet.Fields.Count
For i = 0 To lFieldCount - 1
'copy column names in first row of the worksheet:
rng.Offset(0, i).Value = adoRecSet.Fields(i).Name
adoRecSet.MoveFirst
'copy record values starting from second row of the worksheet:
n = 1
Do While Not adoRecSet.EOF
rng.Offset(n, i).Value = adoRecSet.Fields(i).Value
adoRecSet.MoveNext
n = n + 1
Loop
Next i
'select column range to AutoFit column width:
Range(ws.Columns(1), ws.Columns(lFieldCount)).AutoFit
'worksheet columns are deleted because this code is only for demo:
Range(ws.Columns(1), ws.Columns(lFieldCount)).Delete
adoRecSet.Close
'close the objects
connDB.Close
'destroy the variables
Set adoRecSet = Nothing
Set connDB = Nothing
End Sub
When going from Access to Excel, you have quite a few options!
Here's one way to EXPORT data from Access to Excel.
Dim lngColumn As Long
Dim xlx As Object, xlw As Object, xls As Object, xlc As Object
Dim dbs As DAO.Database
Dim rst As DAO.Recordset
Dim blnEXCEL As Boolean, blnHeaderRow As Boolean
blnEXCEL = False
' Replace True with False if you do not want the first row of
' the worksheet to be a header row (the names of the fields
' from the recordset)
blnHeaderRow = True
' Establish an EXCEL application object
On Error Resume Next
Set xlx = GetObject(, "Excel.Application")
If Err.Number <> 0 Then
Set xlx = CreateObject("Excel.Application")
blnEXCEL = True
End If
Err.Clear
On Error GoTo 0
' Change True to False if you do not want the workbook to be
' visible when the code is running
xlx.Visible = True
' Replace C:\Filename.xls with the actual path and filename
' of the EXCEL file into which you will write the data
Set xlw = xlx.Workbooks.Open("C:\Filename.xls")
' Replace WorksheetName with the actual name of the worksheet
' in the EXCEL file
' (note that the worksheet must already be in the EXCEL file)
Set xls = xlw.Worksheets("WorksheetName")
' Replace A1 with the cell reference into which the first data value
' is to be written
Set xlc = xls.Range("A1") ' this is the first cell into which data go
Set dbs = CurrentDb()
' Replace QueryOrTableName with the real name of the table or query
' whose data are to be written into the worksheet
Set rst = dbs.OpenRecordset("QueryOrTableName", dbOpenDynaset, dbReadOnly)
If rst.EOF = False And rst.BOF = False Then
rst.MoveFirst
If blnHeaderRow = True Then
For lngColumn = 0 To rst.Fields.Count - 1
xlc.Offset(0, lngColumn).Value = rst.Fields(lngColumn).Name
Next lngColumn
Set xlc = xlc.Offset(1,0)
End If
' write data to worksheet
Do While rst.EOF = False
For lngColumn = 0 To rst.Fields.Count - 1
xlc.Offset(0, lngColumn).Value = rst.Fields(lngColumn).Value
Next lngColumn
rst.MoveNext
Set xlc = xlc.Offset(1,0)
Loop
End If
rst.Close
Set rst = Nothing
dbs.Close
Set dbs = Nothing
' Close the EXCEL file while saving the file, and clean up the EXCEL objects
Set xlc = Nothing
Set xls = Nothing
xlw.Close True ' close the EXCEL file and save the new data
Set xlw = Nothing
If blnEXCEL = True Then xlx.Quit
Set xlx = Nothing
Here's another way.
Dim lngColumn As Long
Dim xlx As Object, xlw As Object, xls As Object, xlc As Object
Dim dbs As DAO.Database
Dim rst As DAO.Recordset
Dim strPathFileName As String, strWorksheetName As String
Dim strRecordsetDataSource As String
Dim blnEXCEL As Boolean, blnHeaderRow As Boolean
blnEXCEL = False
' Replace C:\Filename.xls with the actual path and filename
' that will be used to save the new EXCEL file into which you
' will write the data
strPathFileName = "C:\Filename.xls"
' Replace QueryOrTableName with the real name of the table or query
' whose data are to be written into the worksheet
strRecordsetDataSource = "QueryOrTableName"
' Replace True with False if you do not want the first row of
' the worksheet to be a header row (the names of the fields
' from the recordset)
blnHeaderRow = True
' Establish an EXCEL application object
On Error Resume Next
Set xlx = GetObject(, "Excel.Application")
If Err.Number <> 0 Then
Set xlx = CreateObject("Excel.Application")
blnEXCEL = True
End If
Err.Clear
On Error GoTo 0
' Change True to False if you do not want the workbook to be
' visible when the code is running
xlx.Visible = True
' Create a new EXCEL workbook
Set xlw = xlx.Workbooks.Add
' Rename the first worksheet in the EXCEL file to be the first 31
' characters of the string in the strRecordsetDataSource variable
Set xls = xlw.Worksheets(1)
xls.Name = Trim(Left(strRecordsetDataSource, 31))
' Replace A1 with the cell reference of the first cell into which the
' headers will be written (blnHeaderRow = True), or into which the data
' values will be written (blnHeaderRow = False)
Set xlc = xls.Range("A1")
Set dbs = CurrentDb()
Set rst = dbs.OpenRecordset(strRecordsetDataSource, dbOpenDynaset, dbReadOnly)
If rst.EOF = False And rst.BOF = False Then
' Write the header row to worksheet
If blnHeaderRow = True Then
For lngColumn = 0 To rst.Fields.Count - 1
xlc.Offset(0, lngColumn).Value = rst.Fields(lngColumn).Name
Next lngColumn
Set xlc = xlc.Offset(1,0)
End If
' copy the recordset's data to worksheet
xlc.CopyFromRecordset rst
End If
rst.Close
Set rst = Nothing
dbs.Close
Set dbs = Nothing
' Save and close the EXCEL file, and clean up the EXCEL objects
Set xlc = Nothing
Set xls = Nothing
xlw.SaveAs strPathFileName
xlw.Close False
Set xlw = Nothing
If blnEXCEL = True Then xlx.Quit
Set xlx = Nothing
Here's a way to IMPORT date from Access to Excel.
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
Here's one more way to IMPORT your data.
Sub DAOCopyFromRecordSet(DBFullName As String, TableName As String, _
FieldName As String, TargetRange As Range)
' Example: DAOCopyFromRecordSet "C:\FolderName\DataBaseName.mdb", _
"TableName", "FieldName", Range("C1")
Dim db As Database, rs As Recordset
Dim intColIndex As Integer
Set TargetRange = TargetRange.Cells(1, 1)
Set db = OpenDatabase(DBFullName)
Set rs = db.OpenRecordset(TableName, dbOpenTable) ' all records
'Set rs = db.OpenRecordset("SELECT * FROM " & TableName & _
" WHERE " & FieldName & _
" = 'MyCriteria'", dbReadOnly) ' filter records
' write field names
For intColIndex = 0 To rs.Fields.Count - 1
TargetRange.Offset(0, intColIndex).Value = rs.Fields(intColIndex).Name
Next
' write recordset
TargetRange.Offset(1, 0).CopyFromRecordset rs
Set rs = Nothing
db.Close
Set db = Nothing
End Sub

copyfromrecordset returns blank column

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

Refreshing an Excel Pivot Table data source with VBA in MS Access

I prefer producing an Excel report that has no links in it, so that it is lightweight and can easily be emailed.
So I have this report that I generate from MS Access - it writes the table to the TAB of a workbook that I have previously built a Pivot Table that uses that tab as it's source.
What I can't seem to get working properly is
xlPivot.PivotTables("pvAFP").RefreshTable
My code is as follows:
Public Sub ViewAFP(strPathToTemplate As String, Optional dbFullPath As String)
'10 Excel objects created
Dim xlApp As Object
Dim WB As Object
Dim xlSheet As Object
Dim xlPivot As Object
Dim rngWorkingRange As Object
Dim intCOL As Integer
Dim db As Database
Dim rsAFP_Pivot As DAO.Recordset
Dim rsAFP_Data As DAO.Recordset
Dim fld As Variant
Dim strLocation As String
'uses the 'My Documents\COB folder of the user
'C:\Users\[username]\Documents\COB
strLocation = "C:\users\" & Environ$("Username") & "\Documents\COB\AFP_Summary_" & DateString & ".xlsx"
Set xlApp = CreateObject("Excel.Application")
Set WB = xlApp.Workbooks.Open(strPathToTemplate)
Set xlSheet = WB.Sheets("AFP DATA")
Set xlPivot = WB.Sheets("AFP PIVOT")
'ALLOW FOR EXTERNAL ENGINES
If Len(dbFullPath) < 1 Then
Set db = CurrentDb
Else
Set db = OpenDatabase(dbFullPath, True)
End If
Set rsAFP_Data = db.OpenRecordset("Select * FROM AFP_DATA")
intCOL = 1
For Each fld In rsAFP_Data.Fields
xlSheet.Cells(1, intCOL).Value = fld.Name
Debug.Print fld.Name
intCOL = intCOL + 1
Next
xlSheet.Range("A2").CopyFromRecordset rsAFP_Data
Set rngWorkingRange = xlSheet.Range("A1").CurrentRegion
xlSheet.ListObjects.Add(xlSrcRange, rngWorkingRange, , xlYes).Name _
= "AFP_Data"
xlSheet.ListObjects("AFP_Data").TableStyle = "TableStyleLight9"
'set pvAFP to point to this table
xlPivot.PivotTables("pvAFP").ChangePivotCache WB.PivotCaches. _
Create(SourceType:=xlDatabase, SourceData:="AFP DATA!AFP_Data", _
Version:=xlPivotTableVersion12)
xlPivot.Select
xlPivot.PivotTables("pvAFP").RefreshTable
WB.RefreshAll
WB.SaveAs FileName:=strLocation
xlApp.Quit
Set xlSheet = Nothing
Set fld = Nothing
Set rsAFP_Data = Nothing
Set db = Nothing
Set WB = Nothing
Set xlApp = Nothing
End Sub
Would be nice to be ready to use, because the user needs to "Refresh ALL", before anything can be done to the Pivot Table
See if this works for you:
xlPivot.PivotTables("pvAFP").PivotCache.Refresh

How do I copy and filter a DAO recordset in VBA?

Due to problems with DAO (see my previous question), I need to create an Excel VBA Recordset from an Access query and filter its results using a user-defined function.
I thought I could use the following code to accomplish this:
Sub test()
Dim db As Database
Dim rs As Recordset
Dim rs_clone As Recordset
Set db = OpenDatabase(dbPath)
Set rs = db.OpenRecordset("select testVal from dataTable")
Set rs_clone = rs.Clone
rs_clone.MoveLast
rs_clone.MoveFirst
while not rs_clone.eof
if myUDF(rs_clone!testVal) then
rs_clone.delete
end if
rs_clone.moveNext
wend
End Sub
But that actually deletes values from my source table, so the clone isn't a new recordset that I can freely alter, it's just another pointer to the original one. How can I use my UDF to filter out the records I don't want, while leaving the original data untouched, if putting the UDF in the query itself is not an option?
In Access with DAO, this is how you'd do it:
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim rsFiltered As DAO.Recordset
Set db = CurrentDb
Set rs = db.OpenRecordset("SELECT tblInventory.* FROM tblInventory;")
rs.MoveLast
Debug.Print "Unfiltered: " & rs.RecordCount
rs.filter = "[LastUpdated]>=#1/1/2011#"
Set rsFiltered = rs.OpenRecordset
rsFiltered.MoveLast
Debug.Print "Filtered: " & rsFiltered.RecordCount
rsFiltered.Close
Set rsFiltered = Nothing
rs.Close
Set rs = Nothing
Set db = Nothing
However, note that (as mentioned in the help file), it may be just as fast to simply reopen the recordset with new criteria, instead of filtering the existing recordset.
Use the .getrows method:
Dim rs_clone As Variant
...
rs_clone = rs.getrows(numrows)
then process the resulting 2-d array.
Option Compare Database
Private Sub Command0_Click()
Sub Export_Click()
Dim db As Database, rs As Recordset, sql As String, r As Variant
Dim appExcel As Excel.Application
Dim excelWbk As Excel.Workbook
Dim excelSht As Object
Dim rng As Excel.Range
Set appExcel = New Excel.Application
On Error Resume Next
Set excelWbk = appExcel.Workbooks.Open("Folder Name(Template)")
Set db = CurrentDb()
sql1 = "Select * from Query_New"
sql2 = "Select * from Query_Expired"
Set rs1 = db.OpenRecordset(sql1, dbReadOnly)
Set rs2 = db.OpenRecordset(sql2, dbReadOnly)
Dim SheetName1 As String
Dim SheetName2 As String
SheetName1 = "New"
SheetName2 = "Expired"
'For first sheet
On Error Resume Next
excelWbk.Sheets(SheetName1).Select
If Err.Number <> 0 Then
MsgBox Err.Number
excelWbk.Close False
appExcel.Quit
Exit Sub
End If
With excelWbk.Activesheet
.Cells(5, 1).CopyFromRecordset rs1
On Error GoTo 0
End With
'For second sheet
On Error Resume Next
excelWbk.Sheets(SheetName2).Select
If Err.Number <> 0 Then
MsgBox Err.Number
excelWbk.Close False
appExcel.Quit
Exit Sub
End If
With excelWbk.Activesheet
.Cells(5, 1).CopyFromRecordset rs2
On Error GoTo 0
End With
rs1.Close
Set rs1 = Nothing
rs2.Close
Set rs2 = Nothing
db.Close
Set db = Nothing
On Error Resume Next
excelWbk.SaveAs "C:\Documents and settings\" & Environ("UserName") & "\Desktop\Decision.xlsx"
If Err.Number <> 0 Then
MsgBox Err.Number
End If
excelWbk.Close False
appExcel.Quit
Set appExcel = Nothing
MsgBox "The report has been saved"
End Sub
End Sub

Resources