Access Calculate Next Value (lookup value}? - vba

I need to get a value from a textbox in a report's detail section which will give me multiple values. I need to get each of those values into VB to do some calculations... I can pull a value from forms with ChildID = Forms!FRM_Child!ChildID.Value, but when I put
Private Sub Report_Open(Cancel As Integer)
Dim ChildID as Integer
ChildID = Reports!RPT_Due_Date!ChildID.Value
End Sub
it crashes and says "Run-time error '2424': The expression you entered has a field, control, or property name that Microsoft Access can't find."
I've checked and double checked the names. The thing I figure is that somehow because it's in the detail section with multiple values it crashes. Any ideas?
ChildID Last_Asmt_Type Last_Asmt_Date Next_Asmt_Type Next_Asmt_Date
1 Initial Evaluation 1/5/15 Periodic Review 5/5/15
2 Periodic Review 2/5/15 Annual Review 6/1/15
3 Annual Review 3/5/15 Periodic Review 7/1/15
What I want to do is get the Last_Asmt_Type and then with if/then rules select the Next_Asmt_Type ie If Last_Asmt_Type is Periodic Then Next_Asmt_Type is Annual....
How would I do this with a lookup value?

In Report_Open(), the textbox exists as control, but it has no value yet.
Your code would work in Report_Load(), but as you already know, it would be pointless because you would only get the first value.
If you want to read all values, don't try to read them from the report textbox, open a recordset on the report's data source. Like this:
Dim RS As Recordset
Set RS = CurrentDb.OpenRecordset(Me.RecordSource)
Do While Not RS.EOF
Debug.Print RS!MMI
RS.MoveNext
Loop
RS.Close
But:
Most probably there is an entirely different and better way to do what you want. What kind of calculations are you doing?

Related

MS Access 2019: Can't populate a form field using SQL query in VBA

I want to auto-populate a field in my form based on the results of an SQL query. I'm just not sure of the proper syntax to get it to properly read the query. This is what I've got, but it's not returning the value of the query, it's actually just returning the text of the query itself.
Private Sub PurchBatchNo_Enter()
Dim MostRecentPurchBatch As String
MostRecentPurchBatch = "SELECT Max(PurchaseBatchNo) FROM purchases"
Me.PurchBatchNo.Value = MostRecentPurchBatch
End Sub
I'm sure the issue has to do with the quotation marks, but it doesn't work without them either, and I'm not sure how to write it properly.
Thanks for being here for beginners like me!
All your code does is set a variable to a string of characters then attempts to set value of field with that string.
But why would you want to populate field with a value already used in a record? Most likely you need to increment by 1.
To use an SQL statement, would have to open a recordset object then reference field of recordset.
Private Sub PurchBatchNo_Enter()
Dim MostRecentPurchBatch As DAO.Recordset
If IsNull(Me.PurchBatchNo) Then
Set MostRecentPurchBatch = CurrentDb.OpenRecordset("SELECT Max(PurchaseBatchNo) AS MaxBatch FROM purchases")
Me.PurchBatchNo = MostRecentPurchBatch!MaxBatch + 1
End If
End Sub
However, pulling a single value from table is what domain aggregate functions are good for.
Private Sub PurchBatchNo_Enter()
If IsNull(Me.PurchBatchNo) Then Me.PurchBatchNo = DMax("PurchaseBatchNo", "purchases") + 1
End Sub
Instead of using VBA procedure, consider just setting DefaultValue property of textbox bound to PurchBatchNo field with the DMax() expression. As soon as record is initiated by input to another textbox, the PurchBatchNo will populate.
If user should not be able to edit this value, set textbox as Locked Yes and TabStop No and use a different event for the VBA code if you go with VBA.

MS access check column value and change another

