Access Crashes When Using VBA To Set Bound Combobox RowSource - vba

I've asked this on UA but wanted to post here as well in the hope someone can help me figure this out. Also, I'm aware of the evils of using MVFs; this is just something that I want to figure out.
I have a form with a combobox that is bound to a multivalue field. I want to use VBA to set the RowSource of the combobox. (Specifically, I want to use the value of another combobox on the form to filter the available choices in the second combobox, but right now I'm just trying to get the RowSource update to work with a static SQL statment.)
If I set the RowSource in the form's Design Mode, then it works as expected. But as soon as I try to use the exact same value to set the RowSource in VBA, Access crashes. Here is the code on the After Update event of the 'parent' combobox:
Private Sub cboSelRegSet_AfterUpdate()
Dim strSQL As String
On Error GoTo Query_Error
strSQL = "SELECT tblRegulation.ID, tblRegulation.RegulationCode " _
& "FROM tblRegulation " _
& "ORDER BY tblRegulation.RegulationCode;"
MsgBox "Before Filter", vbOKOnly
Me.cboSelReg.RowSource = strSQL
MsgBox "After Filter", vbOKOnly
Me.cboSelReg.Requery
MsgBox "After Requery", vbOKOnly
ExitNow:
Exit Sub
Query_Error:
MsgBox Err.Description
Resume ExitNow
End Sub
If I make "cboSelReg" unbound, then the update works, but since it is no longer bound to an MVF, the user can only select one value which defeats the purpose.
I've also added msgbox prompts to step through the code and it seems to get through the entire subroutine since I get the prompt after the requery. But as soon as I click OK, Access crashes.
Is there a way to make this work?

Related

How to ensure selected combobox item is in table? (Access VBA)

My goal is to create a way to log why something was changed and who changed it.
I have 2 comboboxes that are populated by tables. I use VBA to define the RowSource when the form opens.
When the user clicks the send button, before anything is changed, I want to make sure that the comboboxes have 'valid' selections.
One combobox is a list of employees based on firstname & ' ' & lastname
the other is a list of pre-set reasons (i.e. "Incorrect Hours", Wrong Item #", etc.)
If Nz(Me.cmbReason, "") = "" Then
fncMsgBox "Must select a reason from the dropdown for modifying a labor entry."
GoTo Exit_btnSend_Click
Else
If Not IsNull(DLookup("Reason", "tblEditReason", Me.cmbReason)) Then
fncMsgBox "Must select a reason from the dropdown for modifying a labor entry."
GoTo Exit_btnSend_Click
End If
End If
If Nz(Me.cmbModBy, "") = "" Then
fncMsgBox "Must enter who is modifying this labor entry."
GoTo Exit_btnSend_Click
Else
If IsNull(DLookup("FNAME & ' ' & LNAME", "EMP", Me.cmbModBy)) Then
fncMsgBox Me.cmbModBy & " is not a valid name."
GoTo Exit_btnSend_Click
End If
End If
When I have "If not IsNull..." then it won't accept anything regardless of valid or invalid, if I remove the "IsNull" then I get a mismatch debug.
How do I ensure that what the user puts inside the combo box, is in fact in the table?
June7 Comment - Maybe set combobox LimitToList property to Yes?
Resolved my problem.
LimitToList prevents anything not in the list from being accepted. When clicking on any other control in the form, it pops out the drop down until an item from the list is selected or it is left blank. Allowing the code I was using "If not IsNull(....." to do just what I was looking for!

MS Access VBA Update Query to Clear All Check Boxes On a Form Not Working

I have a button on my MS Access form that uses VBA to update the modified date/time stamp on all records on a datasheet style form that have a checkbox checked in a field called "Confirm Existing Update". After it makes these updates, it is supposed to clear all of the check boxes. This is currently accomplished via a simple SQL update query that executes via VBA once the date/timestamps have been updated:
"Update [CMO Deviations Tracker] SET [CMO Deviations Tracker].[Confirm Existing Update] = FALSE WHERE [CMO Deviations Tracker].[Confirm Existing Update] = TRUE"
The problem is that the query doesn't seem to want to clear the last checkbox checked (in the last row that was interacted with). I've tested the query by copy/pasting it into a blank query design window and it works perfectly there (clears all check boxes, including the final one clicked). So far, I've attempted to add the following to my form button's VBA code:
Shifting the record to the next line before running the Update query via "Me.Recordset.MoveNext"
Saving the last record interacted with via "If Me.Dirty Then Me.Dirty = False"
I added "Forms![CMO Deviations Tracker].Requery" to the end of the code to ensure that I was seeing the latest info
None of these seem to result in the clearing of the last checkbox checked. What could be causing this?
EDIT: I just tried running my separate Update query while the form was open immediately after trying and failing with the button. It failed to remove the last checkbox due to a "lock violation". Interesting...
EDIT2: So the only thing that I've found to work (as a manual workaround) is to check the boxes for all of the rows that I want to update the timestamp for, and then check and uncheck the box for one additional row before clicking the button. Access will then clear all of the desired check boxes like it's supposed to.
EDIT3: Just a point of clarity. The updating of the timestamp on the last record checked appears to work perfectly. It seems like, for whatever reason, it's only the "Confirm Existing Update" checkbox field that is getting locked. Thinking that it could be the method being used, I attempted to clear these checkboxes by editing the Recordset and using a loop to make the "Confirm Existing Update" field for each of the rows in the Recordset equal to "False". It still seems to clear all check boxes except the last one, only this time, the vba code will error out on the final line by saying "Could not update | currently locked". Same error, completely different implementation.
EDIT4: Updating the "Record Locking" property of the form to either "Edited Record" or "No Locks" seems to fix the issue, but only if done as part of the button click code. If I put VBA to update this property in the "On Open" event trigger of the form, or simply update the property in the GUI, it doesn't seem to fix the issue - even with "No Locks" set as the default property. What the heck?
EDIT5: Per request, the following is the VBA from my button. Please note that I've updated the methodology to update the check boxes using a DAO.Recordset, rather than the original SQL Update query.
Private Sub Command187_Click()
Dim Temp_ID As String
Dim DBS_Temp1 As DAO.Database
Dim DevTracker As DAO.Recordset
Dim DevUpdates As DAO.Recordset
If MsgBox("This will confirm that the latest update provided is still current for all items with the 'Confirm Existing Update' box checked above. Are you sure that you want to do this?", vbYesNo) = vbYes Then
Set DBS_Temp1 = CurrentDb
Set DevTracker = DBS_Temp1.OpenRecordset("CMO Deviations Tracker")
Set DevUpdates = DBS_Temp1.OpenRecordset("Deviation Updates")
DevTracker.MoveFirst
DevUpdates.MoveFirst
Do Until DevTracker.EOF = True
If DevTracker![Confirm Existing Update] = True Then
DevUpdates.MoveFirst
Temp_ID = "[Deviation ID] = '" & DevTracker![Deviation ID] & "'"
DevUpdates.FindLast (Temp_ID)
DevUpdates.Edit
DevUpdates![Status Update] = DevUpdates![Status Update] & " "
DevUpdates![Status Update] = Left(DevUpdates![Status Update], Len(DevUpdates![Status Update]) - 1)
DevUpdates.Update
DevTracker.Edit
DevTracker![Confirm Existing Update] = False
DevTracker.Update
End If
DevTracker.MoveNext
Loop
DevUpdates.Close
DevTracker.Close
Set DevUpdates = Nothing
Set DevTracker = Nothing
Set DBS_Temp1 = Nothing
MsgBox "Existing updates for the selected deviations have been confirmed."
Else
DevTracker.MoveFirst
Do Until DevTracker.EOF = True
DevTracker.Edit
DevTracker![Confirm Existing Update] = False
DevTracker.Update
DevTracker.MoveNext
Loop
MsgBox "Update Confirmation Cancelled."
Forms![CMO Deviations Tracker].Requery
Exit Sub
End If
Forms![CMO Deviations Tracker].Requery
End Sub

Run a Query Using a Button in Access

I am trying to run a query in Access 2010 inside of a form. The form, per user request, needs to have buttons that they can use to quickly change the data in their column. For the table being called, there are only two columns that matter: Equiptment_Name and Amount (The other several columns are just there to help reference the data in case they misspell the name of the product). The current query I have is:
UPDATE tblInventory SET Amount = Amount-[Enter Amount]
WHERE ((([tblInventory].Equiptment_Name)=[Enter Name]));
This works perfectly, I just can't get it to work in a form with a button. I've searched all over for help and was encouraged to use a macro because that would be the easiest way. Can someone please walk me through the process of getting a macro to run a version of my query? I'm fine with the user being prompted to enter the amount to withdraw from the Amount category, but it would be nice if they didn't have to type in the Equiptment_Name category since The button would be in the form next to it (see picture below). Thanks for all help in advance.
You could simply use VBA to get this going. Something along the lines of
Private Sub Command70_Click()
If Len(Me.AmountTextBoxName & vbNullString) = 0 Then
MsgBox "Amount cannot be empty !", vbCritical
Exit Sub
End If
If Len(Me.Equiptment_NameTextBoxName & vbNullString) = 0 Then
MsgBox "Equiptment Name cannot be empty !", vbCritical
Exit Sub
End If
CurrentDB.Exeucte "UPDATE tblInventory SET Amount = Amount - " & Me.AmountTextBoxName & _
"WHERE tblInventory.Equiptment_Name = '" & Me.Equiptment_NameTextBoxName & "';"
End Sub
I have taken the Equipment name is actually a String.

Create query to take select data from multiple other tables on command button click

I am going to try to make this question as detailed as possible as it's a really confusing one, at least in my mind. First of all lets start with what everything is called. There are 2 forms, 1 button, 4 tables, and 1 temp-query.
The 2 forms are called WorkOrderDatabaseF & WorkOrderInfoF.
The button is called WorkOrderMoreInfoButton, which creates the temp-query and opens up the form WorkOrderInfoF.
The 4 tables are WorkOrdersT, ClientsT, UnitsT, and CustomersT. All have relations to eachother, in a straight forward line up of (all one to many from left to right)
ClientsT>CustomersT>WorkOrdersT>UnitsT. 1 Client can have as many customers which each customer can have as many work orders which any work order can have as many units.
The temp-query when made is called WorkOrderMoreInfoQ.
Lets jump right in. What happens is this:
There is a subform on the WorkOrderDatabaseF which lists the Work Orders; which which customers and clients belong to which work order. When you select one and click the more info button it pops up the WorkORderInfoF form and doesn't close the main database. From here it has text boxes, and another subform and button (the button won't be used for what I am asking so I won't go into detail about it). The text boxes currently are hooked up to show the data from the selected by a temp-query made when you clicked the button. It took the selection you clicked, and made a query which has 1 line with the information about that work order (the only foreign key in the workorderT is CustomerID which is related to the CustomersT key; which has a foreign key of ClientID which is as you guessed it, related to the key on ClientsT.) The text boxes show all the data correctly, except the CustomerName and ClientName. The subform would show all units that pertain to the workorder selected only. The popup form has the recordsource of the temp-query which I'm calling temp because when you close the more info form it deletes the query.
All code I have so far for things:
More info button:
Private Sub ProjectMoreInfoBtn_Click()
On Error Resume Next
DoCmd.Close acForm, "WorkOrderInfoF"
DoCmd.DeleteObject acQuery, "WorkOrderMoreInfoQ"
On Error GoTo Err_ProjectMoreInfoBtn_Click
Dim qdef As DAO.QueryDef
Set qdef = CurrentDb.CreateQueryDef("WorkOrderMoreInfoQ", _
"SELECT * " & _
"FROM WorkOrdersT " & _
"WHERE WorkOrderID = " & txtWorkOrderID.Value)
DoCmd.OpenForm "WorkOrderInfoF"
Exit_ProjectMoreInfoBtn_Click:
Exit Sub
Err_ProjectMoreInfoBtn_Click:
MsgBox Err.Description
Resume Exit_ProjectMoreInfoBtn_Click
End Sub
On form close delete temp-query code:
Private Sub Form_Close()
On Error Resume Next
DoCmd.DeleteObject acQuery, "WorkOrderMoreInfoQ"
End Sub
How would I make the customer and client name that is associated with tthe workorder be shown in their respective text boxes on the more info form? Also, how would I make only the units for the work order selected show up on the subform (datasheet) in the moreinfo popup form?
Why do you make your life so difficult... What if you create a temporary variable called tempWorkOrder which stores the workorderID as default value.
Afterwards, create a query based on that value and use it as a datasource for your 2nd form..The tempVariable should be set at your first form on the button control by using macro, preferably.
setTempVar
name:
Expression= workorderID(or textboxN.text)
EDIT: As we spoke yesterday..
Set qdef = CurrentDb.CreateQueryDef("WorkOrderMoreInfoQ", _
"SELECT * " & _
"FROM WorkOrdersT inner join WorkOrdersQ on workordersT.WorkOrdersID=WorkOrdersQ.WorkordersID " & _
"WHERE WorkordersT.WorkOrderID = " & txtWorkOrderID.Value)

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