change a field's value with vba - ms-access

I want to change a date in a specific table to today's date by clicking a button in a related form. So all the button does is changing the date in a certain field in my DB. Is there a simple way to do this with VBA?
*Update
Well I wrote this in my VBA code:
CurrentDb.Execute "UPDATE Machines SET LastMaintenance = Date() WHERE MachineID = MachineID.Value"
With "Machines" being my table, "LastMaintenance" the column containing the date that has to be changed into today's date, "MachineID" the name of the record and "MachineID.Value" the name of the textbox bound to that same record.
When I click the button I get this error:
"Not enough parameters. 1 expected."

When performing an update query, you'll want to be cognizant of the datatype for each field, as you will have to present it differently in your code. Also, you will need to break up your string text when inserting a variable. In your current state, it's looking for a MachineID field with 'MachineID.value' as its contents. Try this:
CurrentDb.Execute "UPDATE Machines SET LastMaintenance = Date() WHERE MachineID = " & MachineID.Value

The most straightforward way is to run a UPDATE query.
CurrentDB.Execute "UPDATE someTable SET someDate = Date() WHERE stuff = 47"

If
a button in a related form
means a form bound to that table displaying the record you wish to update, use the OnClick event of the button:
Private Sub NameOfYourButton_Click()
Me![NameOfYourDateField].Value = Date
' Optionally, save the record at once:
Me.Dirty = False
End Sub

An UPDATE command is dangerous because you are making a change to the database assuming sane inputs. I would recommend using parameterized VBA code to avoid both SQL injection and throw an error in VBA for malformed inputs.
This example uses a static string to load your recordset, then it clearly states that the unverified input is only used in a Find command. Then it only acts if a matching record is found. This is a safer operation, albeit more verbose. It's also debuggable in VBA where the SQL UPDATE command is a kind of black box.
With CurrentDb.OpenRecordset("Machines", dbOpenDynaset)
.FindFirst "[MachineID]=" & CLng(MachineID.Value)
If .NoMatch Then
Debug.Print "ID not found: " & MachineID.Value
Else
.Edit
.Fields.Item("LastMaintenance").Value = Date()
.Update
End If
.Close
End With

Related

Object variable error

I've got a subform (RegistrationFsub) based on table Registration. It's purpose is to create a one-to-many relationship between a person and the year(s) they have enrolled in the group.
When a mom enrolls in a new year, I have a command button that is supposed to add a new line to the table Registration with MomID (from the parent form: MomsFsub) and the start date of the current enrollment year (YearStart, from table Year). Since the current enrollment period is represented by the latest date, I want to use the Max() command to retrieve it from YearT. I tried the following code:
Dim db As DAO.Database
Dim sqlSTR As String
Dim IDvar As String
'new code added since question posted
Set db = CurrentDb
Call MsgBox (Max(YearT!YearStart), vbOKonly)
'MsgBox checks value returned for Max(YearStart)
'end new code
IDvar = CStr(MomID)
sqlSTR = "INSERT INTO Registration(YearStart, MomID) SELECT Max(YearStart), "_
& IDvar & " AS expr1 FROM YearT;"
'new: debug statement
Debug.Print sqlSTR
db.Execute sqlSTR
And I got an "Object variable or With block variable not set" error. What am I doing wrong?
Edit: Setting the db to Currentdb fixes the Object variable error, but now returns a "Too few parameters" error. The original table name "Year" has been changed to "YearT," since I only reference it in this one bit of code anyway.
Update
Now that I've fixed RegistrationFsub, it seems that the button also inserts data currently displayed in other controls on the form. So if the 2012 entry has RID = 1 and Leader = True, the above code creates an entry in Registration that also has RID = 1 and Leader = True. How can I keep those other fields blank?
The object variable error is because you didn't Set db to anything before you attempted db.Execute. Do this first ...
Set db = CurrentDb
If you later get an error with Execute, it may be because Year is a reserved word. Enclose that table name in square brackets to avoid confusing the db engine.
sqlSTR = "INSERT INTO Registration(YearStart, MomID) SELECT Max(YearStart), "_
& IDvar & " AS expr1 FROM [Year];"
If you are adding a new record based on the Mom's current new entry, you need to take the current time: Now() and parse the year off of it..
Year(Now())
Looking for Max(YearStart) could be looking for a record that happened 5 years ago..
sqlSTR = "INSERT INTO Registration(YearStart, MomID) SELECT Max(YearStart), "_
& IDvar & " AS expr1 FROM Year;"
I think you need to update the code to two different operations:
sqlSTR = "INSERT INTO Registration(Year(Now()), MomID)"
run your code..
Then do a..
sqlSTR= "SELECT Year(Now()), " & IDvar & " AS expr1 FROM [Year];"
The most relevant answer was deleted before it could be selected, so I shall paste the content here:
The object variable error is because you didn't Set db to anything before you attempted db.Execute. Do this first ...
Set db = CurrentDb
If you later get an error with Execute, it may be because Year is a reserved word. Enclose that table name in square brackets to avoid confusing the db engine.
sqlSTR = "INSERT INTO Registration(YearStart, MomID) SELECT Max(YearStart), "_
& IDvar & " AS expr1 FROM [Year];"
For "too few parameters", add Debug.Print sqlSTR after the sqlSTR = ... line.
But before the Execute command
Run the code and go to the Immediate window (Ctrl+g). Copy the SQL text, create a new query in the query designer, switch to SQL View, and paste in the SQL text. When you run that query, Access will pop up an input box asking you to supply a value for the parameter. That box also include the name of whatever Access thinks is the parameter.
The trouble here is that YearStart had a different field name in table Year.
Many thanks for the clear and helpful answer.