I have an ms access database with some yes/no columns I want to check and set the value of a third. The statement should be something like the following
if !col1 && !col2:
col3 = no
else:
col3= yes
I keep searching but don't really understand vba and can't find what I need .. Mostly a segment of an answer to something else that I cant make work. Currently trying to create it in the "module" section is that even right? Would be best if this could be done automatically as those columns are changed or maybe run once and do all rows. Please help me get on the right track, any help greatly appreciated.
Here is what I would do:
1- Create a form and add at least one command button on it. Name it cmdMyButton or cmdAnythingThatYouWant (cmd is the prefix used in examples from Microsoft for command buttons)
2- in the design view, double click the command button so to pop the code window
3- In the onClick() function, write the code that opens up a recordset for your table, loop through records and for each row, verify the value of those 2 columns and update if needed. (look at the documentation for DAO.recordset)
Let's say you have an Access table named Table1, with some Access fields:
The following Access SQL statement will update the value of col3 based on the values of col1 and col2, for every row in Table1:
UPDATE Table1
SET col3 = NOT col1 AND NOT col2
There are a number of ways to leverage this SQL statement:
You can paste it into the Query Designer in SQL view, and execute it via the Access UI
You can run it as part of an Access macro
You can execute it in VBA, using ADO or DAO
You can execute it in VBA, using the DoCmd.RunSQL method
Instead of VBA, you can use another Automation-supporting programming language
I would just create this on a calculated column in your DB table. See screen shot below:
Notice in the properties I set a formula to acquire the desired results based on the first 2 columns. The "Result type" is set to yes/no to mimic the yes/no field. Only difference is, the third column will display a -1 (True) or 0 (False). but when displaying this information on a form, you can have it display the information in a checkbox fashion. The calculated field is also ideal cause it will only update the third column when the target record is updated, not updating the whole table, very useful if the table size starts holding over 100k records.
If you want a VBA code, then you will need a trigger. I'm assuming its a button on the form, if not, you can always change the below code to match the event you want it triggered on. The below code is also a module that can be called/used for any trigger. The code is also assuming you have a primary key.
Public Sub UpdateThirdColumn(ByVal RecordPK As String) 'RecordPK is a passed variable
'that is the primary key identifier to find the
'record in the table
'Set variavble name for SQL statement, gives you one place to update instead of hunting through code
Dim strSQL As String
'Creates the SQL string in the variable assigned
strSQL = "UPDATE {YourTableNameHere} " & _
"SET {YourThirdFieldNAmeHere} = True " & _
"WHERE ((({YourFirstFieldNAmeHere}) = True AND ({YourSecondFieldNAmeHere}) = True AND ({YourPrimaryKeyFieldHere}) ='" & RecordPK & "'));"
'Executes the SQL statement, dbFailOnError will fail if problem exists in SQL statement
CurrentDb.Execute strSQL, dbFailOnError
End Sub
'Use this code if you have a button to trigger event
Private Sub YourButton_Click()
Call UpdateThirdColumn(Me.YourPrimaryKeyControlName)
End Sub
'Use the bottom 2 codes if you want the update for each check box to be checked and update
Private Sub FirstFieldName_AfterUpdate()
Call UpdateThirdColumn(Me.YourPrimaryKeyControlName)
End Sub
Private Sub SecondFieldName_AfterUpdate()
Call UpdateThirdColumn(Me.YourPrimaryKeyControlName)
End Sub
Let me know if you need more assistance or explanation and I will be glad to help.

combobox.column property returns invalid use of null in vba

I am a database//Access noob, so bear with me. I have a database set up to keep track of Consultants and their Vendors for a tech consulting company. Some consultants are their own vendors, and some have third-party vendors that handle their contracting. In the case where a consultant is also their own vendor, the contact information is the same for both. Contact Info is stored in a separate table, with primary key ContactID and foreign key fields for ConsultantID (primary key in ConsultantT) and VendorID (primary key in VendorT).
In the case that the relevant Contact Info has already been entered on one of the forms, I want to be able to select the already existing Contact Info record and tell the database to add the other foreign key ID field to the existing record based on the record on the main form. So, for example, if I have already entered Contact Info for Consultant A via the Consultant form, when I open the Vendor form to add Consultant A's vendor I want the option to select "Consultant A" from a combo box and have their info populate VendorsF's Contact Info form while adding the VendorID to the already existing Contact Info record for Consultant A.
I think I've almost worked it out, but am stuck on one last thing. Right now I have a popup form (ChooseConsultantInfoF) for selecting an existing ContactInfo record. On that form I have a search combobox (SelectConsultantCombo) to select the existing record, and a command button (SaveConsultantbtn) which I've tried to code to Update the ContactInfoT and add the VendorID from the current record on the VendorsF to the existing record in ContactInfoT. Here is the all of the code for the popup form:
Option Compare Database
Option Explicit
Private Sub SaveConsultantbtn_Click()
Dim stupid As Long
stupid = SelectConsultantCombo.Column(0)
DoCmd.RunSQL "UPDATE ContactInfoT SET VendorID = (Forms!VendorsF!VendorID) Where ContactInfoID = " & stupid & ";"
End Sub
Private Sub SelectConsultantCombo_AfterUpdate()
Dim rst As DAO.Recordset
Set rst = Me.RecordsetClone
rst.FindFirst "ContactInfoID = " & Me!SelectConsultantCombo
Me.Bookmark = rst.Bookmark
leave:
Me!SelectConsultantCombo = Null
If Not rst Is Nothing Then Set rst = Nothing
Exit Sub
End Sub
When I try to put it into action, I get Error 94: Invalid use of Null and it pulls up
stupid = SelectConsultantCombo.Column(0)
I know the code block works apart from that--I tried the Click event once with a numeric value instead of the variable:
Private Sub SaveConsultantbtn_Click()
DoCmd.RunSQL "UPDATE ContactInfoT SET VendorID = (Forms!VendorsF!VendorID) Where ContactInfoID = 1 ;"
End Sub
without any trouble, so the issue must be in calling the combobox's column.
I also tried defining the variable with Nz to allow Null:
stupid = Nz(Me.SelectConsultantCombo.Column(0), 0)
and that gets the code working also, but still doesn't save my VendorID to the record in ContactInfoT. None of the columns in the combobox contain Null values (none that I can find, anyway). Dunno if this is useful, but the Row Source of the combobox is:
SELECT ContactInfoT.ContactInfoID, ConsultantT.ConsultantID, ConsultantT.FirstName, ConsultantT.LastName FROM ConsultantT INNER JOIN ContactInfoT ON ConsultantT.ConsultantID = ContactInfoT.ConsultantID ORDER BY ConsultantT.[LastName], ConsultantT.[FirstName];
Does anyone know why Access doesn't recognize my combobox.column property? Or is there another way to write this up in VBA to avoid this error?
First try stupid = Me.SelectConsultantCombo.Column(0) (you are missing the Me. part).
But what you should really do is make sure your bound column on the combo box is set correctly and just use stupid = Me.SelectConsultantCombo
I took Me!SelectConsultantCombo = Null out of the combo's afterupdate and it works perfectly now! Of course if I have the combo set to null somewhere in the code it's going to pull up null somewhere else, d'oh!

