Can I programatically open a new query window? - ms-access

I'm trying to figure out if/how I can generate a new query window in the Design View either via a macro or VBA code.
Specifically, I want to open a new, blank query in SQL View so I can quickly test SQL code. This is a common activity for me.
I usually create a new query manually via the Ribbon: Create tab > Query Design button > Close (Show Table window) button > SQL View button. This results in a new window called Query1 (or Query2, etc.).
I'd like to condense all of those multiple clicks into a keyboard shortcut or a single macro button on the Quick Access Toolbar. Note that I'm using Access 2010.
Possible?

Add this to a module:
Function NewQueryInSqlView()
' Send the ESC key, without waiting for processing,
' to cancel the select table dialog that occurs when designing new query
SendKeys "{ESC}", False
DoCmd.RunCommand acCmdNewObjectDesignQuery ' create new query
DoCmd.RunCommand acCmdSQLView ' switch to SQL view
End Function
To execute the code by way of a keyboard shortcut, create a new macro, and ensure "Macro Names" column is visible.
Add the following row to macro with the following values in the specified columns:
Macro Name: +{F3}
Action: RunCode
with Function Name argument: NewQueryInSqlView()
Save this macro as "AutoKeys". This macro will map SHIFTF3 to the execution of NewQueryInSqlView(). Note that choosing a key mapping starting with CTRL (the ^ character) will be problematic due to the SendKeys statement in NewQueryInSqlView().

Write a function and call it from a macro:
Public Function foo()
Dim qdf As QueryDef
Set qdf = CurrentDb.CreateQueryDef("qNew", "SELECT 'd' as foo")
DoCmd.OpenQuery qdf.Name
End Function
This will create the query and open it
The macro is a RunCode command that runs the above function.

Try This code:
Sub EmptyQuery()
Dim Qname As String
Qname = "mQname"
On Error Resume Next
CurrentDb.CreateQueryDef Qname
On Error GoTo 0
DoCmd.OpenQuery Qname, acViewDesign
End Sub

Related

Can an Access 2007 Macro determine the name of itself..?

Can an Access 2007 macro determine its own object name..?
My database relies heavily on Navigation Pane custom groups, some with hundreds or objects. I would like to create a generic macro that I can copy, rename, and drop into any group, which would perform actions best summarized as "do this task with every other object in this group".
To do so, the macro would need to be aware of its own name, so the MSysNavPane* groups could be queried for that name, and then the work could proceed from there.
I seem to recall that it's difficult if not impossible for VBA procedures to know their own names, but I couldn't find any information on this topic about Access macros.
As far as I know, no. Macros can only execute simple commands.
Things you can do:
List all open macros (open as in currently being edited, not running)
Public Function AllMacros()
Dim obj As AccessObject, dbs As Object
Set dbs = Application.CurrentProject
' Search for open AccessObject objects in AllMacros collection.
For Each obj In dbs.AllMacros
If obj.IsLoaded = True Then
' Print name of obj.
Debug.Print obj.Name
End If
Next obj
End Function
Use a form for exactly this purpose
Create a blank form with a timer set to 1, and add the following sub (it runs MyFunction and passes the form name as a parameter)
Private Sub Form_Timer()
Me.Visible = False
Run "MyFunction", Me.Name
DoCmd.Close acForm, Me.Name
End Sub
Should behave exactly as your desired macro, only it's a form not a macro

How to force an Access query datasheet to refresh its data