MS Access 2007 - Changing a checkbox to be unchecked

I have an unbound text box that I want to enter a number in and then it would go in a form. When I do this, I want to change the status of checkbox in another form as well. So it is like inventory. When I add this item to this box, I need the checkbox value to change because it's no longer in inventory. So the form I have is 'Info' and the checkbox is named 'ChkboxAvailableUse'. I have the checkbox correlated to a kit number and location and stuff too. So when I enter the number in an unbound text box called 'AssignKit', I want that number to look for the same kit number the 'Info' form and the 'InvKitNumber' text field, and then change that records checkbox (ChkboxAvailableUse) to change to false. I hope this makes sense. I have the line of code I thought would work below. Any help would be fantastic. Thank you
CurrentDb.Execute " UPDATE Info SET ChkboxAvailableUse = FALSE WHERE InvKitNumber = " & Me.AssignKit & ""
If you just want that form to uncheck or check in the table to match your form or subfrom then you could use a recordset.
Dim myR as Recordset
Dim strSQL as String
'This SELECT string will pull from the assignkit field in the subform
'and will be used find the matching record in the table
strSQL = "SELECT * FROM info WHERE InvKitNumber = '" & Me!subformnamehere.Form.AssignKit & "'"
'This will make your recordeset variable the one record you want to modify
Set myR = db.OpendRecordset(strSQL, dbOpenDynaset)
'Now that the recordset is pointing to that row, you can change the checkbox
'with something like this, and even use an IF statement
myR.Edit
myR![ChkboxAvailable] = True
myR.Update
'Then close the recordeset when done
Set myR = Nothing
I hope this helps, let me know if you need me to tweek it.
The sql UPDATE statement updates fields in a table. Tables don't have checkboxes, forms do, and I assume that the field (in the table) is not called ChkboxAvailableUse ?
If the field is named AvailableUse then you would update this field with:
CurrentDb.Execute "UPDATE Info SET AvailableUse = FALSE WHERE InvKitNumber = " & Me.AssignKit
Then you could ReQuery the (other) form (or a control on the form) so that it reflects these changes.

Check if Combobox RowSource is Valid