Customizing an access query based on values of various checkboxes

I'm new to access, and I need to selectively query a database based on a set of checkboxes. For example, If a checkbox called basketball is checked, I'll want to find all records that have that in their Name field. If basketball and baseball are checked, I'll want to find records for both basketball and baseball. The current way we have of doing this is ugly and inefficient, and I'm thinking that this is a fairly common problem to have, so there must be a better way of solving it. I've seen similar things online, but these deal with only one checkbox (not 10 or so like in our form) and they simply aren't very helpful.
Thanks
I'll make a few assumptions, here. I'll assume you have 4 sports; Baseball, Basketball, Football and Hockey. You can add more if you like.
I'll assume you have 4 checkboxes; BaseballCheck, BasketballCheck, FootballCheck and HockeyCheck.
I'll assume you have a table called MyTable, with a field called Sport.
What you can do is add a button to your form. Call it btnSubmit. Add this VBA to your button:
Dim db as Database
Dim rec as Recordset
Dim MySQL as String
Set db = CurrentDB
MySQL = "SELECT * FROM MyTable WHERE 1 = 1"
If BaseballCheck = True then
MySQL = MySQL & " AND Sport = 'Baseball'"
EndIf
If HockeyCheck = True then
MySQL = MySQL & " AND Sport = 'Hockey'"
EndIf
If BasketballCheck = True then
MySQL = MySQL & " AND Sport = 'Basketball'"
EndIf
Etc...
Set rec = db.OpenRecordset(MySQL)
Instead of that last statement, you can use CreateQuerydef to create a permanent query that you can then use as the basis for a report. However, you would have to add some code at the beginning to delete that querydef if it exists, otherwise it will throw an error.
If you want something a little more elegant (and one that will allow for easier scalability) you could always loop through all the checkboxes on your form and dump the sports into an array, and then use that array as the subject of a "WHERE Sport IN (...)" statement.
As no reference information is provided, i use the following for this example;
Formname = Form1
Tablename = test
Checkfieldname = BaseballCheck
In the form property sheet, add the following vba for the BaseBallCheck, this will requery the form after the check has been enabled/disabled.
Private Sub BaseballCheck_AfterUpdate()
Me.Requery
End Sub
Then in the form Recordsource add the following
SELECT test.Baseball
FROM test
WHERE (((test.Baseball)=[forms]![Form1]![BaseballCheck]));
Now when the form refreshes only the values are shown where Baseball = checked or unchecked.

VBA collection with 2 or more fields

I'm using a Collection to store data from a recordset in VBA. The recordset has two fields.
I'm using a collection because I want to utilise its ability to prevent duplicates by using the key parameter. I'm running an SQL query to generate the recordset many times and a lot of the results will be identical to the previous, but some will be different. I want to capture a collection of the unique results from each recordset.
I can do this currently using the following:
rs.Open sql_vehicles, cn
If rs.RecordCount > 0 Then
Do While Not rs.EOF
On Error Resume Next
value = rs.Fields("EVN").value
catalogue_Tags.Add Item:=value, Key:=value
rs.MoveNext
On Error GoTo 0
Loop
End If
which all resides in a for loop generating a new recordset each time which may or may not be different.
This will give me a collection with unique values from the "EVN" field in the recordset, but I need to be able to store the second field in the recordset as well, but I want to still avoid duplicates of the EVN field!
Any ideas on how to do this?
Seems to me you can just use 2 collections to get 2 unique lists...
value = rs.Fields("EVN").value
catalogue_Tags_EVN.Add Item:=value, Key:=value
value = rs.Fields("ABC").value
catalogue_Tags_ABC.Add Item:=value, Key:=value
I just notice your requirement is slightly different then I read the first time...
Add "Microsoft Scripting Runtime" reference to your project and use a dictionary of dictionaries.
Dim evnValues as new Scripting.Dictionary ' this will actually be a dictionary of dictionaries.
inside the loop do this...
ABCvalue = rs.Fields("ABC").value
if not evnValues.Exists(value) then
' sub dictionary does not exist yet. initialize the list for this evn value
evnValues(value)=New Scripting.Dictionary
end if
evnValues(value).item(ABCValue)=ABCValue ' accumulate a list of the ABCValues relative to the unique evnValue.
At the end you will have a dictionary with the Names of the top level being your unique EVN values and the sub value will be a collection of 1 or more ABC values.