Running a database in run time version brings up an error - ms-access

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

Related

Save Excel Workbook From Access VBA

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.

Run-time error '3061'. Too few parameters. Expected 1 Access 2013

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.

VBA Audit Trail code throwing Argument Not Optional error

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.

Passing Functions through Sub Procedure

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.

MS Access: How to bypass/suppress an error?

I'm executing a query like this
select field from table;
In that query, there is a loop running on many tables. So, if the field is not present in a table I get a
Runtime Error 3061
How can I by pass this error such as that on this error flow should go to another point?
This is the code I have recently after going through this forum.
Option Explicit
Private Sub UpdateNulls()
Dim rs2 As DAO.Recordset
Dim tdf As DAO.TableDef
Dim db As Database
Dim varii As Variant, strField As String
Dim strsql As String, strsql2 As String, strsql3 As String
Dim astrFields As Variant
Dim intIx As Integer
Dim field As Variant
Dim astrvalidcodes As Variant
Dim found As Boolean
Dim v As Variant
Open "C:\Documents and Settings\Desktop\testfile.txt" For Input As #1
varii = ""
Do While Not EOF(1)
Line Input #1, strField
varii = varii & "," & strField
Loop
Close #1
astrFields = Split(varii, ",") 'Element 0 empty
For intIx = 1 To UBound(astrFields)
'Function ListFieldDescriptions()
Dim cn As New ADODB.Connection, cn2 As New ADODB.Connection
Dim rs As ADODB.Recordset, rs3 As ADODB.Recordset
Dim connString As String
Dim SelectFieldName
Set cn = CurrentProject.Connection
SelectFieldName = astrFields(intIx)
Set rs = cn.OpenSchema(adSchemaColumns, Array(Empty, Empty, Empty, SelectFieldName))
'Show the tables that have been selected '
While Not rs.EOF
'Exclude MS system tables '
If Left(rs!Table_Name, 4) <> "MSys" Then
strsql = "Select t.* From [" & rs!Table_Name & "] t Inner Join 01UMWELT On t.fall = [01UMWELT].fall Where [01UMWELT].Status = 4"
End If
Set rs3 = CurrentDb.OpenRecordset(strsql)
'End Function
strsql2 = "SELECT label.validcode FROM variablen s INNER JOIN label ON s.id=label.variablenid WHERE varname='" & astrFields(intIx) & "'"
Set db = OpenDatabase("C:\Documents and Settings\Desktop\Codebook.mdb")
Set rs2 = db.OpenRecordset(strsql2)
With rs2
.MoveLast
.MoveFirst
astrvalidcodes = rs2.GetRows(.RecordCount)
.Close '
End With
With rs3
.MoveFirst
While Not rs3.EOF
found = False
For Each v In astrvalidcodes
If v = .Fields(0) Then
found = True
Debug.Print .Fields(0)
Debug.Print .Fields(1)
Exit For
End If
Next
If Not found Then
msgbox "xxxxxxxxxxxxxxxx"
End If
End If
.MoveNext
Wend
End With
On Error GoTo 0 'End of special handling
Wend
Next intIx
End Sub
I'm getting a
Type Mismatch Runtime Error
in Set rs3 = CurrentDb.OpenRecordset(strsql)
I guess I'm mixing up ado and dao but I'm not certainly sure where it is.
Use the On Error statement that VBA supplies:
Sub TableTest
On Error Goto TableTest_Error
' ...code that can fail... '
Exit Sub
:TableTest_Error
If Err.Number = 3061 Then
Err.Clear()
DoSomething()
Else
MsgBox Err.Description ' or whatever you find appropriate '
End If
End Sub
Alternatively, you can switch off automatic error handling (e.g. breaking execution and displaying an error message) on a line-by-line basis:
Sub TableTest
' ... fail-safe code ... '
On Error Resume Next
' ...code that can fail... '
If Err.Number = 3061 Then
Err.Clear()
DoSomething()
Else
MsgBox Err.Description
End If
On Error Goto 0
' ...mode fail-safe code... '
End Sub
There are these statements available:
On Error Resume Next switches off VBA-integrated error handling (message box etc.) completely, execution simply resumes on the next line. Be sure to check for an error very early after you've used that, as a dangling error can disrupt the normal execution flow. Clear the error as soon as you caught it to prevent that.
On Error Goto <Jump Label> resumes execution at a given label, primarily used for per-function error handlers that catch all sorts of errors.
On Error Goto <Line Number> resumes at a given line number. Stay away from that, it's not useful, even dangerous.
On Error Goto 0 it's close cousin. Reinstates the VBA integrated error management (message box etc.)
EDIT
From the edited qestion, this is my proposal to solve your problem.
For Each FieldName In FieldNames ' assuming you have some looping construct here '
strsql3 = "SELECT " & FieldName & " FROM table"
On Error Resume Next
Set rs3 = CurrentDb.OpenRecordset(strsql3)
If Err.Number = 3061 Then
' Do nothing. We dont care about this error '
Err.Clear
Else
MsgBox "Uncaught error number " & Err.Number & " (" & Err.Description & ")"
Err.Clear
End If
On Error GoTo 0
Next FieldName
Be sure to clear the error in any case before you go on with a loop in the same Sub or Function. As I said, a dangling error causes code flow to become unexpected!
Rather than trapping the error, why not use the TableDefs to check for the field or use a mixture of ADO and DAO? ADO Schemas can provide a list of tables that contain the required field:
Function ListTablesContainingField()
Dim cn As New ADODB.Connection, cn2 As New ADODB.Connection
Dim rs As ADODB.Recordset, rs2 As ADODB.Recordset
Dim connString As String
Dim SelectFieldName
Set cn = CurrentProject.Connection
SelectFieldName = "Fall" 'For tksy '
'Get names of all tables that have a column called 'ID' '
Set rs = cn.OpenSchema(adSchemaColumns, _
Array(Empty, Empty, Empty, SelectFieldName))
'Show the tables that have been selected '
While Not rs.EOF
'Exclude MS system tables '
If Left(rs!Table_Name, 4) <> "MSys" Then
' Edit for tksy, who is using more than one forum '
If tdf.Name = "01UMWELT" Then
strSQL = "Select * From 01UMWELT Where Status = 5"
Else
strSQL = "Select a.* From [" & rs!Table_Name _
& "] a Inner Join 01UMWELT On a.fall = 01UMWELT.fall " _
& "Where 01UMWELT.Status = 5"
End If
Set rs2 = CurrentDb.OpenRecordset(strSQL)
Do While Not rs2.EOF
For i = 0 To rs2.Fields.Count - 1
If IsNull(rs2.Fields(i)) Then
rs2.Edit
rs2.Fields(i) = 111111
rs2.Update
End If
Next
rs2.MoveNext
Loop
End If
rs.MoveNext
Wend
rs.Close
Set cn = Nothing
End Function
Try this:
On Error Resume Next ' If an error occurs, move to next statement.
...statement that tries the select...
If (Err <> 0) Then
...act on error, or simply ignore if necessary...
End If
On Error Goto 0 ' Reset error handling to previous state.