How to timestamp Each Field Updated in another assigned Field Ms Access - vba

I'm setting up a database to monitor/timestamp the time of edit for each field (not just the form). so entered the following code in the "after update" event of the property:
Private Sub DReceived_AfterUpdate()
Me![CLASS] = Now()
End Sub
I had hoped that the edit of the field labeled "CLASS" would timestamp in the field "DReceived" but that is not happening.
I have tried "now()" function in the property of the table field but it keeps fixing the current time and date even without anything update. (I ONLY WANT A TIMESTAMP WHEN DATE In Any Field is updated
Private Sub DReceived_AfterUpdate()
Me![CLASS] = Now()
End Sub
If I have fields A to F in a table, if I edit A, B should Timestamp, C; D should TimeStamp, etc.

Use a Before Change Data Macro, not a VBA sub on a form. For one, subs won't trigger if one directly edits the table, and data macros are intended primarily to do this.
The macro would incorporate logic like:
If Updated("CLASS") Then
SetField
DReceived
=Now()

Related

Split contents of an Access field into separate variables in VBA

I have an Access table containing a field with multiple dates (ex: 11/22/2022, 11/23/2022, 11/24/2022) that needs to be split into usable variables. The field could contain 1 to 40 dates, it's unknown at any given time.
I have been unable to find any examples of this being done, any links or ideas anyone might know of?
On your form, create a combo- or listbox. Name it, say, EventDate.
Set its RowSourceType property to ValueList.
Insert code like this in the OnCurrent event of the form:
Private Sub Form_Current()
Me!EventDate.RowSource = Nz(Me!YourMultiDateField.Value)
End Sub
This will list the dates with the option to select one.

VBA/Access: Track the last date a macro was run via a command button

I'm using command buttons to import excel files into various tables, and I want to track the last time each table was updated (i.e. the last time the command button was clicked and ran successfully).
I've tried doing this by adding a text field next to each command button, and then adding Me.TextField1.Value = Date to the _Click subroutine for each button. This fills in the date correctly, but it doesn't save the value when I close the data base.
How do I keep the date value from resetting every time I reopen the database?
The way I would probably approach this is to add a table to your database that contains a list of all the Excel files you import on a routine basis. You would store the filename of the Excel file in one column, and the updated date in another column.
Then you can use the DLookup() function to pull the updated date into your text box by your command button.
Of course there are many approaches you could take here, but which one is best depends on your specific needs. If it is just you running this application on a single computer, you might find it easier to use the SaveSetting/GetSetting functions to save simple values to the registry.
SaveSetting "ExcelImporter", "sheet2.xlsx", "Updated", Now()
TextField1 = GetSetting("ExcelImporter", "sheet2.xlsx", "Updated")
If you have a lot of spreadsheets, you might consider a list box with two columns, one with the name of the file, and the other with the date it was last updated. Then you could use a single button to run the update, based on the selected file. Lots of options... :-)
Add a Date/Time field to the table you are updating and set the Default Value property of the field to Now(). When new records are inserted, they will automatically have their insert date and time set.
If you are updating existing records, then update this field to Now explicitly.
You can query this date with
Dim lastUpdate As Variant
lastUpdate = DMax("DateFieldName", "TableName")
In addition, you see when each record has been inserted or updated.
TextBox values are not saved permanently, unless the RecordSource of the form has been set to a table or query and ControlSource of the TextBox has been set to a column of the table or query.
You could create a Custom Database Property to hold the last time the button was clicked.
Function getLastTimeClick() As Date
Const PropertyName As String = "LastTimeClicked"
On Error Resume Next
getLastTimeClick = CurrentDb.Properties(PropertyName).Value
If Err.Number = 3270 Then
CurrentDb.Properties.Append CurrentDb.CreateProperty(PropertyName, dbDate, Now)
End If
CurrentDb.Properties(PropertyName).Value = Now
On Error GoTo 0
End Function

MS Access - Disable Update on a Certain Field or Column

How do we disable update or edit on a certain column for a record. For example I have Product table with fields of ID, Description, Count. I want to disable the changes on Description only. I know how to do this in sql, but how about in a program for Access or VBA code?
If you're using a form to present the data using a text box control bound to the field, you can lock the field for edits in the field properties. The property is called "locked".
You can also use vba code to lock and unlock the field under certain conditions.
Sub form_current ()
If x = "superuser" then
Me!SalaryField.enabled=true
Me!SalaryField.locked=false
Else
Me!Salaryfield.enabled=false
Me!Salaryfield.locked=true
End if
End Sub

MS Access Can't go to specified record because of another control's VB where clause

