I have got vba which I am running from a batch that starts a macro to execute them, I am trying to close down access once all the functions have finished however making a new function and placing "Application.Quit" is closing the application before the functions have finished.
Anyone have any ideas?
Thanks,
Simon
Edit:
Public Function finish()
Application.Quit
End Function
Put a timer loop in your code to put the DB to sleep and give it time for the functions to run.
First, put this just under the Option Compare or Option Explicit line in any MODULE (NOTE: it must be in a proper module, and not a form's module):
Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Then your function should look like this:
Public Function finish()
Dim X as Integer
For X = 1 To 10
Sleep 1000
DoEvents
Next X
Application.Quit
End Function
Honestly, I don't understand what exactly you are doing so that your application closes before all your functions have finished.
If you want to execute some functions and then close the app, there are two ways how you can do it:
Put several RunCode actions in the macro, each one executing one of your functions and the last one executing Application.Quit.
Write a "runner" function that executes all the others and then quits:
Public Function F1()
'do stuff
End Function
Public Function F2()
'do stuff
End Function
Public Function Finish()
Application.Quit
End Function
'execute this function from the macro:
Public Function Runner()
F1
F2
Finish 'or directly call "Application.Quit" here instead
End Function
No matter which of these ways you choose, Access executes the functions in the specified order, one after the other...and it shouldn't close before everything is finished!
If it does, I suppose you're doing something different.
As already suggested by shahkalpesh in his comment - show us more code, then.
Related
Let me start by saying I am not at all familiar with Access or VBA. However, I am the IT guy and at some point someone created an MS Access database that does a thing and now I have to support it.
We have a database that upon opening deletes any old data and re-runs the external query that makes this application work. Occasionally whatever state the program exited out in that table already does not exist. This causes MS Access to hang on the delete line and I have to run the debugger, comment out the DoCmd.DeleteObject line, re run, and then un-comment the line to let the user continue with their day.
I want to add in some sort of conditional statement, but anything I've been able to google in terms of If...Then statements or 'TableExist' type functions always causes an error to be thrown that I haven't defined the function. My best guess is I'm nesting this incorrectly or I'm not calling some sort of external function correctly, but as I said my VBA knowledge is extremely limited.
This code executes on startup:
Public Function Startup() As Integer
DoCmd.Close acForm, "soLookup"
DoCmd.DeleteObject acTable, "sales_order"
DoCmd.RunSavedImportExport "Import-sales_order"
DoCmd.OpenForm "soLookup"
End Function
Its the
DoCmd.DeleteObject acTable, "sales_order"
Line that causes things to fail.
I've attempted to restructure this several times based on several examples I had found, but I'll only bother with one below
Public Function Startup() As Integer
DoCmd.Close acForm, "soLookup"
If TableExists("sales_orders") Then
DoCmd.DeleteObject acTable, "sales_orders"
Else
'Do nothing
End If
DoCmd.RunSavedImportExport "Import-sales_order"
DoCmd.OpenForm "soLookup"
End Function
Nothing I seem to try seems to give me any result other than an error of some sort. All I want to do is add a conditional statement to this 'Startup' bit that checks if the "sales_order" table even if exists, and if it doesn't, then to just move on to the next comment and forget the DoCmd.DeleteObject. How can I achieve this functionality?! Thanks!
The TableExists function is not a standard function in Access. You need to define it yourself.
There are two main ways to define such a function, by trying and error trapping, or by iterating through all tables and checking names.
Way 1 (error trapping):
Public Function TableExists(TableName As String) As Boolean
On Error Resume Next
TableExists = CurrentDb.TableDefs(TableName).Name = TableName
End Function
Way 2 (iterating collection):
Public Function TableExists(TableName As String) As Boolean
Dim td As DAO.TableDef
For Each td In CurrentDb.TableDefs
If td.Name = TableName Then
TableExists = True
Exit Function
End If
Next
End Function
Define either of these functions in a public module, and your last approach should work
I will instead modify the query to import the source data into a new table (sales_orders), which will overwrite existing data when the query runs and so I don't have to delete the table and have additional check for TableExists
I'm trying to trigger the button that will handle the extraction of the selected document once the user double click the document listed in the form like the screen shot below
So I went in the properties and configured:
Private Sub ParamName_DblClick(Cancel As Integer)
call Forms!FormName.Extract_Click
End Sub
With no success , I also tried :
Private Sub ParamName_DblClick(Cancel As Integer)
Forms!FormName.Extract_Click
End Sub
Inside the form , the sub is declared as below :
Private Sub Extract_Click()
Dim dbs As DAO.Database
//.... //do work
end sub
What I am doing wrong ?
Short answer: You can't, and even if you could (or in contexts where you can), you shouldn't.
Longer answer: don't implement any logic directly in event handlers. Invoke the logic from the handlers:
Private Sub SomeControl_SomeEvent()
DoTheThing
End Sub
Public Sub DoTheThing()
'do stuff
End Sub
That Public member can live in a standard module, and thus can be invoked by anything anywhere - from a button on some form, or from another button on another form, or whatever you need to invoke it from.
But don't invoke event handler procedures yourself. Event handlers handle events, they're invoked by the VBA runtime: leave it that way and live prosper.
I am new to vbscript and trying to use the below code with a Function and then a Sub Procedure. I am confused as to why I have to "call" the function as it should itself return the value without calling the function. Please see the below pieces of code - one with Function and the other one with Sub Procedure.
Function -
Systemutil.Run"C:\Program Files\Internet Explorer\iexplore.exe","www.gmail.com"
Function tester()
Set tester=Description.Create
tester=Browser("title:=Gmail").Page("title:=Gmail").WebButton("html id:=next").GetROProperty("Name")
print tester
End Function
Call tester
If I don't call the function, it doesn't return anything.
I have used function name as a variable to output the value.
Sub Procedure-
Systemutil.Run"C:\Program Files\Internet Explorer\iexplore.exe","www.gmail.com"
Sub tester()
Set X=Description.Create
X=Browser("title:=Gmail").Page("title:=Gmail").WebButton("html id:=next").GetROProperty("Name")
print X
End Sub
Call tester
My question is why doesn't the first script work without calling the Function.
The first part of your code only defines your function. It doesn't execute the code in it yet.
Whether it returns a value or not is irrelevant. If you want the code in your function or sub to execute, you must call it.
I have written some sql queries, some sub procedures and have some saved imports.
Now I am trying to use the Macro Design in Access to provide a run button which will run these objects sequentially.
However I dont see any command for running a sun procedure, I can see OpenVisualBasicModule and Runcode.
OpenVisualBaicModule is only opening my sub procedures and Run Code is asking for a function only.
I created a function with all the sub procedure call inside. But thats not working while individually all of them work.
Any suggestion what to do.
Make sure your VBA code is placed inside a Function (not a SUB, that won't work).
Create your function like:
Function DoSomething()
'Do your stuff
End Function
Or if you want to execute a Sub, just create a Function that calls your sub, like:
Function DoSomething()
Call YourSub()
End Function
Inside the Macro Design, add the 'RunCode' action (Macro Commands > RunCode) and call your function:
DoSomething()
And voila, you're done.
As you are already using code, the Macro seems unnecessary. In the Property Sheet for the Button, find the OnClick row and type in there:
=YourFunctionName()
(this also has to be a Function, not a Sub-procedure; this is a peculiarity of Access)
In your function you can use DoCmd to call any Macro Actions that you are using in your current Macro. Throw a MsgBox as the first line of your function to check that it is running.
You may be less familiar with the code, than a macro, but you will be able to add good comments to it, step-through and debug the code, use sensible error-handling - far easier than you can with a Macro.
I'm trying to create my own toolbar button (commandbarbutton) in Access VBA Editor. Its a button to run a procedure in a public module called "RunTests". I made the button like so:
Public Sub CreateToolbar()
Dim cmdBar As CommandBar
Dim cmdButton As CommandBarButton
Set cmdBar = Application.VBE.CommandBars.Add("Run Tests")
Set cmdButton = cmdBar.Controls.Add(msoControlButton)
cmdButton.FaceId = 558
cmdButton.DescriptionText = "Run the tests"
cmdButton.Caption = "Run Tests"
cmdButton.OnAction = "RunTests"
cmdButton.Enabled = True
cmdButton.Style = msoButtonIconAndCaption
cmdBar.Visible = True
End Sub
I ran the procedure as a test. And it created the button just fine. But the "click" action doesn't respond. The button doesn't seem to be clickable. Does anybody know why?
Edit: Found the solution: http://support.microsoft.com/default.aspx?scid=kb;en-us;Q280607 - I will answer my own question as soon as I can to close it.
The key for me was to make "RunTests" a public subroutine. When it was private it didn't work.
cmdButton.OnAction = "=RunTests()"
public sub RunTests()
private sub RunTests() does not work.
Found the solution - To make it work you have to implement the workaround described here: http://support.microsoft.com/default.aspx?scid=kb;en-us;Q280607
Unfortunately I tried to be fancy and define my button and menus in a class. The OnAction subroutine was never executed while it was defined locally as part of the class. It would only execute when defined outside of the class definition.
When I redefined my class to be just a module containing many subs and functions, then the OnAction subroutine was executed. Might have to do with scope and visibility or that I didn't have the OnAction semantics correct for a call to a class method. Bottom line is to define the button/menu/widget in a module and it will be much easier. (I was using Excel VBA but I think Access and Excel VBA are the same.)