Save query using VBA - vba

I have form with multiple textboxes that are used to filter Subforms. The Subform Source Objects are queries. In order to filter the Subforms I update the query SQL and reassign the query as the source object on the subform.
Set qdf = db.QueryDefs("MyQuery")
qdf.SQL = strNewSQL
mySubForm.SourceObject = "Query.MyQuery"
The filtering works correctly. However when I close my form, I get a message asking if I want to save changes to the queries. How can I avoid this message?
Edit:- Following comment by #June7, closing form using
DoCmd.Close acForm, "MyForm", acSaveNo
solved my issue.
It is also possible to close the form using an embedded macro and setting prompt = No.

Using VBA instead of embedded macro solved your issue but consider that code can be simplified to:
CurrentDb.QueryDefs("MyQuery").SQL = strNewSQL
Me.mySubForm.SourceObject = "Query.MyQuery"

Related

CurrentDb.Execute Error 3061 and DAO.Recordset Error

On a form, a user is able to select a value of either 1 or 2. This number is on an unbound control called CountVal.
When the user selects the submit button, an update query is ran. The following is the query.
UPDATE UserData_T SET UserQuantity = Forms!MainUser_F!CountVal.value;
The query, when run separately, runs as should. The issue comes when I call it in the submit button click event. I use the CurrentDb.Execute method. This method throws a
3061 error of "Too few parameters'.
I have found through much research that control based parameters do not work with the execute method. It works when I set the value as either 1 or 2 but not through the control. I need to have this dynamic.
I have also tried the DAO.Database.OpenRecordset() method, however I am struggling with looping through each record. Logically, I would gravitate to a for each but I'm not finding any references on using this loop with a DAO recordset. Also, wouldn't looping through the recordset be extremely slow? Could I also add an if statement to the query itself?
In MS Access, stored queries can refer to open form or report controls as parameters. However, queries called via DAO methods like CurrentDb.Execute, do not see the GUI interface and hence cannot evaluate form or report controls.
So to continue using form controls as is, simply save your SQL statement as a stored query and call it with DoCmd.OpenQuery (which do not need to be closed for action queries like UPDATE, INSERT, DELETE). This is the coding counterpart to clicking the stored query via Navigation Pane.
DoCmd.OpenQuery "mySavedUpdateQuery"
Do note the above will raise prompts of data changes. To suppress such prompts, use DoCmd.SetWarnings:
DoCmd.SetWarnings False
DoCmd.OpenQuery "mySavedUpdateQuery"
DoCmd.SetWarnings True
You must concatenate the value to build the SQL:
Dim Sql As String
Sql = "UPDATE UserData_T SET UserQuantity = " & Forms!MainUser_F!CountVal.Value & ""

MS Access VBA - take form record out of edit mode to allow recordset operations

I'm editing records on a form. I then want to do a recordset operation on the entire recordset underlying the form. The recordset operation then runs into the error "Error - Could not update; currently locked by another session on this machine"...clearly because a record is being edited.
Regardless of whether this is good practice or not, how might I use vba to get the application to cancel, ignore or complete the form editing operation so that the recordset operation can continue...or it just not possible, because the GUI cannot be "released" from within VBA (kind of like when Excel cells are being edited)?
This can occur quite often. The simple trick is to ensure that the current form record is not "dirty" or is not pending a update.
Thus you can go:
if me.dirty = True then me.Dirty = False
' now call your update routines etc.
Because those other routines may well update the screen/record you are viewing, then you can execute a me.Refresh to ensure that any changes are displayed.
The above will force the record write. In fact if I am in a form, and plan say to launch some popup form, or a form in the next "step" for the user, I also tend to force write the current form out - it is not only safer, but avoids the common "this record been changed by another user". In most cases, the other user is in fact your code.
So simply save the record with the above one line of code - this should eliminate this issue in general. Keep in mind that you can set a form to lock the whole table in the "data" tab of the forms property sheet, but that is unlikely your problem.
Is the form data-bound? It doesn't sound like it.
Me!SomeField = ...
DoCmd.RunCommand acCmdSaveRecord
If your form has control bound to "SomeField", then the form will be updated automatically.
1) Update records using SQL code. For example, you have ID of record that should be updated in the form data set, so you can write something like:
Call CurrentDB.Execute( _
"UPDATE SomeTable SET SomeField = SomeValue WHERE SomeTableID = " & Me!SomeTableID, dbSeeChanges)
2) You can look at the Bookmark property - both Recordset and Form has this property, it describes the record position. So you can write something like this (not the best example, but can help you to get an idea):
Dim Rs as Recordset
Set Rs = Me.RecordsetClone 'make a reference copy of the form recordset
Rs.Bookmark = Me.Bookmark 'locate this recordset to the form current record