I have a lookup listbox which is programmed to allow the user to find a specific record/help topic from the list and view it. Now when the list box is used the where clause locks in the record and the first, previous, next, last buttons freeze up and you cannot use them to go to a record. Is there a way to free up the functionality of the buttons to navigate through the records along with the where clause to select.
Here is the code that operates the listbox selections:
Private Sub List35_AfterUpdate()
Dim myTopic As String
myTopic = "Select * from FormsHelpTable where ([ID] = " & Me.List35 & ")"
Me.Form.RecordSource = myTopic
Me.Comment.Requery
End Sub
I believe since the where clause locks in the selection in the box it does not allow navigation from other controls to interfere. What might be a way around this?
You get the runtime error:
You can't go to specified record.
It appears not to be reading the other record in the source table named Help once it updates using the listbox.
Instead of changing the recordset (this is the 'pool' of records which the form could display), you just need to go to the record the user selects from the listbox.
Method 1 (probably the easiest way if your listbox is in the same order as the records of your form)
Use this code:
Private Sub lstSelect_AfterUpdate()
DoCmd.GoToRecord acDataForm, "HelpForm", acGoTo, Me.lstSelect.ListIndex + 1
End Sub
You need to ensure that:
The recordset of the form is ordered the same as the listbox. So, for example, you could order both by ID, or by Title.
Note that the +1 comes from the fact that the ListIndex starts at 0, whereas the record indexes start at 1.
Method 2
Ensure each record's Title is unique (set No Duplicates on this field).
Change your listbox to return the Title of the record, rather than it's ID.
Then use this:
Private Sub lstSelect_AfterUpdate()
Me.Title.SetFocus
DoCmd.FindRecord Me.lstSelect
Me.lstSelect.SetFocus
End Sub
Things to note:
It works by searching the field with focus for the string specified. That's why we have to SetFocus on the Title textbox on our form.
We could use ID instead, (which would mean we could have duplicate titles if we wanted), but then we would have to have an ID control on the form to SetFocus to. You can't hide this control either, because it needs to have focus whilst using FindRecord.
Update: Method 1 with reverse-selection
Add an Event Procedure in the Form_Current event, with this code. Then update the code in the lstSelect_AfterUpdate procedure as shown after.
Private Sub Form_Current()
Me.lstSelect = Me.lstSelect.Column(0, Form.CurrentRecord - 1)
End Sub
Note that, depending on how your lstSelect is set up, it may be Column(1, Form.CurrentRecord - 1) instead. Read on for details!
Private Sub lstSelect_AfterUpdate()
DoCmd.GoToRecord acDataForm, "HelpForm", acGoTo, Me.lstSelect.ListIndex + 1
Me.lstSelect = Me.lstSelect.Column(0, Form.CurrentRecord - 1)
End Sub
Explanation of new lines:
The Form_Current event fires every time we go to a new record. We need to look at the index of the record (ie. the position of it in the recordset), which we get by using Form.CurrentRecord. We then want to make the listbox select that record. However, we can't use me.lstSelect.ListIndex as before, because that is a read-only property (we can access it to read it, but we can't set it).
Therefore, we use me.lstSelect.Column(colNum,rowNum) instead, where we specify a column number and a row number. If your listbox has two columns (eg. ID and Title), we want to choose the second column. The index starts at 0, so we would use a value of 1. If, like my lstSelect, you only have one column (Title) then we use 0. Note: it doesn't matter if a column is hidden (ie. has width 0). It still 'counts'.
The row number is Form.CurrentRecord - 1. Remember that the forms recordset index starts at 1, but the index of our listbox starts at 0; hence the - 1.
So why do we need a duplicate of this new row in the AfterUpdate event? Try and comment it out to see what happens if we don't put it in. It's has to do with the Form_Current event firing after we use the listbox.
I fixed this issue with a union clause in the SQL lookup code. The UNION ALL clause and the following union on the table used in the other part had allowed all the records to be used.

Display SQL time field on Access form as Access medium time hh:mm am/pm

I am using Access 2010 linked to SQL Server 2008 R2. My problem - how do I display time on an Access form as hh:mm am/pm instead of SQL Server's time(7) format of hh:mm:ss.nnnnnnn?
To complicate things, I do have a look-up table with all the times in half hour time frames? Ex. in SQL, the lookup field says 07:30:00.0000000 - I want to choose a time from the dropdown in my Access form that says 7:30 am and then display it on the Access form as 7:30 am. If I choose it, I want it to store in SQL Server as 07:30:00:0000000 (because I have no other choice).
I can't find anything on this.
Access doesn't have a Time data type, so when it links to a SQL Server time column it maps that column as Text. That's why any Date/Time Format specifier you try to apply to the linked table value has no effect: as far as Access is concerned it's a string.
So if we have a SQL Server table [Appointments]:
and we create a Linked Table in Access we get
If we create an Access form for that linked table and use plain old bound controls we get this
The text box for [apptStart] does work, but it doesn't look so great. The workaround is to leave that text box on the form, but hide it (set its .Visible property to No) and then add another unbound text box to the form. (In this case I called it [txtStartTime].) Set the .Format of the new text box to Medium Time and adjust any other formatting as required (e.g., I set Text Align to Left).
In the On Current form event, calculate the Access Date/time value corresponding to the start time in SQL Server table and stuff that value into the [txtStartTime] text box. Now we get something that looks a little better:
Now what if the user wants to edit that value? In the After Update event for the [txtStartTime] text box we create the corresponding SQL Server time string and stuff that value into the (invisible, bound) [apptStart] text box. When the record is saved the new time value is updated in the SQL Server table.
The code behind the form is as follows:
Option Compare Database
Option Explicit
Const accessDate0 = "1899-12-30 " ' <- note trailing space
Dim startTimeAsDateTime As Date
Private Sub Form_AfterUpdate()
Me.Requery
End Sub
Private Sub Form_Current()
Me.txtStartTime.Value = CDate(accessDate0 & Left(Me.apptStart, 8))
End Sub
Private Sub txtStartTime_AfterUpdate()
Me.apptStart.Value = Format(startTimeAsDateTime, "hh:nn:ss")
End Sub
Private Sub txtStartTime_BeforeUpdate(Cancel As Integer)
On Error GoTo txtStartTime_BeforeUpdate_Error
startTimeAsDateTime = CDate(accessDate0 & Me.txtStartTime.Value)
Exit Sub
txtStartTime_BeforeUpdate_Error:
MsgBox "Start Time appears to be invalid."
Cancel = True
End Sub
Sorry, I don't have a dev environment setup, but can you change your SQL query to:
SELECT Convert(varchar(5), getdate(), 108)
to give HH:MM and truncate the rest so it displays correctly.
Then, you can cast as date on the way back.