I am trying to call a function when running a sub proecudere, however, I keep getting an error message saying "Argument not optional", can someone help?
Code as follows:
Public Sub ret()
Dim FSO As New Scripting.FileSystemObject
Const cstrFolderF = "\\tblSCFLAGCHECKER.txt"
If FSO.FileExists(cstrFolderF) Then
DoCmd.RunSQL "DELETE * FROM [tblSCFLAG_CHECKER]"
DoCmd.TransferText acImportDelim, "tblSCFLAG_CHECKER", "tblSCFLAG_CHECKER", cstrFolderF, True
changefieldnames
Else
'SCAnswer = MsgBox("SC Flags does not exist, do you wish to continue?", vbYesNo Or vbQuestion Or vbDefaultButton2)
'If SCAnswer = vbNo Then Exit Sub
End If
End Sub
Private Sub changefieldnames()
Dim db As Database
Dim tdf As TableDef
Dim n As Object
Set db = CurrentDb
Set tdf = db.TableDefs("tblSCFLAG_CHECKER")
For Each n In tdf.Fields
If n.Name = "?Person ID" Then n.Name = "Person ID"
Next n
Set tdf = Nothing
Set db = Nothing
End Sub
Your changefieldnames function requires two arguments but you give none in the call after
DoCmd.TransferText acImportDelim, "tblSCFLAG_CHECKER", "tblSCFLAG_CHECKER", cstrFolderF, True
changefieldnames
As a remark: you should try to debug your code instead of just posting an error without even stating where exactly the error occurs.
Related
I am exporting a recordset from an access query to an Excel Workbook. The export goes fine, and my syntax prompts the user for a filename/location just as I need. However, the file is not actually saved. Am I missing a step in the process or what code changes need to take place in order to have this function?
Sub ETE()
Dim ExcelApp As Object, wbOutput As Object, wsOutput As Object, bExcelOpened As Boolean
Dim db As DAO.Database, rs As DAO.Recordset, targetRow As Long
Dim targetPath As String, fd As FileDialog, Title As String, saveInfo As Variant
DoCmd.Hourglass True
Set ExcelApp = GetObject(, "Excel.Application")
If Err.Number <> 0 Then
Err.Clear
On Error GoTo Error_Handler
Set ExcelApp = CreateObject("Excel.Application")
bExcelOpened = False
Else
bExcelOpened = True
End If
On Error GoTo Error_Handler
ExcelApp.ScreenUpdating = False
ExcelApp.Visible = False
Set wbOutput = ExcelApp.Workbooks.Add()
Set wsOutput = wbOutput.Sheets(1)
Set db = CurrentDb
Set rs = db.OpenRecordset("qryTakeDataToExcel", dbOpenSnapshot)
With rs
If .RecordCount <> 0 Then
'Write the data to Excel
End If
End With
Set fd = Application.FileDialog(msoFileDialogSaveAs)
With fd
.AllowMultiSelect = False
.Title = "Select Save Location And File Name"
.InitialFileName = "File_" & Format(Now(), "mmddyyyy") & ".xlsx"
If .Show = True Then
wbOutput.SaveAs FileName:=fd.InitialFileName, FileFormat:=50
wbOutput.Close
End If
End With
End Sub
Your filedialog code is not working as expected, and because of that, you're not getting a valid file name and location.
If you want to return the file name picked, you should use .SelectedItems(1), not .InitialFileName. .InitialFileName sets an initial value and doesn't return the full path.
If .Show = True Then
wbOutput.SaveAs FileName:=.SelectedItems(1), FileFormat:=50
wbOutput.Close
End If
This would've probably been easier to catch if you'd have used a valid error handler. Use On Error GoTo 0 to use the default error handler.
I use this line of code:
Call SendTQ2XLWbSheetData("qryCustExportStyColOnlyDrop", "Data", "C:\Users\" & GetLogonName() & "\FWD Order Customer Export.xlsm")
To call and pass parameters to this Function:
Public Function SendTQ2XLWbSheetData(strTQName As String, strSheetName As String, strFilePath As String)
' strTQName is the name of the table or query you want to send to Excel
' strSheetName is the name of the sheet you want to send it to
' strFilePath is the name and path of the file you want to send this data into.
Dim rst As DAO.Recordset
Dim ApXL As Object
Dim xlWBk As Object
Dim xlWSh As Object
Dim fld As DAO.Field
Dim strPath As String
Const xlCenter As Long = -4108
Const xlBottom As Long = -4107
On Error GoTo err_handler
strPath = strFilePath
Set rst = CurrentDb.OpenRecordset(strTQName)
Set ApXL = CreateObject("Excel.Application")
Set xlWBk = ApXL.Workbooks.Open(strPath)
ApXL.Visible = True
Set xlWSh = xlWBk.Worksheets(strSheetName)
xlWSh.Visible = True
xlWSh.Activate
'clear any current size ranges
ApXL.Range("DataRange").Select
ApXL.Selection.ClearContents
xlWSh.Range("A1").Select
For Each fld In rst.Fields
ApXL.ActiveCell = fld.Name
ApXL.ActiveCell.Offset(0, 1).Select
Next
rst.MoveFirst
xlWSh.Range("A2").CopyFromRecordset rst
xlWSh.Visible = False
rst.Close
Set rst = Nothing
xlWBk.Close True
Set xlWBk = Nothing
ApXL.Quit
Set ApXL = Nothing
Exit_SendTQ2XLWbSheet:
Exit Function
err_handler:
DoCmd.SetWarnings True
MsgBox Err.Description, vbExclamation, Err.Number
Resume Exit_SendTQ2XLWbSheet
End Function
However, when I run it I keep receiving error 3061 Too Few Parameters - Expected 1. When I step through, it is this line of code causing the error:
Set rst = CurrentDb.OpenRecordset(strTQName)
However if I hover over the above line in debug, it is showing the name of the query (qryCustExportStyColOnlyDrop) I am passing.
What am I missing?
Thanks.
Most likely you have in your query a reference to a form control.
The value from this you must pass as a parameter if you run the query from code.
So, create a QueryDef object in your function, pass the parameter, and open your recordset from the QueryDef object.
I have built one database where the below audit trail code works flawlessly for both forms and sub-forms in Access 2010. But now that I am using it again in another database, I now get an error "Argument Not Optional" at the first Call. Why would this work in one database and not the other if they both have had the sub-form created the same exact way? I can not get the database to give me more information outside of the not so helpful error code. My best guess is that it has something to do with Sub TrainingEntryAuditChanges(IDField As String, UserAction As String, FormToAudit As Form) but I can't really tell. Like I said, it works in one database, but not this one for some reason. Any ideas?
Module Code:
***ABOVE CODE OMITTED INTENTIONALLY***
'Audit module code for employee training entry form's sub form
Sub TrainingEntryAuditChanges(IDField As String, UserAction As String, FormToAudit As Form)
On Error GoTo AuditChanges_Err
Dim cnn As ADODB.Connection
Dim rst As ADODB.Recordset
Dim ctl As Control
Dim datTimeCheck As Date
Dim strUserID As String
Set cnn = CurrentProject.Connection
Set rst = New ADODB.Recordset
rst.Open "SELECT * FROM tblAuditTrail", cnn, adOpenDynamic, adLockOptimistic
datTimeCheck = Now()
strUserID = Forms!Login!cboUser.Column(1)
'Get computer IP address
Dim myWMI As Object, myobj As Object, itm
Set myWMI = GetObject("winmgmts:\\.\root\cimv2")
Set myobj = myWMI.ExecQuery("Select * from Win32_NetworkAdapterConfiguration Where IPEnabled = True")
For Each itm In myobj
getMyIP = itm.IPAddress(0)
Next
'If user is editing an existing record:
Select Case UserAction
Case "EDIT"
For Each ctl In FormToAudit
If ctl.Tag = "Audit" Then
If Nz(ctl.Value) <> Nz(ctl.OldValue) Then
With rst
.AddNew
![DateTime] = datTimeCheck
![UserName] = strUserID
![UserComputer] = getMyIP
![FormName] = FormToAudit.Name
![Action] = UserAction
![RecordID] = FormToAudit.Controls(IDField).Value
![FieldName] = ctl.ControlSource
![OldValue] = ctl.OldValue
![NewValue] = ctl.Value
.Update
End With
End If
End If
Next ctl
'If a user is creating a new record:
Case Else
With rst
.AddNew
![DateTime] = datTimeCheck
![UserName] = strUserID
![UserComputer] = getMyIP
![FormName] = FormToAudit.Name
![Action] = UserAction
![RecordID] = FormToAudit.Controls(IDField).Value
.Update
End With
End Select
AuditChanges_Exit:
On Error Resume Next
rst.Close
cnn.Close
Set rst = Nothing
Set cnn = Nothing
Exit Sub
'If error then:
AuditChanges_Err:
Dim strError As String
Dim lngError As Long
Dim intErl As Integer
Dim strMsg As String
strError = Err.Description
lngError = Err.Number
intErl = Erl
strMsg = "Line : " & intErl & vbCrLf & _
"Error : (" & lngError & ")" & strError
MsgBox strMsg, vbCritical
Resume AuditChanges_Exit
End Sub
Before_Update code on subform:
Private Sub Form_BeforeUpdate(Cancel As Integer)
If Me.NewRecord Then
Call TrainingEntryAuditChanges("ID", "NEW") ***ERROR THROWN HERE***
Else
Call TrainingEntryAuditChanges("ID", "EDIT")
End If
End Sub
The Argument Not Optional is thrown when you are calling a routine with the incorrect number of arguments required for that routine.
In your code
Sub TrainingEntryAuditChanges(IDField As String, UserAction As String, FormToAudit As Form)
requires three arguments, IDField, UserAction, and FormToAudit.
However, in your Call
Call TrainingEntryAuditChanges("ID", "NEW") ***ERROR THROWN HERE***
you are only passing it two arguments: ID, NEW. You need to pass it a third argument (which looks like it will be the form). Try using me as the third argument to pass the 'current' form that is being updated and therefore calling the routine.
I've finished creating a database and it works perfectly on my computer. I'm using access 2013 and in my VBA code I have written error handler for each function/sub which I use in most databases.
However the users that it is designed for have Access run-time 2007 and every time i run it on their machine i get an un-trapped error "Execution of this application has stopped due to a run-time error".
Code for the command button.
Option Compare Database
Private Sub Command0_Click()
Dim ErrorStep As String
DoCmd.SetWarnings False
'-------------------------------------------------------------------------------------
' Procedure : Command0_Click
' Author : Chris Sparkes
' Date : 13/08/2013
'-------------------------------------------------------------------------------------
ErrorStep = "1 - Cleansing Records"
DoCmd.OpenQuery "qry1_3"
DoCmd.OpenQuery "qry4-7"
DoCmd.OpenQuery "qry9"
Call ExcelOutputReport
Exit_Command0_Click:
On Error GoTo 0
Exit Sub
Command0_Click_Error:
MsgBox "Error in procedure Command0_Click of VBA Document."
GoTo Exit_Command0_Click
On Error GoTo 0
End Sub
Public Function ExcelOutputReport()
Dim ErrorStep As String
DoCmd.SetWarnings False
'---------------------------------------------------------------------------------------
' Procedure : ExcelOutputReport
' Author : Chris Sparkes
' Date : 13/08/2013
'---------------------------------------------------------------------------------------
ErrorStep = "1 - Cleansing Records"
Dim dbLocal As DAO.Database
Dim tbloutput As DAO.Recordset
'DAO Declarations
Dim objExcel As New Excel.Application
Dim objWorkbook As Excel.Workbook
Dim objWorksheet As Excel.Worksheet
Dim IntCurrTask As Integer
Dim blurb As String
Set dbLocal = CurrentDb()
Set tbloutput = dbLocal.OpenRecordset("tbl_output")
Set objExcel = CreateObject("Excel.Application")
Set objWorkbook = objExcel.Workbooks.Open("G:\Enliven Sales Report\Envliven_Report_Template_1.xls")
Set objWorksheet = objWorkbook.Worksheets("Enliven")
objExcel.Visible = True
objWorkbook.Windows(1).Visible = True
tbloutput.MoveFirst
IntCurrTask = 2
Do While Not tbloutput.EOF
With objWorksheet
.Cells(IntCurrTask, 1).Value = tbloutput![CustomerOrderCode]
.Cells(IntCurrTask, 2).Value = tbloutput![CustomerCode]
.Cells(IntCurrTask, 3).Value = tbloutput![CustomerDescription]
.Cells(IntCurrTask, 4).Value = tbloutput![ItemCode]
.Cells(IntCurrTask, 5).Value = tbloutput![ItemDescription]
.Cells(IntCurrTask, 6).Value = tbloutput![DateOrderPlaced]
.Cells(IntCurrTask, 7).Value = tbloutput![CustomerDueDate]
.Cells(IntCurrTask, 8).Value = tbloutput![Quantity]
.Cells(IntCurrTask, 9).Value = tbloutput![ShippedQuantity]
End With
IntCurrTask = IntCurrTask + 1
tbloutput.MoveNext
Loop
tbloutput.Close
dbLocal.Close
DoCmd.SetWarnings True
Set tbloutput = Nothing
Set dbLocal = Nothing
Set objWorksheet = Nothing
Set objWorkbook = Nothing
Set objExcel = Nothing
Exit_ExcelOutputReport:
On Error GoTo 0
Exit Function
ExcelOutputReport_Error:
MsgBox "Error at in procedure ExcelOutputReport of VBA Document."
GoTo Exit_ExcelOutputReport
End Function
Has anyone got any ideas what may be causing this? The references should be fine as I'm using the same ones that I know have worked with different databases that I've made.
Thanks,
Chris
You have added error routines, but you did not activate them. At the beginning of your methods, add an On Error Goto statement:
Private Sub Command0_Click()
On Error Goto Command0_Click_Error
...
End Sub
Public Function ExcelOutputReport()
On Error Goto ExcelOutputReport_Error
...
End Sub
In your error routines, you should display (at least) the contents of Err.Description instead of a generic error message. Otherwise, you will have a really hard time tracking the source of errors. E.g.:
MsgBox "Error in procedure Command0_Click: " & Err.Description
I want to extract all the fields associated to my tables in my access database, to get an inventory of all the data objects. This has to populate a form I've created. I've copied an extract of code to determine whether an object in the database is a query or a table and I would like to alter this, if possible.
Any help will be appreciated
Option Compare Database
Option Explicit
Private Sub AddInventory(strContainer As String)
Dim con As DAO.Container
Dim db As DAO.Database
Dim doc As DAO.Document
Dim rst As DAO.Recordset
Dim intI As Integer
Dim strType As String
Dim varRetval As Variant
On Error GoTo HandleErr
' You could easily modify this, using the
' OpenDatabase() function, to work on any database,
' not just the current one.
varRetval = SysCmd(acSysCmdSetStatus, _
"Retrieving " & strContainer & " container information...")
Set db = CurrentDb
Set con = db.Containers(strContainer)
Set rst = db.OpenRecordset("zstblInventory")
For Each doc In con.Documents
If Not IsTemp(doc.Name) Then
' Handle the special queries case.
' Tables and queries are lumped together
' in the Tables container.
If strContainer = "Tables" Then
If IsTable(doc.Name) Then
strType = "Tables"
Else
strType = "Queries"
End If
Else
strType = strContainer
End If
rst.AddNew
rst("Container") = strType
rst("Owner") = doc.Owner
rst("Name") = doc.Name
rst("DateCreated") = doc.DateCreated
rst("LastUpdated") = doc.LastUpdated
rst.Update
End If
Next doc
ExitHere:
If Not rst Is Nothing Then
rst.Close
Set rst = Nothing
End If
Exit Sub
HandleErr:
MsgBox Err.Number & ": " & Err.Description, , _
"AddInventory"
Resume ExitHere
End Sub
Private Sub RebuildInventory()
On Error GoTo HandleErr
DoCmd.Hourglass True
Me.lstInventory.RowSource = ""
Call CreateInventory
Me.lstInventory.RowSource = "SELECT ID, Container, Name, " & _
"Format([DateCreated],'mm/dd/yy (h:nn am/pm)') AS [Creation Date], " & _
"Format([lastUpdated],'mm/dd/yy (h:nn am/pm)') AS [Last Updated], " & _
"Owner FROM zstblInventory ORDER BY Container, Name;"
ExitHere:
DoCmd.Hourglass False
Exit Sub
HandleErr:
Resume ExitHere
End Sub
Private Sub CreateInventory()
If (CreateTable()) Then
' These routines use the status line,
' so clear it once everyone's done.
Call AddInventory("Tables")
Call AddInventory("Forms")
Call AddInventory("Reports")
Call AddInventory("Scripts")
Call AddInventory("Modules")
Call AddInventory("Relationships")
' Clear out the status bar.
Call SysCmd(acSysCmdClearStatus)
Else
MsgBox "Unable to create zstblInventory."
End If
End Sub
Private Function CreateTable() As Boolean
' Return True on success, False otherwise
Dim qdf As DAO.QueryDef
Dim db As DAO.Database
Dim strSQL As String
On Error GoTo HandleErr
Set db = CurrentDb()
db.Execute "DROP TABLE zstblInventory"
' Create zstblInventory
strSQL = "CREATE TABLE zstblInventory (Name Text (255), " & _
"Container Text (50), DateCreated DateTime, " & _
"LastUpdated DateTime, Owner Text (50), " & _
"ID AutoIncrement Constraint PrimaryKey PRIMARY KEY)"
db.Execute strSQL
' If you got here, you succeeded!
db.TableDefs.Refresh
CreateTable = True
ExitHere:
Exit Function
HandleErr:
Select Case Err
Case 3376, 3011 ' Table or Object not found
Resume Next
Case Else
CreateTable = False
End Select
Resume ExitHere
End Function
Private Function IsTable(ByVal strName As String)
Dim tdf As DAO.TableDef
Dim db As DAO.Database
On Error Resume Next
' Normally, in a function like this,
' you would need to refresh the tabledefs
' collection for each call to the function.
' Since this slows down the function
' by a very large measure, this time,
' just Refresh the collection the first
' time, before you call this function.
Set db = CurrentDb()
' See CreateTable().
'db.Tabledefs.Refresh
Set tdf = db.TableDefs(strName)
IsTable = (Err.Number = 0)
Err.Clear
End Function
Private Function IsTemp(ByVal strName As String)
IsTemp = Left(strName, 7) = "~TMPCLP"
End Function
Private Sub cmdCreateInventory_Click()
Call RebuildInventory
End Sub
Private Sub Detail0_Click()
End Sub
Private Sub Form_Open(Cancel As Integer)
Call RebuildInventory
End Sub
Check out the source code in this answer. You should be able to modify it to do what you need. Unless, as Remou pointed out in his comment, you are working with a pre-2000 version of Access.