This is somewhat related to this question, but I was hoping there may be a more elegant / simple solution than defining a User-Defined Function.
Background
In essence, this is a common question: I need to dynamically modify the RowSource query of a combobox control on an Access form. The twist is that there is a possibility the resulting query may throw an exception when executed. That is because the source table of the query exists in a different database file which is defined dynamically and may not exist, or even if the file does exist, the desired table or column may not.
Ideally, I would like to be able to catch this problem when the assignment is made, so that the combobox will be disabled and the user cannot invoke the invalid query allowing the end-user to know there is no data available for the field.
For example I would like something like this:
Private Sub UpdateComboRows(src as String)
On Error Goto InvalidQueryError
cmbBox.RowSource = "SELECT [colName] FROM [dBase III;DATABASE=K:\" & src & "].[tblName];"
' Something here to invoke RowSource query and throw error
cmbBox.Enabled = True
Exit Sub
InvalidQueryError:
cmbBox.RowSource = ""
cmbBox.Enabled = False
End Sub
Or something using if-then statements.
Question
Are there any 'sleek' approaches to this, or am I stuck with trying to populate a dummy DAO recordset? Is there some way of invoking the Combobox RowSource query besides the Dropdown event?
Why not take a step back and check first that the database exists with Dir, then check that the column exists in a function. Very roughly.
Function IsDBOk() As Boolean
On Error GoTo Err_Trap
''The default for boolean is false, so
''IsDBOK=False at this point
sFile=Dir("K:\" & src)
If sFile<>"" Then
Dim rs As DAO.Recordset
Set rs = CurrentDB.OpenRecordset("SELECT [colName] " _
& "FROM [dBase III;DATABASE=K:\" _
& src & "].[tblName];")
If Not rs.Eof() Then
''The selection is only okay if the recordset
''contains records, however, you could return
''a different error for each problem
''file missing, column missing, empty recordset
IsDBOk = True
End If
End If
Exit Function
Err_Trap:
''A missing column will give error 3061
''IsDBOk is already set to false
End Function

How to directly update a record in a database from a form number (Access 2007)

I have a job-tracking system, and there is a query that returns results of all jobs that are overdue.
I have a form that displays each of these jobs one-by-one, and has two buttons (Job has been completed, and Job not completed). Not completed simply shows the next record.
I cannot find a way to get access to the current record to update it's contents if the "Has been Completed" button is pressed, the closest I can get is the long number which represents the records position in the form.
The VBA to get the index of the record in the form is as follows.
Sub Jobcompleted(frm As Form)
Dim curr_rec_num As Long
curr_rec_num = frm.CurrentRecord
End Sub
This is my first shot at VBA, and after an hour of searching I cannot find anything to solve my problem.
Am I going about this the entirely wrong way? Working in Microsoft Access 2007
Further Info All tables are normalized
Vehicle Table: Contains vehicle_id(pk), as well as rego and model etc
Job Table: Contains job_id(pk), vehicle_id(fk) and other info about what needs to happen, as well as the next occurance date, days between each occurance of the job (all jobs repeat) and other info
Job History Table: Contains job_history_id(pk), job_id(fk), date completed and comments
When the job completed button is pressed, it should create a new entry in the job history table with the current date, any comments and the job id
This is the script I am trying to get working
Private Sub Command29_Click()
Dim strSQL1 As String
Dim strSQL2 As String
Set Rs = CurrentRs
Set db = CurrentDb
strSQL1 = "INSERT INTO completed_jobs(JOB_ID, DATE_COMPLETED, COMMENTS) VALUES " & Rs!job.ID & ", " & Date
db.Execute strSQL1, dbFailOnError
strSQL2 = "UPDATE job SET JOB_NEXT_OCCURANCE = JOB_NEXT_OCCURANCE+JOB_RECURRANCE_RATE WHERE job.ID = Rs!job.ID"
db.Execute strSQL2, dbFailOnError
End Sub
Note: Line Set Rs = CurrentRs is completely incorrect, I believe this is what I need to figure out? This is called on button-press
I am posting an image which shows the form (non-continuous).
#HansUp, I get what you are saying, but I dont quite think it's applicable (I did not provide enough information first time around for you to understand I think)
#sarh I believe this Recordset that you are talking about is what I need, however I cannot figure out how to use it, any hints?
#Matt I am 90% sure I am using a bound form (Like I said, new to Access, been looking at everything people have suggested and learning as I go). There is of course an ID for the job (Just not shown, no need to be visible), but how would I access this to perform an operation on it? SQL I can do, integrating with Access/VBA I am new at
As I understand your situation, your form is data-bound bound (you can get record index), so - your form already located on this record. If you need to update some field of underlying dataset, you can write something like
Me!SomeField = ...
DoCmd.RunCommand acCmdSaveRecord
If your form has control bound to "SomeField", then the form will be updated automatically.
If this will not help, you can look to a couple of another directions:
1) Update records using SQL code. For example, you have ID of record that should be updated in the form data set, so you can write something like:
Call CurrentDB.Execute( _
"UPDATE SomeTable SET SomeField = SomeValue WHERE SomeTableID = " & Me!SomeTableID, dbSeeChanges)
2) You can look at the Bookmark property - both Recordset and Form has this property, it describes the record position. So you can write something like this (not the best example, but can help you to get an idea):
Dim Rs as Recordset
Set Rs = Me.RecordsetClone 'make a reference copy of the form recordset
Rs.Bookmark = Me.Bookmark 'locate this recordset to the form current record
Consider a simpler approach. I doubt you need to be concerned with the form's CurrentRecord property. And I don't see why you should need a command button for "Has been Completed" and another for "Has not been Completed".
Add a "Yes/No" data type field to the table which is used by your form's record source. Set it's default value property to 0, which represents False or No. Call it "completion_status". Create a new form using that record source. Then your form can have a check box control for completion_status.
Newly added records will have False/No as completion_status --- the check box will appear unchecked. The completion_status for other records in the forms can be toggled between Yes (checked) and No (unchecked) using the check box control.

