Assign value to report text box on open - ms-access

Private sub Report_Open (Cancel As Integer)
Dim var1 As Variant
Var1=DLookup(“[Menu_Item]”, “[Thaw_Tags]”, “[ID] = 1”)
Me.Text34.Value= var1
End Sub
I’m trying to get a textbox to get information from a table on open, using a Report. Yet when I open the report i get the error “you can’t assign a value to this object”. What am I doing wrong?

Your dlookup where condition is wrong. It must be
result= dlookup (retrievingColumnName, TableName, [whereCondition]).
Where WhereCondition could be:
NumberColumn=1
TextColumn='This is a text'
Search for dlookup and you will see many examples.
I see you have modified your question. As suggested, controls on "on open" might not be ready for you take values. You can try to move your code to "on load" or try to set focus and then asssign value.

Related

Access VBA - Turn off aggregation when opening form/sub-form

What I'm trying to do is, whenever a user opens a form (and the sub-form that opens by default), I want to search through all the columns (controls?) on the form, check to see if they are currently set to aggregate (sum, count etc.) with Access' built-in Totals row, and if so, set them to not aggregate.
The reason for this is there are several millions records that are stored, so when someone queries it down to 3-4 and turns on Sum, then closes it, when the next person opens it, it tries to sum millions of numbers and freezes up. The form displays the queried results from a table which is populated via SQL (I think, if that sentence makes sense). Here's what I have so far:
Private Sub Form_Load()
'this form_load is in the UserApxSub sub-form, for reference
Call De_Aggregate
End Sub
Private Sub De_Aggregate()
Dim frm As Form, con As Control
Set frm = Forms!UserAPX!UserApxSub.Form!
For Each con In frm.Controls
If con.ControlType = acTextBox Then
If con.Properties("AggregateType").Value <> -1 Then
'crashes on following line
con.Properties("AggregateType").Value = -1
End If
End If
Next con
End Sub
I have not so much experience in Access VBA (usually work in Excel VBA) so please forgive me if I'm entirely off the mark here. The command con.Properties("AggregateType").Value = -1 doesn't throw an error, but Access just straight-up crashes when reaching that line specifically.
I've tried a number of variations in the syntax with no success, and I've also tried looping through other elements of the file (tabledefs, querydefs, recordsets, etc.) as well to see if I'm trying to change the wrong value, but the controls on this subform are the only things in the entire .mdb file that results when I search for elements with the AggregateType property.
I switched out the line that errors with Debug.Print con.Name & " - " & con.Properties("AggregateType").Value and I can check, have nothing return anything other than -1, turn on aggregation in some column manually, and have it return the correct result (0 for sum for example), so I think I'm looking in the right place, just missing some key factor.
I've been working on this for a couple weeks with no success. Any way to fix what I have or point me toward the right direction would be greatly appreciated!
This is not necessarily the answer but I don't have enough reputation
to give a "comment"...
I tried your scenario and verified can change the property value as you are however I did not iterate through all controls and simply used an onDoubleClick event on a column to simulate.
I would suggest trying to fire your sub with Form_Open or Form_Current to see if the property is getting reset after your code has been called for some reason.
UPDATE:
You are referencing the "Subform" Object of your main Form:
Set frm = Forms!UserAPX!UserApxSub.Form!
Try referencing the actual UserApxSub FORM explicitly.
Something like Set frm = Forms!UserApxSub! (assuming UserApxSub is the name of the form)
then stick in the Form_Open of your main form:
Private Sub Form_Open(Cancel As Integer)
'// the following would set a single control only. You can add your loop through all controls
Me!{your control name}.Properties("AggregateType").Value = -1 '// set control in your main form
Form_UserApxSub!{your control name}.Properties("AggregateType").Value = -1 '// set control in your "sub" form
End Sub

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).

Access 2013:Trying to write macro to update form fields from a query result

