Requery a Sub Table in Access Using VBA - ms-access

http://i.stack.imgur.com/NhBss.jpg
I have on the f3AgreeService form the Agreement itmes(parent) and Service details(child). I used a sub table (tService) rather than a sub form to show service info as I want to take advantage of the subdatasheet function that is available only to tables (the + to expand function. The subdatasheets can be linked to either facility/DHB info of the service)(1 to 1-many).
I want to be able to use a button (see facilities/see DHBs) to switch between two different sub data sheets for tService sub form. The code is as follows.
The problem is that sub data sheet will not automatically update, until you close and reopen the whole form. I could for sure close and open the form every time the user clicks. But it seems ugly. Is there a way just to requery or update the tService for the sub datasheet information to take effect?
Private Sub cmdDHBs_Click()
Dim MyDB As DAO.Database
Set MyDB = CurrentDb
MyDB.TableDefs("tService").Properties("SubDataSheetName") = "Table.tServ_DHB"
MyDB.Close
Call RefreshTable 'How?
End Sub
Those I have tried and not worked:
Forms!f3AgreeService.Refresh
Forms!f3AgreeService.Recalc
Forms!f3AgreeService.Query
Forms!f3AgreeService.Repaint

If you really insist on doing this, and I do not recommend it, you can reload the source object of the subform after you have change the subdatasheet:
Me.MySubformName.SourceObject = "Table.tService"

Related

Passing keys from form to sub-form in Access

I'm using a sub-form to assign multiple tasks at the same time. This sub-form is placed on a form that has common details applicable to all the tasks there. For instance: Customer, Product Code, Part Code etc., Both the form and the sub-form feed the data to the same table. These forms are linked with one of the keys - Line Item, which is present on both the form and the sub-form. The other two keys are Task Title - placed on the sub-form, and Stage ID placed on the main form. Line Item is configured in a way that it populates the value from another open form for both the main form and the sub-form.
But Access isn't allowing me to add any details whatsoever to the sub-form. It gives me the error "You must enter a value for 'TableName.LineItem' field.
Kindly advise.
Two Approaches:
Select Table A and hit create form on the ribbon. Then do the usual prettification like deleting id columns, setting the forms format to continuous forms, and replacing textboxes with combo- boxes where appropriate.
First Approach is put unbound controls and a button in the header. Then insert the values from the controls in the button click event
Private Sub cmbAddRecord_Click()
Dim db As Database
Set db = CurrentDb
Dim rs As DAO.Recordset
Set rs = db.OpenRecordset("TableA")
rs.AddNew
rs!A = Me.txtA
rs!B = Me.txtB
rs!C = Me.txtC
rs.Update
Me.Requery 'show changes
rs.Close
db.Close
Set rs = Nothing
Set db = Nothing
End Sub
You can also insert values while actively entering the data for instance
Private Sub A_AfterUpdate() 'A is the TextBox in the detail section that is bound to A in TableA and so forth
Me.B = B.Parent!txtB
Me.C = C.Parent!txtC 'Tip use Me.MyControlName.SetFocus to select a control
Me.Refresh 'show changes
'tip you can also put this code in hotkeys https://learn.microsoft.com/en-us/office/vba/api/access.form.keydown
End Sub
'

VBA update subform recordsource

Quick and easy one (Probably) for you.
My home form has a lot of sub forms within tab controls. Some of these sub-forms have their own sub-form based off a query and that query has criteria input control on the parent form.
As you can imagine upon loading the home form I would have to enter all the parameters in pop-up boxes as the subforms/queries are also loading.
My work-around for this is setting those query sub-forms recordsource to ""
Then once the user control that applies the where condition is updated it changes their record source to the query.
Only, my code (Below) doesn't work. And After half hour of staring at it I can't figure out why, it produces no errors it just does nothing.
All fields/records just have #NAME?
Private Sub txt_EventID_AfterUpdate()
Me.txt_forcefocus.SetFocus
Me.sub_SpeakerOnboarding.Form.RecordSource = qry_SpkrOnboard
Me.Requery
End Sub
I also tried the following:
Private Sub txt_EventID_AfterUpdate()
Me.txt_forcefocus.SetFocus
Me.sub_SpeakerOnboarding.Form.RecordSource = qry_SpkrOnboard
Me.Refresh
End Sub
Again no results, nothing... All fields/records just have #NAME?
Hopefully I've missed something simple otherwise I'll have to rethink the entire form designs
RecordSource is a string:
Private Sub txt_EventID_AfterUpdate()
Me.txt_forcefocus.SetFocus
Me.sub_SpeakerOnboarding.Form.RecordSource = "qry_SpkrOnboard"
End Sub
To refer to a control on the subform:
Value = Me![SubformControlNAME].Form![txt_EventID].Value

