Not sure this is possible, but it seems like it should be doable.... it is 2013 after all! And some forum posts I found suggest it is, but I have not been successful in getting it to work...
I have an Access 2010 db with a macro that downloads files from 3 different web sites and then proceeds to import the data and process it. It runs for 1hr and 17 mins.
I want to schedule this macro to run at 4am so it is all done and dusted by coffee time and work start 8am... So I created a VBScript to run this, which will then be placed into the Task Scheduler for the desired time.
It is a single user DB, my use only on my PC.
I have done some research but I cannot seem to get this working. Here's what I have so far:
Macro inside "Main" module in Access 2010 inside of "Pricing Model.accdb":
Public Sub Download_And_Import()
ProcStep = ""
ExecStep = 1
DoCmd.SetWarnings False
'Empty the Execution Progress table
DoCmd.RunSQL "DELETE * FROM EXECUTION_PROGRESS"
Call Update_EXECUTION_PROGRESS(Format(Now(), "YYYY/MM/DD HH:MM:SS"), ExecStep, "Starting Download_Files Main Procedure...")
Call Download_Files.Download_Files
Call Update_EXECUTION_PROGRESS(Format(Now(), "YYYY/MM/DD HH:MM:SS"), ExecStep, "Finished Download_Files Main Procedure...")
Call Update_EXECUTION_PROGRESS(Format(Now(), "YYYY/MM/DD HH:MM:SS"), ExecStep, "Starting Import_Files Main Procedure...")
Call Import_Files.Import_Files
Call Update_EXECUTION_PROGRESS(Format(Now(), "YYYY/MM/DD HH:MM:SS"), ExecStep, "Finished Import_Files Main Procedure, closing application now...")
DoCmd.SetWarnings True
End Sub
I then created the following VBScript to run Access VBA Macro externally:
dim accessApp
set accessApp = createObject("Access.Application")
accessApp.OpenCurrentDataBase("G:\Pricing DB\Pricing Model.accdb")
accessApp.Run "Download_And_Import"
accessApp.Quit
set accessApp = nothing
I get the message "Illegal function call, Line 4" which is the step:
accessApp.Run "Download_And_Import"
Any ideas / help is highly appreciated! Thanks in advance!
M
I don't see anything wrong with the VBScript itself. I copied your code, changed the db file name and procedure name, and it ran without error. So my guess is the VBScript error "bubbles up" from Access when it tries to run the procedure.
Open Pricing Model.accdb in Access, go to the Immediate window (Ctrl+g), type in the following line and press Enter
Application.Run "Download_And_Import"
If that throws an error you surely have a problem in that procedure. If it doesn't throw an error, you could still have trouble running it from a scheduled task if the procedure requires Windows permissions and you haven't set the task to run under your user account.
If you need to troubleshoot the procedure, first add Option Explicit to the module's Declarations section. Then run Debug->Compile from the VB Editor's main menu. Fix anything the compiler complains about. Repeat until the code compiles without error.
Disable DoCmd.SetWarnings False during troubleshooting because it suppresses information. Consider whether substituting the DAO Database.Execute method for DoCmd.RunSQL will allow you to avoid turning SetWarnings off at all.
You could try including the ProjectName:
accessApp.Run "[Pricing Model].Download_And_Import"
The project-name defaults to the database name, and square-brackets are needed because of the spaces.
This shouldn't be necessary, because your Sub is Public, but worth a try.
I ran into the same (msg) issue the script was OK! Problem was i was testing the script with the database opened as I was in development mode, as soon i closed the Database the script worked well.Close the database before testing the script.
Related
MS Access (2007 - 2016) in Office 365
I'm trying/failing to capture a value passed into Access from the command line using the Command() function in a Macro. THis is the macro that I created with the wizard...
If Command()="Update_Burndown_Metrics" Then
RunSQL
SQL Statement insert .... blah, blah
End If
No error when I save the macro, but when I run...
The expression you entered has a function name that Microsoft Access can't find
If I replace the...
If Command()="Update_Burndown_Metrics"
with
If 1=1
It runs fine. IOW, it's not the SQL. It's the "Command() function that it can't find.
I got the idea to use Command() from Opening Microsoft Access with parameters . Doesn't seem to work for me. But that coding approach is also confirmed here... http://www.utteraccess.com/wiki/Command-Line_Switches . So I think it's something else.
Eventually, I would like to pass the Update_Burndown_Metrics arg using /cmd on the command line.
Why can't it find Command() as a valid function ? Is it a scoping thing? Do I have to give Command() context somehow, maybe with some sort of prefix ?
I can't seem to reproduce the issue that you are describing, though, I am using an earlier version of MS Access, and so there may be some differences in the behaviour of this function.
The Command function should be globally accessible, even outside of VBA (it can be referenced by the ControlSource property of a text box, for example), and so this isn't an issue of scope.
I do observe from the Office 365 documentation, that the Command function is being invoked without the use of parentheses in the sample VBA Sub provided; therefore it may be worth you trying your code without including such parentheses, e.g.:
If Command = "Update_Burndown_Metrics" Then
MsgBox "Test succeeded."
Else
MsgBox "Test failed."
End If
The workaround I created is to create a function in vba that gets and returns the command...
Public Function GetCommand() As String
GetCommand = Command()
End Function
Then...
If GetCommand() = "Update_Burndown_Metrics" Then ...
I have a pass through query built in Teradata set to export data to an Excel spreadsheet. I'm trying to automate it, but when I run the macro or open the query, a window pops up asking for the data source. I have an ODBC connection created and I'm thinking there has to be a way to make the macro pass the data source name so it will run without interaction.
Edit: Adding Macro as requested
Function AutoExec()
On Error GoTo AutoExec_Err
DoCmd.OutputTo acOutputQuery, "Performance Interval Data", "ExcelWorkbook(*.xlsx)", _
"filepath\filename.xlsx", False, "", , acExportQualityPrint
DoCmd.Quit acExit
AutoExec_Exit:
Exit Function
AutoExec_Err:
MsgBox Error$
Resume AutoExec_Exit
End Function
Couple of concerns, (can't validate any of this right now as I do not currently have access to Access for testing), but it looks like:
You're trying to OutputTo a query, to the best of my knowledge that
is not feasible.
Your file path is setup as filepath\filename.xlsx unless that is the actual location and name of your Excel sheet, something seems
wrong there to me.
I don't really think this macro relates to an ODBC of any sort in its current state.
But, you should at least start with fixing the filepath issue. That should be the full path to your Excel file and the full name of the file as well. (i.e. C:\TEMP\TestExcelSheet.xlsx)
All that being said, you may want to just go with something like this (although its a little difficult to tell if this is what you actually want or not):
'Export Excel file from Query
DoCmd.TransferSpreadsheet acExport, , "acOutputQuery", _
"C:\TEMP\TestExcelSheet.xlsx", True
NOTE: "acOutputQuery" should be the actual name of your passthrough query, "C:\TEMP\TestExcelSheet.xlsx" would be your destination path, and True adds the query's headers into the sheet, False to ignore the headers.
Up to a couple days ago I had this very simple script running just fine;
Set appAccess = CreateObject("Access.Application")
appAccess.OpenCurrentDatabase "\\mynetwork\myconnection\mydatabase.accdb"
appAccess.DoCmd.OpenQuery "Update", acViewNormal, acEdit
Set appAccess = Nothing
Unfortunately now, all of a sudden, throws me an error message:
I've tried Googling some solutions but it seems that the error code 800A09C5 is rather uncommon.
The interesting part is that this other code works fine, so I'm really confused as to why I'm getting the above error.
SET oAcc = CREATEOBJECT("Access.Application")
oAcc.OpenCurrentDatabase "\\mynetwork\myconnection\mydatabase.accdb"
oAcc.DoCmd.OutputTo acOutputTable, "PR_NOTES", "Excel97-Excel2003Workbook
(*.xls)", "\\mynetwork\OutputFiles\File_" & replace(FormatDateTime
(now,2),"/","-") & "at" & replace(FormatDateTime(now,4),":","-") &".xls", False, "",
, acExportQualityPrint
Any insight is appreciated.
This code line of:
appAccess.DoCmd.OpenQuery "Update", acViewNormal, acEdit
will not work for several reasons. First up the code constants of acViewNomral and code constant of acEdit are NOT part of vbScript, but are constants from Access. Vb scripting has NO idea what the value of these constants are. So you have to replace the constants with the actual values from Access. (so in the debug window in access you print out the constants by type in
? acViewNormal
And
? acEdit
Now a quick test shows above constants to be “0”, so you would replace the constants with a 0 (no quotes).
Next up your command is failing because you opening the query in EDIT mode – that mode is to edit and modify the query – not run the query.
Next up and a greater issue is when you use docmd. To execute a query, you will receive “dialog” boxes such as do you want to update all these rows yes/no – because of script and automation you will be un-able to click ok and answer yes to those prompts. You can change setwarnings, but most easy to just use the execute method.
So in the syntax of
appAccess.DoCmd.OpenQuery "Update"
should work – but then those nasty prompts such as "you are about to update xxx rows etc. will appear - and you can't answer those prompts in the script.
Better to use the execute method, and thus use
appAccess.currentdb.Execute "Update"
In a data validation form, I have a subroutine checking previously-entered data on a LostFocus event by ensuring that the release time (TimeReleased in table; Me.txtTimeReleased on form) is after the capture time (ObservationTime in table; Me.txtObservationTime on form). I'm using LostFocus rather than BeforeUpdate because the data were bulk-imported into the db and are now being error-checked.
My users keep getting a compile error (Compile Error: method or data member not found) upon tabbing out of the field this sub is attached to but I cannot reproduce the problem locally. The error occurs on this line:
If (Me.txtTimeReleased) <= (Me.ObservationTime) Then
and the part highlighted is '.txtTimeReleased'
Full code block:
Private Sub txtTimeReleased_LostFocus()
Dim badData As Variant
Dim resp As Variant
'Also check that time released is after time captured
If Not IsNull(Me.txtObservationTime) And Not IsNull(Me.txtTimeReleased) Then
If (Me.txtTimeReleased) <= (Me.ObservationTime) Then
resp = MsgBox("Release time must be after capture time." & vbCrLf & "Please double check this field's value: is it correct?", _
vbYesNo + vbExclamation + vbDefaultButton2, "Release Time Before Capture Time")
If resp <> vbYes Then badData = True
End If
End If
If badData = True Then
Me.cmbTaxonId.SetFocus 'set focus away so can set focus back
With Me.txtTimeReleased
.SetFocus
.SelStart = 0
.SelLength = 10
End With
End If
End Sub
Other things to note:
Both the table field and form control are formatted as 'Short Time' (24-hour time)
There is an input mask on that form control for 24-hour time; I use input masks very rarely and thus aren't familiar with them--perhaps the input mask could be causing the problem?
There are similar LostFocus subs on most of the other controls which do not produce this (or any other) error
Things I've tried:
Checking spelling
Fully decompling and recompiling the code: starting with shift, compact and repair with shift, open with /decompile flag while holding shift, compact and repair with shift, re-open with shift, and finally compile (without error)
Replacing the form in their database with one that works fine for me on the same data
Google
Things that seem odd to me:
I can't reproduce the error locally.
The error is triggering on the second instance of
Me.txtTimeReleased rather than the first: it has already passed a Not
IsNull(Me.txtTimeReleased) check.
The fact that it's a compile error: could that be masking something else?
Thanks for your time, and please let me know if there's any additional information that would be useful. Any thoughts are most welcome!
You checked for Null txtObservationTime and txtTimeReleased, but compare then txtTimeReleased and ObservationTime. Maybe solution is:
If Not IsNull(Me.txtObservationTime) And Not IsNull(Me.txtTimeReleased) Then
If (Me.txtTimeReleased) <= (Me.txtObservationTime) Then
Opening the .mdb with the /decompile flag is one of the first things I would have suggested, but you said you already tried that.
Here's another undocumented trick to deal with "hidden" compile problems that get baked in by VBA behind the scenes:
First, make a backup copy of your .mdb just to be safe (this is, after all, an undocumented technique).
Then, save your form to a text file using SaveAsText:
SaveAsText acForm, "MyFormName", "C:\MyFormName.txt"
Finally, re-load your form using the equally undocumented LoadFromText:
LoadFromText acForm, "MyFormName", "C:\MyFormName.txt"
Compile.
Compact.
Repair.
Hope for the best.
Good luck.
I suggest you use variables:
intThat = Me.txtTimeReleased
If intThis <= intThat Then
Try using ! instead of a dot:
intThat = Me!txtTimeReleased
If intThis <= intThat Then
And now, the answer that worked for me last week:
Comment out the offending line.
Run a compile that is successful.
Restore the offending line.
The compile may work now. Don't ask me why.
I have a program that uses a Microsoft Access database for its back-end. I need to have some VBA code (that calls a web service) execute whenever specific tables/fields are updated by the program. I see this working just like a trigger in SQL Server.
Is it possible to monitor for and act upon changes like this in Access?
Update
The program in question does not run inside of Access (i.e. not a VBA app), it simply uses an MDB file as its back-end storage. Unfortunately I don't have access to the program's code as it is a closed third party application.
This question is old, but the answers are no longer correct. Access 2010 added data macro events that can be run when data is inserted, updated or deleted. The following events are available while using either the table datasheet view or table design view (events are attached directly to table and not through the form macro button):
After Delete Macro Event
After Insert Macro Event
After Update Macro Event
Before Change Macro Event
Before Delete Macro Event
More information is located here:
https://msdn.microsoft.com/en-us/library/office/dn124692.aspx
https://support.office.com/en-us/article/Create-a-data-macro-b1b94bca-4f17-47ad-a66d-f296ef834200
Access the GUI environment vs Jet the database format are separate things.
If you are using an Access database as a backend - it's just the JET functionality you can work with. Access the GUI (which includes VBA) runs on the client machine and there is no automated trigger functionality.
If your program is the only program using the Access file, then it should know when a table is being updated and execute some code in place of a trigger.
Otherwise, you need another application/service running all the time that is checking the access file tables for updates (maybe you have some update_date type of field on your tables?).
When an Access database file gets written to, it's date/time stamp changes. I suppose you could try using a file monitor to detect changes to the file, and then examine the file to see what has changed.
It would help if the Access database has LastModified date/time columns in the tables.
If you are using Jet (i.e. the data is stored in an MDB file back end) then the only places you can run code would be in the After Update Event in a Form. The problem here of course is if the data is changed without using the form then the event will not fire.
If you are using MS Access 2003 then to run a Web Service you can download the Microsoft Office 2003 Web Services Toolkit Click Here to download
If you are stuck in VBA it gets a little rough. One way to go would be to have a form with timer in it (you could have it open invisibly. The timer could check the table, say once a minute (or whatever interval seems suitable) for changes in record count, and verify the table still exists. (code below)
But personally this isn't what I would recommend that you do. Access is notorious for corruption. When used as a simple back end you are fairly safe most of the time, but to have it running a monitor, means the file is always open. This is basically playing Russian Roulette with your database. At minimum I would link to your database from another Access file and monitor the linked tables, that way if your monitor crashes, you don't take the production DB with you. Finally, make sure that you don't query too often, as I'd hate to see you be the sole cause of the website timing out:)
Option Explicit
Private m_lngLstRcrdCnt_c As Long
Private Sub Form_Open(Cancel As Integer)
Const lngOneMinute_c As Long = 60000
Me.TimerInterval = lngOneMinute_c
End Sub
Private Sub Form_Timer()
Const strTblName_c As String = "Foo"
Const strKey_c As String = "MyField1"
Dim rs As DAO.Recordset
Dim lngRcrdCnt As Long
If TableExists(strTblName_c) Then
Set rs = CurrentDb.OpenRecordset("SELECT Count(" & strKey_c & ") FROM " & strTblName_c & ";", dbOpenSnapshot)
If Not rs.EOF Then lngRcrdCnt = Nz(rs.Fields(0&).Value, 0&)
rs.Close
If lngRcrdCnt <> m_lngLstRcrdCnt_c Then
m_lngLstRcrdCnt_c = lngRcrdCnt
'Number of records changed, do something.
End If
Else
'Table is deleted, do something.
m_lngLstRcrdCnt_c = -1
End If
End Sub
Private Function TableExists(ByVal name As String) As Boolean
Dim tdf As DAO.TableDef
On Error Resume Next
Set tdf = CurrentDb.TableDefs(name)
If LenB(tdf.name) Then 'Cheap way to catch broken links.
Set SafeGetTable = tdf
End If
End Function