I am trying to create a macro to update the value of a field in a form based off the results of a query.
I am entirely new to working with vba in Access so I apologize if I am asking a basic question.
I should mention, the "test" query returns exactly one result. It is essentially used similarly to a VLookup.
Currently My code is thus:
Private Sub UpdateBasic_Click()
Dim bucket As String
DoCmd.OpenQuery "test", acViewNormal, acReadOnly
'this line is meant to record the result of the query into a variable. It is not working but I haven’t found the right command to get it to pick up the data yet.
bucket = A1
DoCmd.Close acQuery, "test", acSaveNo
DoCmd.OpenForm "BasicData", acNormal, , , acFormEdit, acWindowNormal, "Global_ID = 'sdkfa'"
'this line is meant to update the value of the field on the form.
DoCmd.SetProperty testfield, acPropertyValue, bucket
End Sub
I am having no luck getting the SetProperty command to work at all. It is consistently telling me I have a data type mismatch regardless of whether I try to give it a variable like bucket or a value like 10. Error message is as follows:
Run-time error ‘2948’:
An Expression you entered is the wrong data type for one of the arguments.
Any and all help would be appreciated.
If you're simply trying to assign the result of a query to the value of a field in a form, I'd recommend a DLookup() function. You can use it like this (assuming the form's control is a textbox):
Me.TextBox.Value = DLookup("FieldName", "QueryName")
More elaborate solutions would involve recordsets, etc. but if you're looking for a quick, simple solution this should do just fine. Hope that helps!

MS Access TextBox Value is always NULL

I am doing some work for someone that insists on using MS Access. I don't usually use it so I am a bit new to the whole control structure and best practices. What I am trying to achieve is to have a filter textbox on a form which, when a value is entered, it will filter the rows in the detail section. That seems like a straightforward use case. I initially tried the following behaviour as the event handler for the On Change event:
Private Sub FilterGrid()
Me.Text32.SetFocus
If Not IsNull(Me.Text32.Text) And Me.Text32.Text <> "" Then
Me.Filter = "JobNumber LIKE '*" & Me.Text32.Text & "*'"
Me.FilterOn = True
End
Else
Me.FilterOn = False
End If
End Sub
This worked perfectly until I typed something that didn't have any rows matching and the whole thing exploded with this error (and was unrecoverable without closing the form):
Run-time error '2185': You can't reference a property or method for a control unless the control has the focus.
I did some reading around and the general opinion was that .Text should not be used and .Value (or simply the Text32 without a property) should be used. That produced some very strange behaviour. The Text32.Value is ALWAYS null. I have a watch window and I can see that for the normal behaviour, Text32.Text has an actual value, but Text32.Value is NULL.
Obviously I am doing something wrong, but I don't have enough experience with Access to know what it is.
Just as an aside, another suggestion was to do Text32.SetFocus right before accessing the Text property. This doesn't resolve the error I mentioned. It still throws the exact same error.
Is anyone able to point me in the right direction here?
As you found out, the textbox's Value is only set after the control loses focus.
Conversely, the Text property is only accessible while the control has focus.
The Value property is defined as the default member for controls; that means Text32 will be implicitly the same as Text32.Value, however, depending on the context,Text32 can sometimes refer to the control itself, not just its value.
All these discrepancies can sometimes be infuriating.
To go back to the matter at hand: you have 2 ways to handle filtering.
if the list to filter is large, it's probably better that the user type their filter, then press ENTER to validate it.
if your list is not too large, you can implement filter as you type.
First case, wait for user input to be validated by ENTER.
Say your filtering textbox is called txtFilter and is located on a form whose subform is showing a datasheet (or continuous form) that you want to filter.
All you need to do is wire the textbox OnKeyDown events as such:
' We will only perform the filter if the user press the ENTER key
Private Sub txtFilter_KeyDown(KeyCode As Integer, Shift As Integer)
Select Case KeyCode
Case 13, 9
KeyCode = 0
QuickFilter
End Select
End Sub
' Perform the actual filtering on the subform
Private Sub QuickFilter()
Dim sql As String
Dim filter As String
If txtFilter.Text = vbNullString Then
' Reset the filter if the textbox is emtpy
SubForm.Form.FilterOn = False
Else
'Some common substitutions that users may have already inserted as wildchars
filter = Replace(txtFilter.Text, "%", "*")
filter = Replace("*" & filter & "*", "**", "*")
' We construct the filter SQL
sql = "([JobNumber ] LIKE """ & filter & """)"
sql = sql & " OR ([ProjectCode] LIKE """ & filter & """)"
sql = sql & " OR ([SupplierName] LIKE """ & filter & """)"
'... Add as many columns to filter on as you want
' Assign the filter to the subform
SubForm.Form.filter = sql
SubForm.Form.FilterOn = True
End If
End Sub
Second case, filter as you type
Well, it's fairly easy, we just need to add to the above solution a way to track changes as the user is typing.
This is best done through the OnChange event of the texbox.
Private Sub txtFilter_Change()
QuickFilter
End Sub
That's all you need to add.
dont use .text property
instead use .value property
text3.value=text1.value+text2.value
you dont need setfocus like .text property everytime.
it works perfectly....vba ms access

Access 2010 VBA ControlSource Loop

I have multiple fields on a form that have no values associated with them until data is entered into that field. At which point those controls have the #Name? value. All I'm trying to do is hide the fields using a loop as opposed to writing If statements. Here is the code working with a single If statement to hide said field/fields.
If Not Me.txtField.ControlSource = "#Name?" Then
Me.txtField.ColumnHidden = True
End If
I can't seem to figure out how to hide multiple controls that have the #Name? flag. Any help would be appreciated.
Dim ctl As Control
Dim ctlError As String
ctlError = "#Name?"
For Each ctl In Me.Controls
If Not ctl.ItemsSelected(txtField) = ctlError Then
ctl.ColumnHidden = True
End If
Next ctl
EDIT:
On the main form there is a subform with a cross tab query. But the problem is results on the query are populated from a combobox. So I've added fields that are not yet available in the query to the subform and end up with #Name? Attached is a screenshot to better illustrate the issue.
There is a 90% chance I'm going about this process wrong, so it's a learning process right now.
It would be easier to address this question if you described the specific errors that are raised by your code. This answer assumes that the control in question is a TextBox.
"#Name?" means that a control's ControlSource refers to a field that is not in the form's RecordSource. For example, if your query has two fields (ID and BirthDate, for example) and your form has three controls, with ControlSource of "ID", "BirthDate", and "BirthCountry", then the control whose RecordSource is "BirthCountry" will show "#Name?". However, its Value is not "#Name?". Rather, calling the Value property raises error 2424 (with the rather unhelpful message "The expression you entered has a field, control, or property name that Microsoft Office Access can't find").
The only way I know to check for the string "#Name?" is through the control's Text property, which is only available when the control has the focus, so that's not much help. If you retrieve the value of the ControlSource property, you'll get "BirthCountry" (of course). So you could check all ControlSources on your form against the fields of the form's RecordsetClone (add error handling, please):
For Each ctl In Controls
If Not RecordSourceContains(ctl.ControlSource) Then
ctl.Visible = False
End If
Next
Function RecordSourceContains(strFieldName as String) As Boolean
Dim fld As Field
For Each fld In RecordsetClone.Fields
If fld.Name = strFieldName Then
RecordSourceContains = True
Exit For
End If
Next
End Function
You'll probably want to do some other bookkeeping. For example, you'd want to check for expression control sources (which begin with "=") because they won't be in the RecordSource. You'll also either need to handle error 438 (Object doesn't support this property or method) or check each control's type to make sure it has a ControlSource property.
In design view for the form, what does the field say for Control Source? It should be blank, meaning the form is unbound. If it's not, then that explains #Name.
More information: http://www.databasedev.co.uk/unbound-forms-add-data.html
Here is code I use to take care of that:
Sub setControl
'' You can use this in your loop
Call FieldEnable(subFrm, "boxQty", booSellSet)
End Sub
''----------------
Private Sub FieldEnable(subFrm As Access.Form, strCtlName As String, _
booEnableMe As Boolean)
On Error GoTo errHandler
subFrm(strCtlName).Enabled = booEnableMe
subFrm(strCtlName).Visible = booEnableMe
errExit:
Exit Sub
errHandler:
If Err.Number = 2164 Or Err.Number = 2165 Then ''control has the focus
Resume Next
Else
DoCmd.Hourglass False
Screen.Application.Echo True
MsgBox "Problem with control named " & strCtlName
Resume errExit
End If
End Sub
I have to adjust many fields on the form, so this is very reusable. I might be turning them "on" or "off"; this takes care of either. Let me know if you have questions.
It all boils down to this method for hiding the field:
Control.Enabled = False
Control.Visible = False
Delete the field Black from table.
And then make make again the Black field in your table.