combobox.column property returns invalid use of null in vba - sql

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!

Related

MS Access VBA: Fetch data from a query which corresponds to an ID field from a selected row in a subform table

I'm completely new to VBA and MS Access!
I have a Subform within a form which contains data about items which all have an "Equipment ID" field.
Using data from a different table, I have a query to count the number of "faults" associated with each item. This Query also has the "Equipment ID" field.
I have a second form which contains text boxes, and can be accessed by a button. On the button click, the form opens up and data from the selected current row in the subform are passed into the text boxes. I have assigned the original data table to the form control source.
What I want to do:
I'm having trouble with the query. I have been trying to link the subform and the query, so that when the row on the sub form is selected, the "Equipment ID" is grabbed from that, and the "number of faults" in the Query can be found from its corresponding "Equipment ID".
Here is the code so far (and what I want to happen in comments):
Private Sub Button_Click()
Dim db As Database
Dim rs As DAO.Recordset
Dim EqIDfrm As String 'Equipment ID from the subform
'Open up the Faults Query
Set db = CurrentDb
Set rs = db.OpenRecordset("qryFaultTotal")
'open up the second form
DoCmd.OpenForm "SecondForm"
'Grab the "Year" from the selected row in the sub form and assign it to SelectYear. The text
'box value in the second form then becomes the SelectYear value.
SelectYear = [Forms]![Form1]![tblAsset Subform].[Form]![Year]
[Forms]![Form2]![txtYear] = SelectYear
' etc. for other fields
'grab the equipment ID from the subform and from the Query
EqIDfrm = [Forms]![Form1]![tblAsset Subform].[Form]![Equipment_ID]
EqIDqry = rs![Equipment_ID]
'<--- this seems to be part of the problem
'Lookup the Total number of faults from the FaultTotal Query, where the Equipment ID in the Query is
the same as the equipment ID on the subform from the selected row.
Fault = DLookup("[TotalFault]", "[FaultTotal]", "[EqIDqry] = " & [EqIDfrm] & "")
End Sub
When I use lookup I keep getting an error of some sort (type mismatch, run-time error), and I just can't figure it out. It doesn't seem to like the EqIDqry but I don't know why despite Googling. I feel like it should be very simple, but I understand I may have to do something totally different! Any advice would be appreciated :)

MS Access 2019: How do I check for duplicate records before update, then run a specific procedure if duplicates are found?

I am very new to both StackOverflow and to doing any sort of advanced programming in MS Access. I created a database to catalog my trading card collection (Excel just wasn't cutting it since we're talking about over 2000 unique cards). At first it was just a simple table of records, but now it's turned into a full-fledged database that I have search forms for and queries and everything.
What I'm trying to do right now is streamline my process a bit, and there is something very specific that I want to make Access do. I'm almost certain that whatever I want to do will have to be done in VBA, and I'm just not familiar enough with it to do what I want.
What I want it to do is this: Any time a new record is entered, I want it to check the record before it saves the record into the DB (I'm fairly confident that I need to use the "Before Update" event for this) and make sure that the "Sort ID" field (an auto-calculated field I've created) contains no duplicates (I know I'll most likely have to use queries for this since auto-calculated fields can't be indexed). If the program detects a duplicate, I want it to produce a message box saying that I'm trying to enter a duplicate record and ask me if I want to update the "number owned" field of the existing record instead of creating a new one, and then take me to the record in question on an affirmative response.
What I currently have is a validation rule that uses an index (comprised of the fields that generate the Sort ID), which generates a custom error message by using the following VBA code in the "On Error" event:
Private Sub Form_Error(DataErr As Integer, Response As Integer)
Const conErrRequiredData = 3022
If DataErr = conErrRequiredData Then
MsgBox ("Duplicate Sort ID. Please update the 'number owned' field on the existing record instead.")
Response = acDataErrContinue
Else
Response = acDataErrDisplay
End If
End Sub
This code works exactly as it should, but I want more than a pop-up error that I can't do anything with. I have a query entitled "CheckDuplicateSortID" that I created using the Query Wizard, and it checks the "Sort ID" field for duplicates, but that's as far as I've managed to get. The example on This site is about the closest I've managed to find to what I'm looking for, but the code sample given is very difficult for me to understand because there's very little explanation with it; I'm not familiar enough with Access VBA to know which parts are important code and which parts are his specific field names and other variables; I haven't gotten any error messages because I'm stumped on even trying to figure out what needs to be changed from that sample code and what it needs to be changed to.
Edit: Just for the sake of clarification, the solution doesn't have to involve the Sort ID field. I created that so I'd have one field I can point the program to. But if it would be simpler to just use the index that I use for my current validation rules (with the error message generated by the above code), I'm open to that too.
After some considerable finagling, I actually managed to find a solution to this on my own, though it is probably needlessly complicated (I'm definitely open to simpler solutions, if anyone has any).
Rather than using the actual SortID field, I modified the code in the OP to this:
Private Sub Form_Error(DataErr As Integer, Response As Integer)
Dim strMsg As String
Dim iResponse As Integer
'The text to be displayed in the message prompt.
strMsg = "Unable to save record. The values you have entered would generate a duplicate." & Chr(10)
strMsg = strMsg & "Would you like to clear this form and edit the existing record instead?"
'Calls for the yes/no message prompt specifically when the no-duplicate
'validation rule is violated (error 3022).
Const conErrRequiredData = 3022
If DataErr = conErrRequiredData Then
iResponse = MsgBox(strMsg, vbQuestion + vbYesNo, "Invalid Sort ID")
Response = iResponse
If iResponse = vbYes Then
'Calls a custom function that opens the record in question for editing.
UpdateOnError
Else
'Cancels the operation on a negative response and does not clear the form.
Cancel = True
End If
Else
Response = acDataErrDisplay
End If
End Sub
As you can see from the above code, the event calls a custom function, which is coded as follows:
Function UpdateOnError()
On Error GoTo UpdateOnError_Err
Dim UpdateGoToID As Variant
'Selects the Sort ID in question for the purpose of opening the existing record.
UpdateGoToID = Forms![Card List Entry Form]!txtSortID
'Clears the invalid form.
DoCmd.RunCommand acCmdUndo
'Opens the existing record the user attempted to duplicate.
DoCmd.OpenForm "Card List Entry Form", acNormal, "", "[Sort ID]=" & "'" & UpdateGoToID & "'", , acNormal
UpdateOnError_Exit:
Exit Function
UpdateOnError_Err:
MsgBox Error$
Resume UpdateOnError_Exit
End Function
Like I said, this is probably a lot more steps than actually needed, but it does work as I want it to: when the user attempts to enter a duplicate record, an error message pops up asking if they would like to update the existing record. If yes, it takes them to the existing record. If no, it closes the error message without clearing the form or saving the record.

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.

Access Calculate Next Value (lookup value}?

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?

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.