Open multiple forms issue in Access

I got query to make some modification that enable user to open multiple instances of the form when they do search data. I got manage to create a new module following Allen Browne guide and now I can open multiple instances of the spreadsheet which is good step forward but I cannot find solution how I can open that specific form.
In module I have got following code:
Public clnClient As New Collection 'Instances of frmClient.
Function OpenAClient()
'Purpose: Open an independent instance of form frmClient.
Dim frm As Form
'Open a new instance, show it, and set a caption.
Set frm = New Form_SurgeriesForm
frm.Visible = True
frm.Caption = frm.Hwnd & ", opened " & Now()
'Append it to our collection.
clnClient.Add Item:=frm, Key:=CStr(frm.Hwnd)
Set frm = Nothing
End Function
And under my button I replaced bit:
DoCmd.OpenForm "SurgeriesForm", acNormal
Forms!SurgeriesForm.Requery
.. and usef following code:
ModuleInstances.OpenAClient
I recon I need to add / change somehow the code below to be able to open multiple instances but do not have idea how to do it.
DoCmd.OpenForm "SurgeriesForm", acNormal
Forms!SurgeriesForm.Requery
I appreciate for any help with this as i got stuck and do not know how I can achieve this.
I think this is what you want?...
With the button on your SurgeriesForm add this code to the On Click event to open a new instance of the form:
Private Sub Command8_Click()
OpenAClient
End Sub
This will create a new instance of the form each time you click the button.
Next, add a blank combo-box to the form and change it's Row Source Type to Value List.
Add this code to the form:
Private Sub Combo9_GotFocus()
Dim frm As Variant
Combo9.RowSource = ""
For Each frm In clnClient
Combo9.AddItem frm.Caption
Next frm
End Sub
Now, when you click the drop-down it will list each form that you have created an instance of.
Finally, add this code to the form:
Private Sub Combo9_AfterUpdate()
clnClient(Combo9.Value).SetFocus
End Sub
Now, selecting a form name from the combo-box will move the focus to that form.
NB: You'll need to update the name of the controls to match yours.
NB2: Remember to open the first form using OpenAClient or it won't get listed in the combobox (as it's not in the collection).

Requery only one record in a datasheet view form (MS Access)

