I am using Access 2013. I searched a variety of online resources. I thought SendKeys was the answer.
Once per quarter, my client will receive an updated Access database. All table names should be identical each quarter. I want them to run a macro, specify the location of the new file, and then the macro updates the linked tables and executes all other queries I’ve built (I have the last part working).
The part I have not be able to get working is to check the “Always prompt for a new location box”, check the “select all” box and click OK (and then click OK and close after the client specifies the new file location). Below is the code I am using.
Function Open_LinkedTableManager()
DoCmd.RunCommand acCmdLinkedTableManager 'this step works fine
'the following lines, up until Application.Run don’t appear to be
'doing anything. The code will run, but I have to manually execute
'each of the steps I am trying to automate before it gets to the
'Application.Run step
SendKeys "%a", True ' also tried SendKeys "%(a)" and "+a", "a", etc,
'True; Alt+a checks the "Always prompt for a new location box”
SendKeys "%s", True ' also tried SendKeys "%(s)", True; Alt+s checks the "select all" 'box
SendKeys "{Enter}" ' then user specifies location of new file
SendKeys "{Enter}" ' click OK after receiving message "All selected linked tables 'were successfully refreshed"
' click Close to close linked table manager and proceed to the next step below (not 'sure how to do this)
Application.Run ("Update_all_queries") ' this is working;
End Sub
If sending to yourself then try DoEvents after each sendkey.
DoEvents Function
Yields execution so that the operating system can process other events.
Syntax
DoEvents( )
Remarks
The DoEvents function returns an Integer representing the number of open forms in stand-alone versions of Visual Basic, such as Visual Basic, Professional Edition. DoEvents returns zero in all other applications.
DoEvents passes control to the operating system. Control is returned after the operating system has finished processing the events in its queue and all keys in the SendKeys queue have been sent.
DoEvents is most useful for simple things like allowing a user to cancel a process after it has started, for example a search for a file. For long-running processes, yielding the processor is better accomplished by using a Timer or delegating the task to an ActiveX EXE component.. In the latter case, the task can continue completely independent of your application, and the operating system takes case of multitasking and time slicing.
Caution Any time you temporarily yield the processor within an event procedure, make sure the procedure is not executed again from a different part of your code before the first call returns; this could cause unpredictable results. In addition, do not use DoEvents if other applications could possibly interact with your procedure in unforeseen ways during the time you have yielded control.
I have solved your dilemma. All I needed to do was place the sendkey statements before the call to to the linked tabled manager. See Below - Worked Great For Me! I was also able to add all of the commands in your order and they worked great. Good luck, hope this helped. Let me know. Adam
PS: If you have many tables to change the path on, this will be painful for the user for every table you are forcing them to have to set the path for.
SendKeys "%s", 1
DoCmd.RunCommand acCmdLinkedTableManager
Related
After a good search and some (over)thinking I came to the conclusion that I have no answer on what seems to be a simple question.
I have an excel document with many (20+) userforms in it. If you press a button (that is not in the userform, but just on the excel sheet) to start over again it should close any userform that's open at that moment.
I tried with unload me but of course I got an error when there wasn't any open userform.
Then I tried to add on error resume next thinking it would skip the line if there was no userform and therefore not giving an error but just continue what I want it to do. (opening a new userform).
It did indeed not give me the error anymore but it doesn't close any open userform as well (when there is one open).
So here I am, hoping someone here can help me as I don't know what to do. I could list up all of the userforms I suppose but it should be possible to go faster and automatically I suppose?
Some more info: It is never possible to have more than one userform open at the same time. // The button I want to create closes all the userforms if there are any and leads the user back to the main menu.
Thanks in advance!
KawaRu
Try calling the following when you want to unload all forms
Sub UnloadAllForms(Optional dummyVariable As Byte)
'Unloads all open user forms
Dim i As Long
For i = VBA.UserForms.Count - 1 To 0 Step -1
Unload VBA.UserForms(i)
Next
End Sub
This is hopefully the worst code that I have written in the last 5 years, but it will close any breathing form in Excel that you may have (and will kill any variables etc) :
Public Sub CloseAll()
End
End Sub
Use with caution!
From the MSDN End Statement:
The End statement stops code execution abruptly, without invoking the Unload, QueryUnload, or Terminate event, or any other Visual Basic code.
Code you have placed in the Unload, QueryUnload, and Terminate events offorms and class modules is not executed.
Objects created from class modules are destroyed, files opened using the Open statement are closed, and memory used by your program is freed.
Object references held by other programs are invalidated.
The End statement provides a way to force your program to halt. For normal termination of a Visual Basic program, you should unload all forms.
Your program closes as soon as there are no other programs holding references to objects created from your public class modules and no code executing.
I have a macro which runs an SQL query, which triggers a long slow recalculation of the spreadsheet based on the new data. When it finishes I've used application.speech to alert me if certain conditions have been met; all this works fine. But:
As I said, the recalculation can take quite a while, so I sometimes lock Windows and go do something else while I wait. Does anyone know of a way to pause the macro so that it doesn't run the last few lines (i.e. the audio alerts) until Windows is unlocked?
Before you call Application.speech you could check if the system is locked and if it is locked you repeat the check every minute until it is unlocked.
Code if a system is locked
Sub SystemLocked()
Do While Check_If_Locked = "Locked"
Application.Wait TimeValue("00:00:01")
Loop
MsgBox "Done"
End Sub
Code for Check_If_Locked can be found here
https://www.mrexcel.com/forum/microsoft-access/646623-check-if-system-locked-unlocked-using-vba.html
I have copied and slightly modified the code found at the bottom of this post to allow tabbing between form controls on a worksheet form I have created. Here is the segment relating to the KeyCode = vbKeyEnter:
Select Case KeyCode
Case vbKeyTab
Dim Backward As Boolean
Backward = (Shift And fmShiftMask)
Call MoveFocus(Cntrl:=Cntrl, TabIndex:=TabIndex, Backward:=Backward)
Case vbKeyEnter
Select Case TypeName(Cntrl)
Case TxtBoxType
If Not (Cntrl.EnterKeyBehavior And Cntrl.MultiLine) Then
Call MoveFocus(Cntrl:=Cntrl, TabIndex:=TabIndex)
End If
Case Else
On Error Resume Next
Application.Run Sheet1.CodeName & "." & Cntrl.name & "_Click"
On Error GoTo 0
End Select
End Select
The code works fine for tabbing forward and backward between controls. However, I'm having troubles using the enter key to check and uncheck check box controls. It works for option buttons, but does not work check boxes. If I add CheckBox1.Value = True to the CheckBox1_Click event it works to check it true, but naturally won't allow it to uncheck to false. I've tried adding the following IF statement to set it to true or false depending on current value, but then nothing happens.
If CheckBox1.Value = True Then
CheckBox1.Value = False
Else
CheckBox1.Value = True
End If
Another note: When I hit enter and nothing happens to the form control it moves the active cell down the active column. Any suggestions?
This may or may not be an answer to the programming question; I will let the voters decide.Q. Enter Key simulate click not working for checkboxes
Why would you do such a thing? You are spending time and effort to intentionally 'break' a working system. The spacebar has long been the accepted keystroke for toggling a checkbox on and off, Tab and Shift+Tab are used for navigating between form controls and Enter↵ is the default for OK.
By 'working system' I mean the whole Mac/Windows/Linux GUI system and the millions of people that have trained to work within long defined standard practises. You can take the mouse away from any competent office worker and their productivity will not suffer. They can navigate through the system and applications to perform their work because everything in the system from setting the video resolution to typing workers' timecard data into a custom form works the same way.
Take a Windows user and stick them in front of their first Mac. They can use the programs and get the job done because the vast majority of operations (and particularly the ones for basic operation of an application) are the same. Take a Mac user and stick them in front of a Linux machine and you will get the same results. The basic day-to-day operation of the machine and its programs are the same.
What is the point of any prospective applicant looking for employment to come with a CV filled with office experience if you are going to create a proprietary system that takes all of their training, practise and experience and throws it out the window?
The use of the spacebar to toggle a checkbox on and off predates Windows 3.0. There is a difference between building a better mousetrap and reinventing the wheel¹.
¹ If you don't think that maintaining GUI standards is something to strive for, consider the backlash that the Office 2007 ribbon created. An entire sub-industry dedicated to producing add-ons that brought back Office 2003 functionality was spawned.
I am looking for a way to click on a button 'open file'.
I wrote a excel-VBA macro that connects with SAP module. What it should do is to add a file as an attachment in SAP. As a result I get pop-up window, just a standard windows open file window to get the file name and open file button.
My question is how to automatically insert a file name (always known) and click on that open file button?
I tried sendkeys from within excel-VBA, but it turns out that the once the open file window pops up the whole Sub routine stops.
I know I need Winapi to do this.
You probably need to do a DoEvents to allow the keys to be processed by SAP.
Quoting from VBA help:
DoEvents Function
Yields execution so that the operating system can process other
events.
Syntax
DoEvents( )
Remarks
The DoEvents function returns an Integer representing the number of
open forms in stand-alone versions of Visual Basic, such as Visual
Basic, Professional Edition. DoEvents returns zero in all other
applications.
DoEvents passes control to the operating system. Control is returned
after the operating system has finished processing the events in its
queue and all keys in the SendKeys queue have been sent.
DoEvents is most useful for simple things like allowing a user to
cancel a process after it has started, for example a search for a
file. For long-running processes, yielding the processor is better
accomplished by using a Timer or delegating the task to an ActiveX EXE
component.. In the latter case, the task can continue completely
independent of your application, and the operating system takes case
of multitasking and time slicing.
Caution Any time you temporarily yield the processor within an event
procedure, make sure the procedure is not executed again from a
different part of your code before the first call returns; this could
cause unpredictable results. In addition, do not use DoEvents if other
applications could possibly interact with your procedure in unforeseen
ways during the time you have yielded control.
So I have an Access database with a front and a back end. I will be distributing it to users soon, but I have no control over where exactly they will put the files on their computers. However, I think I can count on them putting front and back ends in the same folder.
As such, when the front end opens, I want it to check that the linked tables are correctly connected to the back-end database. I have working code for this; however I don't know where to put it. When the front end opens, a menu form is automatically opened (configured through the start-up dialogue box). I have put the code in the OnOpen event, which I thought occurred before any data is loaded, but when I test this out, I get a message telling me that the back-end cannot be found (it's looking in its old location).
Basically, is there an event I can use that runs before any forms have opened?
Create a Macro and name it "autoexec".
For the macro action, select "RunCode" and then set the function name to the name of the function you use to check your linked tables.
As Matt said, create a macro, call it "autoexec", and select "RunCode" as the macro action. The Function Name argument should be the name of the function you wish to run (and not a sub), and if the function has no arguments, you should still put () at the end, or it won't work.
I generally prefer to create a small form that runs a number of checks, such as finding the back-end and so forth, and set various options. The code for the open event of this form might be:
Me.Visible = False
'Determines if the database window is displayed
SetProp "StartupShowDBWindow", False, dbBoolean
'Hide hidden and system objects
SetOption "Show Hidden Objects", False
SetOption "Show System Objects", False
'Find back end
CheckLinkPath
I keep a table of tables to be linked in the front-end and if any are missing, this form can be used to report the error, or any other error for that matter.
Set RS = CurrentDb.OpenRecordset("Select TableName From sysTables " _
& "WHERE TableType = 'LINK'")
RS.MoveFirst
strConnect = db.TableDefs(RS!TableName).Connect
If Not FileExists(Mid(strConnect, InStr(strConnect, "DATABASE=") + 9)) Then
'All is not well
blnConnectError = True
Else
Do Until RS.EOF()
If db.TableDefs(RS!TableName).Connect <> strConnect Then
blnConnectError = True
Exit Do
End If
RS.MoveNext
Loop
End If
If everything is ok, the small form calls the main menu or form and the user never sees the checking form. I would also use this form to open a password prompt, if required.
Before putting your front end and back end in the same folder, think about it. Isn't it worth having 2 folders? What about multiple users on the same computer accessing the same back-end database? What about multiple users accessing the same databse through a network? What is the necessity of having a front end-back end typology if your app is basically a single-user app?
Why don't you add a dialog box to your app, in case your connectivity is lost? You could create a fileDialog object in your code, allowing the user to browse for a *mdb file anywhere on his computer/network. It is then possible to control that the selected mdb file contains all requested tables and open the corresponding links (I guess you are using the transferDatabase command).
And what about additional tools/references you'll need for your app to run when you'll distribute it to your final users? By default, MS Access records the 3 basic ones:
Visual Basic For Application
Microsoft Access Library
Microsoft DAO Library
If your app needs anything else, such as ADO or Office objects (ADODB.recordset or Office commandbars for example), you will have to add the references manually for each installation, as the final user won't be able to open the VBA window and access the tools/references menu.
So, if you need to deploy your app on multiple computers, I strongly advise you to use a deployment tool such as this free one. You'll need a few hours to be able to use it properly, but the result is worth it. You'll be able to give your clients a real installer module. It will create folders, add requested shortcuts, and manage references in the computer's registry. This will make your deployment definitely painless!
EDIT: the autoexec macro is definitely the right solution for calling code before any event.
EDIT: don't forget that your final users can make profit of the runtime version of Access, which is free!
As others have suggested, I'd use the AutoExec macro in this case. If your code that checks the linked tables is currently a sub, change it to a function that returns TRUE if it succeeds. You can then use the "conditions" column in the AutoExec macro to exit the application with a user-friendly error dialog if the link table code fails. Your AutoExec macro could be something like:
Call your LinkTables() function, set condition to terminate startup if it fails.
Call your "Main" startup menu form.
You could send them a *.BAT file that copies the databases to c:\temp (or whatever folder you choose. Setup the linked to this folder before creating the BAT file. Zip it up and email it to them. then you won't have to worry with the extra needed code.