MS Access search for record by textbox instead of dropdown

I'm pretty new to MS Access. I'm trying to create a simple form that will basically search for a particular record using a textbox, rather than a drop down box. Essentially a user would be able to enter an ID number and retrieve some other related Info. However, I do not want the user to be able to add any new records to the database. I've been able to get the forms to look the way I want them, but I'm not sure where to place the code (do I create a macro, insert the code into the properties of the button?) Any help is greatly appreciated!
I assume that you have bound your form to a table or a query and that you want to be able to enter the ID manually in a textbox, then press ENTER and load that record's data or display an error message if there is no such record.
As dsteele said, make sure that the form's Data property Allow Addtions is set to No to disallow users from adding records.
Then, from the AfterUpdate event of the textbox, add the following code (assuming that your textbox is named txtGoTo):
Private Sub txtGoTo_AfterUpdate()
If (txtGoTo & vbNullString) = vbNullString Then Exit Sub
Dim rs As DAO.RecordSet
Set rs = Me.RecordsetClone
rs.FindFirst "[ID]=" & txtGoTo
If rs.NoMatch Then
MsgBox "Sorry, no such record '" & txtGoTo & "' was found.", _
vbOKOnly + vbInformation
Else
Me.RecordSet.Bookmark = rs.Bookmark
End If
rs.Close
txtGoTo = Null
End Sub
Note that you will have to change the line rs.FindFirst "[ID]=" & txtGoTo to something that is adequate for your data:
"[ID]=" should be replaced by the field you want to search (it could be "[POReference]=" or something else.
if you are searching by a numeric ID, for instance because the field is an autonumber column, then the code is fine.
Otherwise, if the field you are searching on is a string (say PN12-G) then you have to change the code to:
rs.FindFirst "[ID]=""" & txtGoTo & """"
Failing to use the proper quoting (or quoting where not necessary) will result in errors of the kind Data type mismatch....
As a new user, I would recommend that you have a look at the sample NorthWind project database that is either shiped with older versions of Access or available as a template for download from Access 2007.
There a lots of techniques to learn from as a new Access developer, including other ways to implement record navigation.
Set the form property Data/'Allow Additions' to No.
Either in the AfterUpdate event of the textbox, or in the Click event of a button, you can write code or assign a macro to look up and display the record you want.