I am new on access and what I am trying to do is a select with a criteria so I created a query with the wizard and seted the criteria with a text from a form ([Forms]![Form1]![Transacao]) and created a button to run the query at the first time works great but when I type something else and click the button the datas do not refresh. What I have to do to refresh? I've tryed to add refresh on the event click of the button and did not work.
Thanks in advance for your help.
In Access, a query is usually opened in a default Datasheet view. This default datasheet is contained in a window (or tab) that is only accessible using Macros or DoCmd in VBA.
Once a query window is open, its data will not necessarily update automatically when new records are added to the underlying table(s). The datasheet needs to be "requeried". (Incidentally, the term "refresh" is usually reserved to mean "redrawing" a window on the screen and has nothing to do with the data. This is especially the case in programming and development environments which deal with data and drawing/painting windows and controls on the screen.)
Here is one way to force a query to update its data (when open in its default datasheet view):
DoCmd.OpenQuery "QueryName"
DoCmd.Requery
Calling OpenQuery should also activate the query window if it is already open. If you find that the windows does not activate, you can also call DoCmd.SelectObject acQuery, "QueryName" before DoCmd.Requery.
The DoCmd methods correspond to Macro actions, so if the query is activated by a Macro, just add the Requery action to the macro after the OpenQuery or SelectObject actions. Leave the Control Name parameter of the Requery action blank to force the entire query to updated.
I know this question is a bit stale at this point, but since I couldn't find a suitable answer to this question and the above answer didn't work for me (and still hasn't been accepted), I thought I'd offer my solution for those few poor saps still stuck developing applications in Access. My use case was slightly different (changing the underlying SQL of a query, then opening/refreshing it), but the same principle could be applied. The gist is to first check to see if the query is open and close it if it is. Then open it up again.
To do this, paste this code into a VBA module:
Public Function open_or_refresh_query(query_name As String, Optional sql_str As String = "")
' Refresh or open an existing query
' query_name: Name of the query
' sql_str: optional new SQL string if changing the underlying SQL. If not given,
' the query will open with its existing SQL string
On Error GoTo err_handler
Dim qdf As QueryDef
' Loop through each query in the DB and find the one of interest by name
For Each qdf In CurrentDb.QueryDefs
If qdf.Name = query_name Then
' If the query is open, close it
If SysCmd(acSysCmdGetObjectState, acQuery, query_name) <> 0 Then
DoCmd.Close acQuery, query_name, acSaveNo
End If
Exit For
End If
Next qdf
Set qdf = CurrentDb.QueryDefs(query_name)
' Reset the SQL if new SQL string was given
If Len(sql_str) > 0 Then qdf.sql = sql_str
' Close the QueryDef object to release resources
qdf.Close
' Open the query in default datasheet view
DoCmd.OpenQuery query_name
exit_function:
Exit Function
err_handler:
MsgBox "Error " & Err.Number & ": " & Err.Description, vbCritical, "Error"
Resume exit_function
End Function
At this point you could call this function from any other VBA code in your project. To open/refresh a query from a macro as the OP wanted to do, create a new macro and add a RunCode action with open_or_refresh_query("my_query") in the Function Name field, changing my_query to the name of your query.

using autoexec to link tables prior to on open event

This question follows a previous question Form is ignoring the code in OnOpen event that was answered by Andre.
I have a form that is bound by a control that executes a query, so I can't use the onopen event to relink tables when the form is opened. I have created a function as follows:
Function AutolinkDB()
Dim tdf As DAO.TableDef
For Each tdf In CurrentDb.TableDefs
' check if table is a linked table
If Len(tdf.Connect) > 0 Then
tdf.Connect = "Connect String"
tdf.RefreshLink
End If
Next
''' Andre edit: after relinking the tables, open the start form
DoCmd.OpenForm "loginputFrm"
''' Andre edit
End Function
Next, I created an autoexec macro that looks like the following:
OpenForm
Form Name loginputFrm
View Form
Filter Name
Where Condition
Data Mode
Window Mode Normal
RunCode
Function Name Autolink()
Problem is that the autolink does not execute the function, and app still asks for manual password.
The only thing in your AutoExec macro should be
RunCode -> AutolinkDB()
(Note that you currently have Autolink() - typo?)
Nothing else. At the end of AutolinkDB(), open your start form with DoCmd.OpenForm.
Otherwise the form will be opened first, and ODBC data accessed.

Action on Form Save

We have an Access 2010 database that acts as a front-end to a MS SQL database. When we edit data in the form there is a procedure that needs to run in order to properly save certain data back to SQL.
Our DB programmer added a "Save Button" to do this. But that causes another problem - there are multiple ways in Access by which to save a form -
Navigate to the next record
Click on the Confirmation bar on the left
Create a new record
Search for a new record
Use commands in the ribbon
Is there any way to attach a procedure the actual save action so that no matter how a person moves to a next form that the procedure gets run?
[update]
Here is the code behind the scenes: the first sub is attached to the "Save" Button. Of course, the second is attached to the form BeforeUpdate.
Private Sub SaveRecord_Click()
'From NAME form
Form_BeforeUpdate False
End Sub
Private Sub Form_BeforeUpdate(Cancel As Integer)
'used by NAME form
[Last_Update] = Now
'*********************
Save_Record
'*********************
MName_ID = Me.Name_ID
Me.Undo
Cancel = True
If Not IsNull(MName_ID) Then
Jump_to_Name_ID MName_ID, True
Else
End If
End Sub
I guess I just don't understand what the button is for.
So I installed an MS Access 2010 trial and finally managed to figure out a way to solve your problem. It includes data macros and a hidden gem that took me quite a while to find.
Here's how you run VBA when a table changes:
Create an ordinary module (haven't tried class modules) with public functions:
Module name: EventHandlers
Public Function InsertEvent(ByVal id As Integer)
MsgBox "inserted: " + CStr(id)
End Function
Open the table that, when modified, should run VBA and go to "Table" in the ribbon.
Click on "After Insert"
In the "Add New Action"-select box, choose SetLocalVar (or select it from the Action Catalog).
In the Name-field, insert the name of the module (in this case, EventHandlers, as we created earlier)
In the Expression-field, write the name of the function: InsertEvent([id]) (where [id] is an actual column in the table you're adding a data macro for)
Save and close
Whenever something is inserted to the table, a messagebox will be shown with the id.
You could do the same with the update event. The function could be something like this:
Public Function UpdateEvent(ByVal oldValue As String, ByVal newValue As String)
MsgBox oldValue + " changed to: " + newValue
End Function
and the data macro would be
Action: SetLocalVar
Name: EventHandlers
Expression: UpdateEvent([Old].[your_column_name];[your_column_name])
Note: Executing DoCmd.RunSQL with update, insert or delete will execute data macros and THEN ask the user if he or she actually WANTS to update/insert/delete the row. If the user clicks cancel, nothing is changed but your data macro executed anyway. If you haven't already, you should probably disable this check before implementing data macros.
Well, I was not able to use Mr. Sommer's solution because it was not possible to add an event handler to a linked table on account of their being read-only. But, I did work out a simple procedure that seems to work well enough.
So, I was actually already using the BeforeUpdate event, so I'm catching the right event here - this is the event that traps the save, whether it be on change of navigation or the save-record bar on the left. However, there were a few issues that resulted from using Application.Echo False to keep Access from posting back the old data to the control whilst the Me.Undo takes place.
So we use cancel=true to prevent the BeforeUpdate event from doing its normal processing, and we use Me.Undo to prevent Access from trying to save data to the linked tables.
Private Sub Form_BeforeUpdate(Cancel As Integer)
Cancel = True
[Last_Update] = Now
'*********************
Save_Record '-->This will save the data back to SQL
'*********************
MName_ID = Me.Name_ID
Application.Echo False 'don't show the undo in the controls
Me.Undo
If Not IsNull(MName_ID) Then 'used for the navigation buttons
Jump_to_Name_ID MName_ID, True
Else
End If
Application.Echo True 'turn the control refresh back on
Me.Repaint
End Sub

Access making a report on update/creation of a data

i am trying to create a Report based on a query which will be made on each
creation / update of my DataBase
i attach the report to a button with a macro,
problem is that if nothing was changed and someone just press over the button the report would be fired but with no data, and if the data was inserted to the text boxes and i press over the button with the macro the data does not append to the data base.
my macro lines:
OnError Next,
OpenReport Accept, Report, , , Normal // Accept is the name of the report
GoToRecord Next,
[MacroError]<>0 =[MacroError].[Description], Yes, None,
Thanks in advance for your help
A good way to test and track this would be by adding a 'Yes/No' field called for example "flgReported" in to one of the tables used in the query, then after running your report you could update all rows to true. Any new rows added afterwards would then be false and you could bring this in to your select query to only report on False rows, this would also allow you to test whether there was any data to return when clicking the button before going ahead and running the report.
Update: If you highlight the macro in question and then goto "Tools > Macro > Convert Macro's to Visual Basic" and then click 'Convert' it will generate the VB code for you. This could then be called from your button instead of the Macro and before the main procedure you could insert this to check if there were any new records:
Private Sub ButtonClick() "For Example"
Dim rs As Recordset
Set rs = CurrentDb.OpenRecordset("SELECT * FROM queryname where flgReported = False")
If rs.BOF And rs.EOF then 'No Records to report so we quit at this point
rs.close
set rs = Nothing
Exit Sub
End If
'Remainder of Macro Code goes here
'Then run a simple SQL here to update the flags to True
End Sub