Access VBA unable to refresh a form

I have a form (frmDropDownEdit) that has a filtered table as the data. A "New" button is created that opens another form (frmDropDownNew) and the user can enter new data. When complete the new form is closed and the user is back to the original form. The code for frmDropDownNew correctly add the info to the table, then the code refreshes the frmDropDownEdit form but it does not refresh. If I click the refresh button in the ribbon, it also does not refresh. But refresh all does work.
How can I have my code refresh the data in frmDropDownEdit. I also put code me.refresh on the OnGotFocus event but that does not even run.
Here is my source code
Private Sub Command5_Click()
'Add Button
Dim rst As DAO.Recordset
Set rst = CurrentDb.OpenRecordset("tblDropDown")
rst.AddNew
rst!DdCategory = Me.txtCategory.Value
rst!DdDescription = UCase(Me.txtDescription.Value)
rst.Update
rst.Close
DoCmd.Close
Forms!frmDropDownEdit.Refresh
End Sub
On my MS Access 2010 ×64 single user PC, Forms![AnyForm] .Refresh never worked in VBA, independently where it is placed in any database's code. Form_Current() doesn't run either as it should after data are modified (verified by putting a Stop therein). Moreover, records with modified data are neither marked dirty nor refreshed before the vba code has finished. Procedures which should run without delay when data are modified don't run, even when placed into the modified fields' events.
Thus, one has to use a work-around. Many people recommend to use .Requery instead of .Refresh and then to return by vba code to the desired record, but this requires a field with a primary key.
My solution for tables without primary key is the following:
'…
' ESSENTIAL: this code must be run from ANOTHER module !
' (it runs without error in MyForm's own code [eg. in Form_Activate(),
' but then MyForm is NOT immediately refreshed as desired,)
' one still has to repeat these steps by hand afterwards…
DoCmd.GoToRecord acForm, "MyForm", acNext
DoCmd.GoToRecord acForm, "MyForm", acPrevious
' NB: Forms![MyForm].Refresh doesn't work
' at this place in "MyOtherModule" either.
'…
As mentioned in above code comments: this code must be run from another module ("MyOtherModule") - in my case, a form-independent procedure called upon closing a pop-up form opened from the first form, which interactively modifies data. These data should be updated/refreshed immediately when closing the pop-up form, reflecting all changes and their consequences (for example, automatic filling-in/deleting of other data and/or en/disabling controls or making them [in]visible, depending on the modified fields' values).

Hey subform - let go of my Table

I'm having a bit of an issue with timing, I think, that's driving me batty!
I have a Form with a subform with a Table as recordsource (as a datasheet)
Users can edit the data in the datasheet
Upon closing the form (via btnSave), I intend to run a function that exports the datasheet, with its changes to an XLS via Transfer spreadsheet.
Access is complaining the table is "already in use"
I have attempted to set the subform's recordsource = "" then requery
Same complaint from Access about the table - but table is not open!
Any suggestions how and where to attach the export function?
Note: The export function works just fine under its own dedicated button on the MainForm. I just want to run this same function when I close the form/subform.
HansUp, I can confirm the following syntax also works:
Forms![Matched]![Matched subform].SourceObject = ""
Thanks for the suggestion!
Crude, but effective:
DoCmd.Close acForm, "Forms![Matched]![Matched subform]", acSaveNo
No more complaints about the locked table
HansUp, I'll play with that syntax; always fuzzy trial and error on those pesky sufbform properties.

Requery a subform from another form?

I've struggling with this problem on my own, then with some help, then search about it; but I haven't had any luck. So I decided to ask.
I have two forms in Access 2007 lets call them MainForm and EntryForm.
MainForm has a subform and a button. The button opens the EntryForm in Add Mode. What I want to do is when the EntryForm saves the new record it would update (requery) the subform in MainForm.
I've try this setup code
Private Sub cmdSaveAndClose_Click()
DoCmd.Save
'requery list
Forms![MainForm]![subformName].Requery
'' I've also tried these
'Forms![MainForm]![subformName].Form.Requery
'Forms.("MainForm").[subformName].Requery
'Forms.("MainForm").[subformName].Form.Requery
DoCmd.Close
End Sub
None of these attempts seem to work. Is there a way to make this requery?
Thanks for the help in advance.
You must use the name of the subform control, not the name of the subform, though these are often the same:
Forms![MainForm]![subform control name Name].Form.Requery
Or, if you are on the main form:
Me.[subform control name Name].Form.Requery
More Info: http://www.mvps.org/access/forms/frm0031.htm
Just a comment on the method of accomplishing this:
You're making your EntryForm permanently tied to the form you're calling it from. I think it's better to not have forms tied to context like that. I'd remove the requery from the Save/Close routine and instead open the EntryForm modally, using the acDialog switch:
DoCmd.OpenForm "EntryForm", , ,"[ID]=" & Me!SubForm.Form!ID, , acDialog
Me!SubForm.Form.Requery
That way, EntryForm is not tied down to use in one context. The alternative is to complicate EntryForm with something that is knowledgable of which form opened it and what needs to requeried. I think it's better to keep that kind of thing as close to the context in which it's used, and keep the called form's code as simple as possible.
Perhaps a principle here is that any time you are requerying a form using the Forms collection from another form, it's a good indication something's not right about your architecture -- that should happen seldom, in my opinion.
I tried several solutions above, but none solved my problem.
Solution to refresh a subform in a form after saving data to database:
Me.subformname.Requery
It worked fine for me. Good luck.
I had a similar kind of issue, but with some differences...
In my case, my main form has a Control (vendor) which value I used to update a Query in my DB, using the following code:
Sub Set_Qry_PedidosRealizadosImportados_frm(Vd As Long)
Dim temp_qry As DAO.QueryDef
'Procedimento para ajustar o codigo do cliente na Qry_Pedidos realizados e importados
'Procedure to adjust the code of the client on Qry_Pedidos realizados e importados
Set temp_qry = CurrentDb.QueryDefs("Qry_Pedidos realizados e importados")
temp_qry.SQL = "SELECT DISTINCT " & _
"[Qry_Pedidos distintos].[Codigo], " & _
"[Qry_Pedidos distintos].[Razao social], " & _
"COUNT([Qry_Pedidos distintos].[Pedido Avante]) As [Pedidos realizados], " & _
"SUM(IIf(NZ([Qry_Pedidos distintos].[Pedido Flexx], 0) > 1, 1, 0)) As [Pedidos Importados] " & _
"FROM [Qry_Pedidos distintos] " & _
"WHERE [Qry_Pedidos distintos].Vd = " & Vd & _
" Group BY " & _
"[Qry_Pedidos distintos].[Razao social], " & _
"[Qry_Pedidos distintos].[Codigo];"
End Sub
Since the beginning my subform record source was the query named "Qry_Pedidos realizados e importados".
But the only way I could update the subform data inside the main form context was to refresh the data source of the subform to it self, like posted bellow:
Private Sub cmb_vendedor_v1_Exit(Cancel As Integer)
'Codigo para atualizar o comando SQL da query
'Code to update the SQL statement of the query
Call Set_Qry_Pedidosrealizadosimportados_frm(Me.cmb_vendedor_v1.Value)
'Codigo para forçar o Access a aceitar o novo comando SQL
'Code to force de Access to accept the new sql statement
Me!Frm_Pedidos_realizados_importados.Form.RecordSource = "Qry_Pedidos realizados e importados"
End Sub
No refresh, recalc, requery, etc, was necessary after all...
By closing and opening, the main form usually runs all related queries (including the subform related ones). I had a similar problem and resolved it by adding the following to Save Command button on click event.
DoCmd.Close acForm, "formname", acSaveYes
DoCmd.OpenForm "formname"
Just discovered that if the source table for a subform is updated using adodb, it takes a while until the requery can find the updated information.
In my case, I was adding some records with 'dbconn.execute "sql" ' and wondered why the requery command in vba doesn't seem to work. When I was debugging, the requery worked. Added a 2-3 second wait in the code before requery just to test made a difference.
But changing to 'currentdb.execute "sql" ' fixed the problem immediately.
All your controls are belong to us!
Fionnuala answered this correctly but skimmers like me would find it easy to miss the point.
You don't refresh the subFORM you refresh the subform CONTROL. In fact, if you check with allforms() the subForm isn't even loaded as far as access is concerned.
On the main form look at the label the subform wizard provided or select the subform by clicking once or on the border around it and look at the "caption" in the "Other" tab in properties. That's the name you use for requerying, not the name of the form that appears in the navigation panel.
In my case I had a subform called frmInvProdSub and I tried for many hours to figure out why Access didn't think it existed. I gave up, deleted the form and re-created it. The very last step is telling it what you want to call the control so I called it frmInvProdSub and finished the wizard. Then I tried and voila, it worked!
When I looked at the form name in the navigation window I realized I'd forgotten to put "Sub" in the name! That's when it clicked. The CONTROL is called frmInvProdSub, not the form and using the control name works.
Of course if both names are identical then you didn't have this problem lol.
I ran into this issue today.
I was in a form that contained a button on subform1. Subform1 made changes to Subform2 that required a requery.
I found success with: Me.Parent.subform2.form.recordset.requery