Copying records in Access VBA - vba

I'm attempting to build a process where you click the EndofDay button which will then go into the subform look for any status of 10 (In Process) and then copy those records before auto completing them. The problem I'm having is getting my
DoCmd.DoMenuItem acFormBar, acEditMenu, 8, , acMenuVer70DoCmd.DoMenuItem acFormBar, acEditMenu, 8, , acMenuVer70 ... command set to work properly. I get an error message saying "The action or command "Copy" isn't available now".
The main form is "frmTasks" and the subform is called "Tasks" and the table that "Tasks" uses is called "tblTasks".
UPDATE:
I've found if I try to run my original code within the sub form Tasks by itself the code will copy without the "Copy is unavailable" message. If I try to call that code from the main form I get the copy is unavailable again. I'm not sure why it is saying the function copy is unavailable. Any clue as to why?
Private Sub EndofDay_Click()
If Me.Tasks.Form.Status = 10 Then
'Copy In Process Tasks
DoCmd.DoMenuItem acFormBar, acEditMenu, 8, , acMenuVer70
DoCmd.DoMenuItem acFormBar, acEditMenu, 2, , acMenuVer70
DoCmd.DoMenuItem acFormBar, acEditMenu, 5, , acMenuVer70
'Complete Old In process Tasks
Else
MsgBox ("Nothing Done")
'do nothing
End If
End Sub
Updated Code:
Private Sub EndofDay_Click()
Dim rstSource As DAO.Recordset
Dim rstInsert As DAO.Recordset
Dim fld As DAO.Field
Dim lngLoop As Long
Dim lngCount As Long
Set rstInsert = Me!Tasks.Form.RecordsetClone
Set rstSource = rstInsert.Clone
With rstSource
lngCount = .RecordCount
For lngLoop = 1 To lngCount
If Nz(!Status.Value, 0) <> 10 Then
' Ignore record.
Else
With rstInsert
.AddNew
For Each fld In rstSource.Fields
With fld
If .Attributes And dbAutoIncrField Then
' Skip Autonumber or GUID field.
ElseIf .Name = "Start Date" Then
' Skip read-only field.
ElseIf .Name = "Date Completed" Then
' Skip read-only field.
ElseIf .Name = "Owner" Then
' Skip read-only field.
ElseIf .Name = "Active" Then
' Skip read-only field.
ElseIf .Name = "Status" Then
' Insert default value.
rstInsert.Fields(.Name).Value = 0
Else
' Copy field content.
rstInsert.Fields(.Name).Value = .Value
End If
End With
Next
.Update
End With
.Edit
!Status.Value = 100
.Update
End If
.MoveNext
Next
rstInsert.Close
.Close
End With
Set rstInsert = Nothing
Set rstSource = Nothing
End Sub
Any help would be greatly appreciated.

Could be something like this in your Click event of the EndOfDay button on the main form:
Public Sub CopyRecords()
Dim rstSource As DAO.Recordset
Dim rstInsert As DAO.Recordset
Dim fld As DAO.Field
Dim lngLoop As Long
Dim lngCount As Long
Set rstInsert = Me!NameOfSubformControl.Form.RecordsetClone
Set rstSource = rstInsert.Clone
With rstSource
lngCount = .RecordCount
For lngLoop = 1 To lngCount
If Nz(!Status.Value, 0) <> 10 Then
' Ignore record.
Else
With rstInsert
.AddNew
For Each fld In rstSource.Fields
With fld
If .Attributes And dbAutoIncrField Then
' Skip Autonumber or GUID field.
ElseIf .Name = "SomeReadOnlyField" Then
' Skip read-only field.
ElseIf .Name = "Status" Then
' Insert default value.
rstInsert.Fields(.Name).Value = 0
Else
' Copy field content.
rstInsert.Fields(.Name).Value = .Value
End If
End With
Next
.Update
End With
.Edit
!Status.Value = 100
.Update
End If
.MoveNext
Next
rstInsert.Close
.Close
End With
Set rstInsert = Nothing
Set rstSource = Nothing
End Sub

Related

MS access VBA Field.Properties.Append method fails

