I am making a form in MS Access 2013 and it has 5 fields, this form is used to create an "Event." When creating an event, all 5 fields are used. However, the same form is also used to update an event. When updating an event, only three of the fields should be changed. How can I make it so that two of the fields are ignored when updating? I do not want to make a separate form for updating.
One option would be to set field.enabled = false if the primary key of a record (shoudl be a field of type autovalue) is set to a value in the Form_Current trogger, i.e. do something like this:
Private Sub Form_Current()
If IsNull(Me!pk) Then
Me!Field.Enabled = True
Else
Me!Field.Enabled = False
End If
End Sub
(just replace pk and Field with your real field names)
Related
Is there a best practice around opening a form based on recordsources whose columns are limited by the user's role?
We have some users who modify data that don't want to see the columns marking criteria for inclusion on different reports (columns with boolean values named isOnRpt1, isOnRpt2, etc. used for filtering purposes) and other users who only run reports that need to sort and filter data but not see columns used for internal calculations. Say we have 65 columns total and everyone wants to see the same 5 key columns and 10 filtering columns but some users need visibility of 30 additional columns and others want to see 20 other columns. What I have now is the God view with all of everyone's columns, and it's freaking them out.
Is there a best practice for maintaining a form for users in different roles whose datasheet view contains different subsets of columns? I'm not worried about visibility of controls on the form view, users in the reporter role won't use that view at all.
I don't want to create different forms for each role (frmDetailReporter, frmDetailWriter) whose only difference is the qry in the recordsource property. I have a main form staff in any role could use to navigate to a role-specific instance of this detail form (they need to navigate to other forms with aggregate data) but I'm not sure if I should have an entry point for each role in the form's VBA code or change the recordsource property before opening the form or if there's a better way to support users of different views of the same data source.
TIA
Let's say I've identified two roles, Reporter and Writer. I can create two queries for those roles, qryDetailReporter and qryDetailWriter with different columns. I have two buttons on a main form for the two different roles, btnDetailReporter and btnDetailWriter used to open the shared detail form, frmDetail, containing all the VBA code for all the roles. Is there a best practice for the VBA code behind frmMain.btnDetail* for loading frmDetail? I'd like to set the recordsource property to one of the two queries before loading the form, but Access forms don't work that way, so I'm thinking I could have a global variable containing a roleID referenced in frmDetail's load event that sets the recordsource property, but I'd prefer to do this without a global variable.
Here's what I have now:
' module
Public g_roleID As Integer
' frmMain
Private Sub btnDetailWriter_Click()
g_roleID = 1
DoCmd.OpenForm "frmDetail", acFormDS
End Sub
Private Sub btnDetailReporter_Click()
g_roleID = 0
DoCmd.OpenForm "frmDetail", acFormDS
End Sub
' frmDetail
Private Sub Form_Open(Cancel As Integer)
Dim objCtl As Control
Dim sTxt As String
Dim sFld As String
Select Case g_roleID
Case 0
RecordSource = "qryDetailReporter"
Case 1
RecordSource = "qryDetailWriter"
Case Else
RecordSource = "vw_detail"
End Select
On Error GoTo noFld
For Each objCtl In Controls
Select Case objCtl.ControlType
Case acTextBox, acComboBox
sTxt = objCtl.ControlSource
objCtl.ColumnHidden = False
sFld = RecordsetClone.Fields(sTxt) & ""
End Select
Next
Exit Sub
noFld:
objCtl.ColumnHidden = True
Resume Next
End Sub
I would suggest to create different queries for each role with different set of fields and change RecordSource property of form depending on user role. The form should have set of all available columns. After selecting required recordsource a simple VBA code should compare set of available fields in recordsource with set of ControlSource properties of each form's control. If the field is missing in recordsource, hide the column using ColumnHidden control's property.
There are two tables in my database: Add_New_Initiative and Add_Risk
There is a 1:M relationship between Add_New_Initiative and Add_Risk.
When adding a risk via the Add_Risk form, the user must select the related Initiative_ID from a drop down combo box.
Based on that selection, a value list titled Risk_Area, within the Add_Risk form, will either be enabled or disabled. To determine this, I need to look up the record by Initiative_ID and see what answer the user previously selected for a value list titled Tier, within the Add_New_Initiative form.
Logically, I see it playing out as such:
If Initiative_ID on Add_Risk form is Null, then Risk_Area will be disabled.
If Initiative_ID on Add_Risk form is not blank, then lookup the Tier value on the Add_New_Initiative form for the record with the Initiative_ID that the user entered/selected on the Add_Risk form.
If the Tier is 1 or 2, then Risk_Area will be enabled on the Add_Risk form.
If the Tier is 3 or Null, then Risk_Area will be disabled on the Add_Risk form.
When coding this in VBA, how would I reference the Tier value that is stored in the other Form/Table?
According to the question, you are having trouble looking/referencing data in other tables.
Perform a dlookup to look for a specific value in a table/query.
dim VarTier as integer
VarTier = nz(Dlookup("Tier","Add_New_Initiative","Initiative_ID=" & me.Initiative_ID.value),-1)
Dlookup will return:
Null if there is no record found with matching criteria, which is handled by nz thus making VarTier into -1, so you can handle it with an if statement.
If a record with Initiative_ID equal to the Add_Risk form is found, it will return the value of Tier for that record.
Then you will have to compare the result of the lookup with a simple if.
If Vartier = 1 or VarTier = 2 then
me.list.enabled = true
End If
More about Dlookup over here.
https://msdn.microsoft.com/es-es/library/office/ff834404(v=office.15).aspx
I am trying to make a subform that works similarly to a splitform.
I would use splitform but, as far as I could tell, I can't filter only the results of the datasheet portion of the split form, and not the results of the rest.
See here...
The subformPartDetail only returns records where the OrderID is equal to the mainform's OrderID. There is no filter in the mainform so it returns all partDetail Records regardless of the OrderID. In this particular instance, the main form has 21 records to cycle where as the subform only has four.
An issue occured when I use the subform for adding or deleting records. When I try to use the main form to cycle through the records, the added ones were skipped and the deleted ones threw an error telling me that the record I was attempting to go to has been deleted.
I corrected it like this by putting these on the subform events...
Private Sub Form_AfterInsert()
Dim frm As Form
Dim rst As Recordset
Set frm = Forms!PartDetails
Set rst = frm.Recordset
rst.Requery
End Sub
Private Sub Form_Delete(Cancel As Integer)
Dim frm As Form
Dim rst As Recordset
Set frm = Forms!PartDetails
Set rst = frm.Recordset
rst.Requery
End Sub
But say I try to delete the record the mainform is displaying from the subform. That code does not work and will not requery. It throws an error when I cycle away from and then back to that record.
How can I fix this?
I know I can move the record from the deleted one before it deletes by using
rst.move
I don't know where to began for testing whether the record that is being deleted is the same one that the main form is displaying.
Maybe I'm not understanding the situation correctly, but there shouldn't be any need for VBA to achieve this. If the subform is using the Link Master Fields and the Link Child Fields with your subform, those IDs would work automatically. And if you have a relationship set up between the two tables, if you delete the Order record (and have Enforce Referential Integrity: Cascade Delete) selected, it should clear out the line items automatically to avoid orphan records.
I have a form for creating new records in a table generated using SQLFORM. One of the fields of the table will not be directly exposed to the user but instead created based on the values of a few other input elements which themselves are not part of the table.
How do I add additional fields to an SQLFORM that are not part of the table and do not need to be part of the database insert? And where would be the place to calculate the non-exposed field before inserting into the database?
(A hypothetical example would be having latitude and longitude coordinate fields in the table but no address field. In this example, would need address field on create form that could be used to geocode and store coordinates in lat/lng fields)
The way I solved this was by using SQLFORM.factory instead of SQLFORM.
1. I extracted the fields defined on my table
fields = [field for field in db.customer]
2. appended the new fields I wanted
fields += [
Field('customer_type','string', label=T('Customer Type'),
requires=IS_IN_SET(customer_types, zero=None, sort=False)),
Field('another_field','string', label=T('Another Field')),
]
3. used SQLFORM.factory to generate the form
form = SQLFORM.factory(
*fields,
formstyle='bootstrap',
_class='customer form-horizontal',
table_name='customer'
)
* note the asterisk before fields is necessary
4. still used form.process().accepted but then calculated what I needed to and then manually handled the database insert
if form.process().accepted:
...
form.vars.some_nonwritable_field = calculate_complicated_value()
db.customer.insert(**db.customer._filter_fields(form.vars))
...
_filter_fields prevents the dynamically added fields from being part of the insert.
This way I could add additional field to the form that were validated but not part of the insert.
In recent versions of web2py you can do it shorter:
form = SQLFORM.factory(
db.table,
Field('my_field_1'),
Field('my_field_2'),
)
I need some help with Access 2010 forms. My form has a number of fields (from one table). One of the field is a logical field. If the user selects true, then the next field (text field) should be enabled. This is working fine - I created an after update event procedure. The problem I have is if the user accidentally selects true, and then selects a value/s for the text field (the text field looks up a query - it is a look up field and it can have more than one value - the user can select/check as many from the list and they will be stored to the text field, separated by coma).
How will I set the text field (look up field) value to blank, if the user goes back and set the logical field to false? me.textfield.value = null gives an error.
Can anyone please help me? Thank you!
Just keep in mind that in fact a multi-value column is in fact a normalized data table.
So the display looks like this:
To clear the records selected in this child table, which is your mult-value selection, you can use this code behind the above button:
Dim rstChild As DAO.Recordset
Set rstChild = Me.Recordset.Color.value
Do While rstChild.EOF = False
rstChild.Delete
rstChild.MoveNext
Loop
Me.Color.Requery
An easy way to insert a blank lookup field is to select the field in design view and click on the lookup tab in the field properties. Before the first entry in Row Source insert the following " ";