I have a rather simple looking problem but it turned out to be more complicated than I thought.
I have a field (column) in my subForm which is a ComboBox.
I have a field (column) in another subForm by which I would like to filter this comboBox.
Basically, the comboBox before filtering has some 600 records, too many to scroll by casual user. I created a simple subForm whose field is linked to a mainForm and this works perfectly (ie. the selected record-field-ID is displayed on mainForm).
Now what I want is that this comboBox is filtered by this record (ie. only showing relevant fields). The problem is that if I simply Requery it with this given filter, the other fields show up blank.
I want this filter to apply only to NEW RECORDS comboBox, not the whole datasheet view.
What I did is:
Private Sub Sekacie_Operacie_GotFocus()
Dim SQL As String
SQL = CurrentDb.QueryDefs("qrySekacie_Operacie").SQL
Me.Sekacie_Operacie.RowSource = Replace(SQL, ";", "") & " WHERE Sekacie_Operacie.Operacia_ID = " & Me.Parent.Form!txtOP_ID
Me.Sekacie_Operacie.Requery
'works kinda as intended
End Sub
Private Sub Form_AfterInsert()
Me.Sekacie_Operacie.RowSource = CurrentDb.QueryDefs("qrySekacie_Operacie").SQL
Me.Refresh
End Sub
And when I select the record in my filter subForm:
Private Sub Form_Current()
Dim SQL As String
SQL = CurrentDb.QueryDefs("qrySekacie_Operacie").SQL
With Me.Parent.Form.subSekacie_Operacie_Modelu
.Form!Sekacie_Operacie.RowSource = SQL
.Form.Refresh
End With
End Sub
However, this workaround still shows "blank" records sometimes (I have to refresh the form by clicking different record) and I find it strange I had to go all the way to do this. Is there no simpler way of accomplishing this?
A couple of immediate things:
No need to refresh the whole sub form, just refresh the control.
Private Sub Form_AfterInsert()
' Me.Refresh ' replace this line with the following line
Me.Sekacie_Operacie.Refresh ' or is it Requery I can't remember
End Sub
The following code can be improved
Private Sub Form_Current()
Dim SQL As String
SQL = CurrentDb.QueryDefs("qrySekacie_Operacie").SQL
With Me.Parent.Form.subSekacie_Operacie_Modelu
.Form!Sekacie_Operacie.RowSource = SQL
.Form.Refresh
End With
End Sub
' by using code like this
Private Sub Form_Current()
Dim SQL As String
SQL = CurrentDb.QueryDefs("qrySekacie_Operacie").SQL
me.Sekacie_Operacie.RowSource = SQL
' I think the above line will cause the combo to refresh
' anyway (in some version of accees it might not,
' but, if needed add the following line
' me.Sekacie_Operacie.refresh
End Sub
The following line has the potential to produce and error
(perhaps when the main form is a new record)
WHERE Sekacie_Operacie.Operacia_ID = " & Me.Parent.Form!txtOP_ID
replace it with
WHERE Sekacie_Operacie.Operacia_ID = " & nz(Me.Parent.Form!txtOP_ID,0)
Note that adding such code will stop the subform from working independently of the main form and will require it to have a parent form.
You could get around this by using:
if not me.parent is nothing then
WHERE Sekacie_Operacie.Operacia_ID = " & nz(Me.Parent.Form!txtOP_ID,0)
end if
About your approach.
I find it a bit weird what you are doing. Consider this:
Say the query qrySekacie_Operacie returns 100 rows when run without any WHERE clause. When you are inserting a record into the subform you want to limit the combo by adding a WHERE clause that uses a value in the parent formMe.Parent.Form!txtOP_ID) , this might limit the number of rows displayed to 10.
It is worth noting that if any of the other rows in the subform contain value other than one of these 10 the combo will display a blank value. I think this is what you are experiencing.
My first question was why not use the on current event of the parent form to change the subform combo box SQL. It appears this is not what you need.
It appears that other values can exist in the dataset of the subform and that you only want certain value to be enterable in this subform but you want the subform to display any values that have been entered.
So that gets interesting. Here's what I would do:
Create a hidden combo control (with no control source) that is only visible when a new record is being entered. When this new combo is shown the other one is hidden.
Set up this new combo with the required SQL
use a before insert event to copy the value form the new combo to he old one.
Easy peezy?
Let me know ho you get on.
One other thing
I like to Ensure a subform encapsultes code that operates on it "private" controls.
As I general rule of thumb, where possible (which is 99% of the time), I like to try and keep subforms so that they will work as forms in their own right. They can be though of as an object, so if they work independently, it is an indication that their code has been encapsulated within their own code module.
So if the form has me.form.parent = nothing then the code behaves differently as it is a independent form.
So rather than the parent form code module having code that sets the SQL of the subforms combo, I would write a public sub in the subforms module (called SetComboSQL) that can be called (with the appropriate parameters. ie OPid ) to set the combo SQL.
To call the procedure in the parent form I would add
Private Sub Form_Current()
Me.MySubformControlName.Form.SetComboSQL(OPid:=Me.txtOP_ID)
End Sub
' note that intellisense won't pick up this proeprty BUT it will work. Use debugger to check it out.
I hope you find this tip useful (as it can be a massive headache saver. THE MOST BASIC OO PRINCIPAL is encapsulation. An object should own all the code that effects it's properties (and controls).

MS Access 2007 Converting forms into sub form - "form not found" issue

So I recently have been trying to incorporate more sub forms to make the UI more friendly. So I have a pre developed form that runs some VB, so for examples sake lets just say that it runs SQL statement, returns the recordset, and fills text boxes with the data (because this is sort of an interactive dashboard concept:
dim db as database
dim rs as recordset
dim sql as string
set db = current db
sql = "SELECT * FROM tblMain;"
set rs = db.OpenRecordSet(sql)
rs.movefirst
[forms]![DashboardSubName].txtValue1 = rs!Value1
rs.close
set rs = nothing
set db = nothing
with error handling that returns a error "DashboardSubName" not found. So orginally this form was its own form, and opening it by itself it works fine, but once I use it within the parent form i get this error.
im sure it is simply something i am not aware of, but what gives?
thanks guys
justin
When a Form is loaded as a sub-form, it is referenced as if it were just another control on the Main Form - it is no longer part of the global Forms collection.
So the correct reference should be:
Me!DashboardSubName.Form.txtValue1
where DashboardSubName is the name of your sub-form control.
Assuming the code you showed us is part of the subform, rather than the parent form, replace
[forms]![DashboardSubName].txtValue1 = rs!Value1
with
Me.txtValue1 = rs!Value1
The reason for the syntax here is that the subform control is distinct from the subform embedded inside it. The subform control has properties of its own (limited in comparison to the subform itself), and to get to the properties/methods of the subform embedded in it you have to specify that you want the form that the subform embeds.
Me!MySubformControl
...is the subform control.
Me!MySubformControl.Form
...is the form embedded in the subform control.
Last of all, I really wonder why you're walking a recordset to update data in a subform. This is not normal practice, though it's tangential to your actual question.