I have a form that creates a table. Everything works fine except for one point.
I want one field of the created table to appear as a combobox, so I have to change its DisplayControl property to acComboBox.
As far as I know, the property firstly has to exist. If not, then you have to create it and then append it to the collection.
The problem is that when it comes to append the property it throws a Run-time error '3219': Invalid operation..
Here is the code to this point:
Private Sub bInsert_Click()
Dim accApp As Access.Application
Dim DB As DAO.Database
Dim tbl As DAO.TableDef
Dim fld As DAO.Field
Dim indx As DAO.Index
Dim rst As DAO.Recordset
Dim i As Integer, iFields As Integer
Dim sForm As String, str As String
Dim frm As Access.Form
Dim sCtrl() As String
If Not Application.IsCompiled Then _
Application.RunCommand acCmdCompileAndSaveAllModules
'there is a subform for the fields:
Set rst = Me.subfFields.Form.Recordset
rst.MoveFirst
'completion check:
If IsNull(Me.tName) Then
MsgBox "Insert table name."
Exit Sub
ElseIf rst.AbsolutePosition = -1 Then
MsgBox "Insert at least one field."
Exit Sub
End If
'create a db that will use later:
If Dir(Me.tDB) = "" Then
Set accApp = New Access.Application
accApp.NewCurrentDatabase Me.tDB
accApp.Quit
Set accApp = Nothing
End If
'create Table:
Set DB = Application.CurrentDb
Set tbl = DB.CreateTableDef(Me.tName)
'ID as PK:
Set fld = tbl.CreateField("ID", dbLong)
fld.Attributes = dbAutoIncrField
tbl.Fields.Append fld
Set indx = tbl.CreateIndex("IDindex")
indx.Primary = True
Set fld = indx.CreateField("ID")
indx.Fields.Append fld
tbl.Indexes.Append indx
Set indx = Nothing
Set fld = Nothing
'add rest of the fields:
Do Until rst.EOF
i = Me.subfFields.Form!cType
If i = dbText Then
Set fld = tbl.CreateField(Me.subfFields.Form!tName, i, Nz(Me.subfFields.Form!tSize, 255))
Else
Set fld = tbl.CreateField(Me.subfFields.Form!tName, i)
End If
tbl.Fields.Append fld
If Me.subfFields.Form!cControl = 111 Then
SetDAOProperty fld, "DisplayControl", dbInteger, acComboBox
End If
rst.MoveNext
Loop
End Sub
Sub SetDAOProperty(WhichObject As Field, PropertyName As String, PropertyType As Integer, PropertyValue As Variant)
Dim prp As DAO.Property
On Error GoTo ErrorHandler
WhichObject.Properties(PropertyName) = PropertyValue
WhichObject.Properties.Refresh
Cleanup:
Set prp = Nothing
Exit Sub
ErrorHandler:
Select Case Err.Number
Case 3270 ' "Property not found"
Set prp = WhichObject.CreateProperty(PropertyName, PropertyType, PropertyValue)
'=====================================
'the next line throws the error:
'=====================================
WhichObject.Properties.Append prp
WhichObject.Properties.Refresh
Case Else
MsgBox Err.Number & ": " & Err.Description
End Select
Resume Cleanup
End Sub
Can someone explain what is the problem please? Seems like I'm missing something. Is there some kind of syntax error? My native language isn't English.
So as June7 suggested, appending firstly the table and then modifing the field's properties, worked fine.
Here is the final code in case someone needs it:
'create Table:
Set DB = Application.CurrentDb
Set tbl = DB.CreateTableDef(Me.tName)
'ID as PK:
Set fld = tbl.CreateField("ID", dbLong)
fld.Attributes = dbAutoIncrField
tbl.Fields.Append fld
Set indx = tbl.CreateIndex("IDindex")
indx.Primary = True
Set fld = indx.CreateField("ID")
indx.Fields.Append fld
tbl.Indexes.Append indx
Set indx = Nothing
Set fld = Nothing
'add rest of the fields:
Do Until rst.EOF
i = Me.subfFields.Form!cType
If i = dbText Then
Set fld = tbl.CreateField(Me.subfFields.Form!tName, i, Nz(Me.subfFields.Form!tSize, 255))
Else
Set fld = tbl.CreateField(Me.subfFields.Form!tName, i)
End If
tbl.Fields.Append fld
If Me.subfFields.Form!cControl = 111 Then
SetDAOProperty fld, "DisplayControl", dbInteger, acComboBox
End If
rst.MoveNext
Loop
'append table:
DB.TableDefs.Append tbl
'format comboboxes:
rst.MoveFirst
Do Until rst.EOF
If Me.subfFields.Form!cControl = 111 Then
Set fld = tbl.Fields(Me.subfFields.Form!tName)
SetDAOProperty fld, "DisplayControl", dbInteger, acComboBox
SetDAOProperty fld, "RowSourceType", dbText, "Value List"
SetDAOProperty fld, "RowSource", dbText, "Test1;Test2"
SetDAOProperty fld, "ColumnCount", dbInteger, 2
SetDAOProperty fld, "ColumnWidths", dbText, "0;1"
SetDAOProperty fld, "ListRows", dbInteger, 4
SetDAOProperty fld, "LimitToList", dbBoolean, -1
SetDAOProperty fld, "AllowValueListEdits", dbBoolean, 0
SetDAOProperty fld, "ShowOnlyRowSourceValues", dbBoolean, -1
End If
rst.MoveNext
Loop
This answer may be similar to this, but is not a duplicate. The goal is similar but the problem faced(error) is different.

How to store record information from a ListBox to a Table?

I am using the following code that is linked to a button cmdAdd. Using the 'On Click' event, the ListBox selection information is copied to a table KitBuild.
Private Sub cmdAdd_Click()
Dim strSQL As String
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim ctl As Control
Dim varItem As Variant
On Error GoTo ErrorHandler
Set db = CurrentDb()
Set rs = db.OpenRecordset("KitBuild", dbOpenDynaset, dbAppendOnly)
'make sure a selection has been made
If Me.lstResults.ItemsSelected.Count = 0 Then
MsgBox "At least 1 part must be selected."
Exit Sub
End If
'add selected value(s) to table
Set ctl = Me.lstResults
For Each varItem In ctl.ItemsSelected
rs.AddNew
rs!ItemNo = ctl.ItemData(varItem)
rs.Update
Next varItem
ExitHandler:
Set rs = Nothing
Set db = Nothing
Exit Sub
ErrorHandler:
Select Case Err
Case Else
MsgBox Err.Description
DoCmd.Hourglass False
Resume ExitHandler
End Select
End Sub
Shown below is the table KitBuild where selections are saved. Currently, it only transfers over 1 piece of information from the selection which is No from qryParts into the column called ItemNo (ID #8). This works fine but I also need to transfer over the Description and Unit Cost of records from qryParts to KitBuild.
I tried changing the following to rs!Description and rs!UnitCost but the No value just shifts over to those columns (ID #9, 10) rather than providing the Description and Cost.
'add selected value(s) to table
Set ctl = Me.lstResults
For Each varItem In ctl.ItemsSelected
rs.AddNew
rs!ItemNo = ctl.ItemData(varItem)
rs.Update
Next varItem
This is an example of the information I would like copied from qryParts to KitBuild.
How can I modify the code to include No, Description and Cost?
I assume that your ListBox has data in the order as on your last picture. Use this:
'add selected value(s) to table
Set ctl = Me.lstResults
For Each varItem In ctl.ItemsSelected
rs.AddNew
rs!ItemNo = ctl.Column(0)
rs!Description = ctl.Column(1)
rs!UnitCost = ctl.Column(2)
rs.Update
Next varItem

Add start and end word fields for tracked changes

I want to add two word fields at the start and end of each track change of a document.
I am iterating through the word revisions using a for-each loop.
Below is my code :
Private Function TrackChangesOnDeletions(ByRef WordRange As Word.Range)
On Error GoTo ErrorHandler
Dim fTrackRevisions As Boolean
Dim objRevision As Word.Revision
Dim objContentControl As Word.ContentControl
Dim objRange As Word.Range
Dim objField As Word.Field
Dim index As Long
Dim objRangeCopy As Word.Range
Dim objFieldEnd As Word.Field
With WordRange.Document
fTrackRevisions = .TrackRevisions
.TrackRevisions = False
End With
With WordRange
For Each objRevision In .Revisions
On Error Resume Next
With objRevision
Set objRange = .Range
'Make sure there's no break character that may exist at the end of the specified range,
'in order to avoid end field appears at the beginning of the next line.
If Len(.Range.Text) > 0 Then
Select Case Asc(WordRange.Characters.Last)
Case 7, 10, 11, 12, 13, 14
.Range.MoveEnd Unit:=WdUnits.wdCharacter, Count:=-1
End Select
End If
'Create a copy of the passed range.
Set objRangeCopy = .Range.Duplicate
With objRangeCopy
.Collapse wdCollapseEnd
'Ensure we are not at an end-of-row marker.
Do While .Information(wdAtEndOfRowMarker) = True
.MoveEnd Unit:=WdUnits.wdCharacter, Count:=1
.Collapse wdCollapseEnd
Loop
End With
'Create a new field at the specified range.
Set objFieldEnd = objRangeCopy.Fields.Add(Range:=objRangeCopy, Type:=wdFieldComments, PreserveFormatting:=False)
'Insert end tag
objFieldEnd.Code.InsertAfter " >"
Set objRangeCopy = .Range.Duplicate
objRangeCopy.Collapse Direction:=wdCollapseStart
objFieldEnd.Update
'Insert the start tag
Set objField = objRangeCopy.Fields.Add(Range:=objRangeCopy, Type:=wdFieldComments, Text:="Deletion< ", PreserveFormatting:=False)
objField.Update
objRange.SetRange Start:=objField.Code.Start - 1, End:=objFieldEnd.Code.End + 3
objRange.Font.StrikeThrough = True
objRange.Font.ColorIndex = wdRed
.Reject
End With
Err.Clear
Set objContentControl = Nothing
Next objRevision
End With
ErrorHandler:
WordRange.Document.TrackRevisions = fTrackRevisions
Set objContentControl = Nothing
Set objField = Nothing
Set objRange = Nothing
Set objRevision = Nothing
Select Case Err.Number
Case 0
Case Else
ShowUnexpectedError ErrorSource:="TrackChangesOnDeletions" & vbCr & Err.Source
End Select
End Function
My issue is, once the code executed for the first revision, it gets the first revision as the next revision (at for loops' next) as well, event the revision count remain same. So the start and end fields keep adding to the first revision and it makes word crash.
For the below original text,
I need the output as,
When the field codes are hidden, it should display as :
But my code gives the output as, (I have manually stop the for loop iteration to have this capture, else it will add fields and fields and cause word crash)
Form my further testings, I have identified that, if some text were inserted before the revision within the loop, the next revision will be same as the current revision. So the loop is running nonstop and then crash word.
Could anybody please tell me what I am doing wrong here.
Thank you in advance.
In order to move out from the loop at correct time, I used the below approach.
Any improvements or other answers are appreciated.
Private Function TrackChangesOnDeletions(ByRef WordRange As Word.Range)
On Error GoTo ErrorHandler
Dim fTrackRevisions As Boolean
Dim objRevision As Word.Revision
Dim objRange As Word.Range
Dim objRangeCopy As Word.Range
Dim objFieldStart As Word.Field
Dim objFieldEnd As Word.Field
Dim index As Long
Dim revisionCount As Long
With WordRange.Document
fTrackRevisions = .TrackRevisions
.TrackRevisions = False
End With
revisionCount = WordRange.Revisions.Count
index = 1
If (revisionCount > 0) Then
Set objRevision = WordRange.Revisions(index)
Do While Not objRevision Is Nothing
If AllowTrackChangesForDeletion(objRevision) = True Then
On Error Resume Next
With objRevision
Set objRange = .Range
'Make sure there's no break character that may exist at the end of the specified range,
'in order to avoid end field appears at the beginning of the next line.
If Len(objRange.Text) > 0 Then
Select Case Asc(objRange.Characters.Last)
Case 7, 10, 11, 12, 13, 14
objRange.MoveEnd Unit:=WdUnits.wdCharacter, Count:=-1
End Select
End If
'Create a copy of the passed range.
Set objRangeCopy = objRange.Duplicate
With objRangeCopy
.Collapse wdCollapseEnd
'Ensure we are not at an end-of-row marker.
Do While .Information(wdAtEndOfRowMarker) = True
.MoveEnd Unit:=WdUnits.wdCharacter, Count:=1
.Collapse wdCollapseEnd
Loop
End With
'Create a new field at the specified range.
Set objFieldEnd = objRangeCopy.Fields.Add(Range:=objRangeCopy, Type:=wdFieldComments, PreserveFormatting:=False)
'Insert end tag
objFieldEnd.Code.InsertAfter " >"
Set objRangeCopy = objRange.Duplicate
objRangeCopy.Collapse Direction:=wdCollapseStart
objFieldEnd.Update
'Insert the start tag
Set objFieldStart = objRangeCopy.Fields.Add(Range:=objRangeCopy, Type:=wdFieldComments, Text:="Deletion< ", PreserveFormatting:=False)
objFieldStart.Update
objRange.SetRange Start:=objFieldStart.Code.Start - 1, End:=objFieldEnd.Code.End + 3
objRange.Font.StrikeThrough = True
objRange.Font.ColorIndex = wdRed
.Reject
End With
Err.Clear
End If
'Move to the next revision (unable to use for loop, because it iterates through the first revision everytime and
'then crash word
index = index + 1
If index > revisionCount Then
Exit Do
End If
Set objRevision = WordRange.Revisions(index)
Loop
End If
ErrorHandler:
WordRange.Document.TrackRevisions = fTrackRevisions
Set objFieldEnd = Nothing
Set objFieldStart = Nothing
Set objRange = Nothing
Set objRangeCopy = Nothing
Set objRevision = Nothing
Select Case Err.Number
Case 0
Case Else
ShowUnexpectedError ErrorSource:="TrackChangesOnDeletions" & vbCr & Err.Source
End Select
End Function

MS Word Drop down list or combo box from MS Access Database

I'm trying to populate a combo box or drop down list from an access database. I used the following website for code template. I modified it to suit my needs. I keep getting the error: 5941 The requested member of the collection does not exist"
Source code: http://www.fontstuff.com/mailbag/qword02.htm
My Code:
Private Sub Document_Open()
On Error GoTo Document_Open_Err
Dim cnn As New ADODB.Connection
Dim rst As New ADODB.Recordset
cnn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=*path to database removed for post*;"
rst.Open "SELECT DISTINCT TOP 25 [Equipment] FROM tblEquipment ORDER BY [Equipment];", _
cnn, adOpenStatic
rst.MoveFirst
With ActiveDocument.FormFields("Equipment").DropDown.ListEntries
.Clear
Do
.Add rst![Equipment]
rst.MoveNext
Loop Until rst.EOF
End With
Document_Open_Exit:
On Error Resume Next
rst.Close
cnn.Close
Set rst = Nothing
Set cnn = Nothing
Exit Sub
Document_Open_Err:
MsgBox Err.Number & vbCrLf & Err.Description, vbCritical, "Error!"
Resume Document_Open_Exit
End Sub
Code that almost works:
Private Sub Document_Open()
On Error GoTo Document_Open_Err
Dim cnn As New ADODB.Connection
Dim rst As New ADODB.Recordset
cnn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=*removed for post*;"
rst.Open "SELECT DISTINCT TOP 25 [Field1] FROM Equipment_List ORDER BY [Field1];", _
cnn, adOpenStatic
rst.MoveFirst
With ActiveDocument.FormFields("Equipment").DropDown.ListEntries
.Clear
Do
.Add rst![Field1]
rst.MoveNext
Loop Until rst.EOF
End With
Document_Open_Exit:
On Error Resume Next
rst.Close
cnn.Close
Set rst = Nothing
Set cnn = Nothing
Exit Sub
Document_Open_Err:
MsgBox Err.Number & vbCrLf & Err.Description, vbCritical, "Error!"
Resume Document_Open_Exit
End Sub
I'm updating my last post here. See the code below; set a reference to DAO and make a couple minor tweaks to suit your needs.
Option Explicit
'Requires a reference to the '"Microsoft DAO 3.51 (or 3.6) Object Library."
Private Sub Userform_Initialize()
Dim myDataBase As DAO.Database
Dim myActiveRecord As DAO.Recordset
Dim i As Long
'Open the database to retrieve data
Set myDataBase = OpenDatabase("D:\Data Stores\sourceAccess.mdb")
'Define the first recordset
Set myActiveRecord = myDataBase.OpenRecordset("Table1", dbOpenForwardOnly)
'Set the listbox column count
ListBox1.ColumnCount = myActiveRecord.Fields.Count
i = 0
'Loop through all the records in the table until the EOF marker is reached.
Do While Not myActiveRecord.EOF
'Use .AddItem method to add a new row for each record
ListBox1.AddItem
ListBox1.List(i, 0) = myActiveRecord.Fields("Employee Name")
ListBox1.List(i, 1) = myActiveRecord.Fields("Employee DOB")
ListBox1.List(i, 2) = myActiveRecord.Fields("Employee ID")
i = i + 1
'Get the next record
myActiveRecord.MoveNext
Loop
'Close the database and clean-up
myActiveRecord.Close
myDataBase.Close
Set myActiveRecord = Nothing
Set myDataBase = Nothing
lbl_Exit:
Exit Sub
End Sub
Private Sub CommandButton1_Click()
Dim oRng As Word.Range
Dim oBM As Bookmarks
Set oBM = ActiveDocument.Bookmarks
Set oRng = oBM("EmpName").Range
oRng.Text = ListBox1.Text
oBM.Add "EmpName", oRng
Set oRng = oBM("EmpDOB").Range
oRng.Text = ListBox1.List(ListBox1.ListIndex, 1)
oBM.Add "EmpDOB", oRng
Set oRng = oBM("EmpID").Range
oRng.Text = ListBox1.List(ListBox1.ListIndex, 2)
oBM.Add "EmpID", oRng
Me.Hide
lbl_Exit:
Exit Sub
End Sub
Code Source:
https://gregmaxey.com/word_tip_pages/populate_userform_listbox_or_combobox.html

Export Each Access Table To Individual Workbook

I have been using this syntax which will export every table in a database to ONE excel workbook, but now my needs are to export every table to it's own workbook. How could this be tweaked to export each table to it's own workbook?
Sub ExportToExcel()
Dim td As DAO.TableDef, db As DAO.Database
Dim out_file As String
out_file = "C:\fromaccess.xlsx"
Set db = CurrentDb()
For Each td in db.TableDefs
If Left(td.Name, 4) = "MSys" Then
'Do Nothing
Else
DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel9, td.Name, out_file, True, Replace(td.Name, "dbo_","")
End If
Next
End Sub
EDIT
I tried the suggestion by #HA560 but get an error of
Run-time error '91':
Object variable or With block variable not set
This is updated code:
Sub ExportToExcel()
Dim td As DAO.TableDef, db As DAO.Database
Dim out_file As String
Dim xl As Excel.Application
out_file = "C:\fromaccess.xlsx"
Set db = CurrentDb()
For Each td in db.TableDefs
xl.Workbooks.Add
If Left(td.Name, 4) = "MSys" Then
'Do Nothing
Else
DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel9, td.Name, out_file, True, Replace(td.Name, "dbo_","")
End If
Next
End Sub
Bit of a long one which includes a three procedures. After running you should have a list of table names and TRUE/FALSE in the immediate window saying whether the export was successful.
ExportAll - The main procedure.
CreateXL - this creates an instance of Excel. It uses late binding, so no need to set references.
QueryExportToXL - this is the code to export the table. I haven't used TransferSpreadsheet as I like more control.
You need to pass a worksheet reference to the function.
You can pass either a query name or a recordset to the function.
You can pass an alternative sheet name.
The default cell to paste into is A1, but you can change this.
By default it adjusts the column widths to fit.
You can pass a collection of heading names to use instead of the field names.
There's not much error handling in there - such as passing a different number of heading names than there are fields, giving illegal sheet names.
It needs work :)
Public Sub ExportAll()
Dim db As DAO.Database
Dim tdf As DAO.TableDef
Dim rst As DAO.Recordset
Dim oXL As Object
Dim oWrkBk As Object
Set db = CurrentDb
'Create instance of Excel.
Set oXL = CreateXL
For Each tdf In db.TableDefs
If Left(tdf.Name, 4) <> "MSys" Then
'Create workbook with single sheet.
Set oWrkBk = oXL.WorkBooks.Add(-4167) 'xlWBATWorksheet
'Open the table recordset.
Set rst = tdf.OpenRecordset
'In the immediate window display table name and TRUE/FALSE if exported successfully.
Debug.Print tdf.Name & " - " & QueryExportToXL(oWrkBk.worksheets(1), , rst, tdf.Name)
'Save and close the workbook.
oWrkBk.SaveAs "<path to folder>" & tdf.Name
oWrkBk.Close
End If
Next tdf
End Sub
'----------------------------------------------------------------------------------
' Procedure : CreateXL
' Author : Darren Bartrup-Cook
' Date : 02/10/2014
' Purpose : Creates an instance of Excel and passes the reference back.
'-----------------------------------------------------------------------------------
Public Function CreateXL(Optional bVisible As Boolean = True) As Object
Dim oTmpXL As Object
'''''''''''''''''''''''''''''''''''''''''''''''''''''
'Defer error trapping in case Excel is not running. '
'''''''''''''''''''''''''''''''''''''''''''''''''''''
On Error Resume Next
Set oTmpXL = GetObject(, "Excel.Application")
'''''''''''''''''''''''''''''''''''''''''''''''''''''''
'If an error occurs then create an instance of Excel. '
'Reinstate error handling. '
'''''''''''''''''''''''''''''''''''''''''''''''''''''''
If Err.Number <> 0 Then
Err.Clear
On Error GoTo ERROR_HANDLER
Set oTmpXL = CreateObject("Excel.Application")
End If
oTmpXL.Visible = bVisible
Set CreateXL = oTmpXL
On Error GoTo 0
Exit Function
ERROR_HANDLER:
Select Case Err.Number
Case Else
MsgBox "Error " & Err.Number & vbCr & _
" (" & Err.Description & ") in procedure CreateXL."
Err.Clear
End Select
End Function
'----------------------------------------------------------------------------------
' Procedure : QueryExportToXL
' Author : Darren Bartrup-Cook
' Date : 26/08/2014
' Purpose : Exports a named query or recordset to Excel.
'-----------------------------------------------------------------------------------
Public Function QueryExportToXL(wrkSht As Object, Optional sQueryName As String, _
Optional rst As DAO.Recordset, _
Optional SheetName As String, _
Optional rStartCell As Object, _
Optional AutoFitCols As Boolean = True, _
Optional colHeadings As Collection) As Boolean
Dim db As DAO.Database
Dim prm As DAO.Parameter
Dim qdf As DAO.QueryDef
Dim fld As DAO.Field
Dim oXLCell As Object
Dim vHeading As Variant
On Error GoTo ERROR_HANDLER
If sQueryName <> "" And rst Is Nothing Then
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'Open the query recordset. '
'Any parameters in the query need to be evaluated first. '
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Set db = CurrentDb
Set qdf = db.QueryDefs(sQueryName)
For Each prm In qdf.Parameters
prm.Value = Eval(prm.Name)
Next prm
Set rst = qdf.OpenRecordset
End If
If rStartCell Is Nothing Then
Set rStartCell = wrkSht.cells(1, 1)
Else
If rStartCell.Parent.Name <> wrkSht.Name Then
Err.Raise 4000, , "Incorrect Start Cell parent."
End If
End If
If Not rst.BOF And Not rst.EOF Then
With wrkSht
Set oXLCell = rStartCell
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'Paste the field names from the query into row 1 of the sheet. '
'Or the alternative field names provided in a collection. '
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
If colHeadings Is Nothing Then
For Each fld In rst.Fields
oXLCell.Value = fld.Name
Set oXLCell = oXLCell.Offset(, 1)
Next fld
Else
For Each vHeading In colHeadings
oXLCell.Value = vHeading
Set oXLCell = oXLCell.Offset(, 1)
Next vHeading
End If
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'Paste the records from the query into row 2 of the sheet. '
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Set oXLCell = rStartCell.Offset(1, 0)
oXLCell.copyfromrecordset rst
If AutoFitCols Then
.Columns.Autofit
End If
If SheetName <> "" Then
.Name = SheetName
End If
'''''''''''''''''''''''''''''''''''''''''''
'TO DO: Has recordset imported correctly? '
'''''''''''''''''''''''''''''''''''''''''''
QueryExportToXL = True
End With
Else
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'There are no records to export, so the export has failed. '
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
QueryExportToXL = False
End If
Set db = Nothing
On Error GoTo 0
Exit Function
ERROR_HANDLER:
Select Case Err.Number
Case Else
MsgBox "Error " & Err.Number & vbCr & _
" (" & Err.Description & ") in procedure QueryExportToXL."
Err.Clear
Resume
End Select
End Function
After for each use workbooks.add()method...out_file=activeworkbook.path