Access: display warning if room has no check-out date - ms-access

We have an Access-db which lists the residents of a carehome. When a resident moves out of the room, there's a field to enter the date of exiting. Sometimes (a lot actually) the user forgets to enter this date.
When registering a new resident to room 1, I'd like to show a warning if the exit date of the former resident is still blank or if the starting date of the new resident overlaps with the one from the previous resident.
Prevention of input optional. Any suggestions?
Tnx!

Well, I suppose as noted, the point to fix this would the the form/time/place when the date of exit is not filled out. So, you could in that form simple use the before update event. Check if the exit date is not entered, and thus pop up a message and set cancel = true in the before update event. The user will not be able to exit or save that data until such time they enter that exit date.
Now I suppose in your new booking form, you can simply query/check the database for records that don't have that exit date, and pop up a warning .
dim strWhere as string
strWhere = "(RoomNumber = " & me!RoomNumber & ") AND (EixtDate is null)"
if dcount("*","tblBookings",strWhere) > 0 then
msgbox "warning - this room has previous bookings without Exit date"
do whatever you want here!
End if

Related

MS Access Textbox.OldValue equivalent for DateTime Format

When we update a bound textbox on a form, we can use the _BeforeUpdate event to perform logical checks and controls before the update, and reset the textbox to it's previous value using the txtboxfield.OldValue property if so desired.
This does not work if the underlying bound is a DateTime field.
Is there an equivalent for the DateTime field? If not, is there a workaround that I could use in the following piece of code?
Private Sub txtDueDate1_BeforeUpdate(Cancel As Integer)
'Alert if inital due date is modfied
If Not (Me.txtDueDate1 = vbNullString) Then
Select Case MsgBox("Are you sure you wish to modify the original due date?", _
vbOKCancel Or vbInformation, "Original Due Date")
Case vbOK
Exit Sub
Case vbCancel 'reset the previous value
Me.txtDueDate2.SetFocus
Cancel = True
Me.txtDueDate1.OldValue
'Me!txtDueDate1.Undo
End Select
End If
End Sub
Using the .Undo option doesn't work for me, as I with to use .SetFocus which gets blocked by...
run time error 2108: You must save the field before you can execute...
I have experimented with moving the .SetFocus command arround, but it does not matter where it is placed.
The _BeforeUpdate will not allow you to perform another save while current BeforeUpdate is being executed. It's like the transaction is locked until this event is completed.
You can undo the current field and cancel the event by:
Me!txtDueDate1.Undo
Cancel = True
If you require editing/modifying other fields, you can either move this code to OnAfterUpdate or move all validations to your Form'sOnBeforeUpdate on which you can then halt the entire update process

Unique Membership Number in Access Database

I have a Database in Access 2010 where the 1st field is a unique membership number. The field is set Indexed, no duplicates. If a duplicate is entered on the input form no error message is displayed and nothing else works until a unique number is entered. I need the code that would trap the error on the number field losing focus so that a message box would tell the user the problem and then set focus back to the number field or let the user cancel all input.
This is what I have and it causes Datatype errors
Private Sub Grumpy_No_BeforeUpdate(Cancel As Integer)
If DLookup(Str("[Grumpy_No]"), "Grumpy", Str("[Grumpy_No]") = Me!Str(Grumpy_No)) Then
MsgBox "Number has already been entered in the database."
Cancel = True
Me!Grumpy_No.Undo
End If
End Sub
Any clues as to where I am going wrong would be very much appreciated
Looks to me like you're heading in the right direction but you need to fix your DLookup expression. Its third argument must be a single string. I don't see why Str() is useful --- just build a string. Actually I would use DCount instead of DLookup, but then the same issues still apply.
Private Sub Grumpy_No_BeforeUpdate(Cancel As Integer)
If DCount("[Grumpy_No]", "Grumpy", "[Grumpy_No] = " & Me!Grumpy_No.Value) > 0 Then
MsgBox "Number has already been entered in the database."
Cancel = True
'Me!Grumpy_No.Undo '<- consider allowing the user to see the value which failed
End If
End Sub
Note, if you can make Grumpy_No an autonumber primary key, Access will supply unique values automagically, so you wouldn't need your own code to check those values.

Basic Inventory Setup with Access

So I'm a Novice to access and need help finishing my Inventory Database.
Currently I have the Following Tables and the field in them:
(Table: Fields, first field is primary key)
Items: Item#, Item Desc, Item Spec Reorder Level, Qty to Reorder, Qty on Hand
Materials_Used: ID(just an Autonumber field), Project, Item#, Amount
Projects: Project
Purchase_Orders: PONum, Received Date
Receiving_Amount: ID(again autonumber), Item#, Amount, PONum
I'm having issues in 2 area's:
Tying in PONum with Items Receiving_Amount: Currently I have a Purchase_Orders form which asks the user to input the date and POnum and a sub form of the Receiving amount in datasheet form. Thing is after I enter a date and PONum, and move down to entering the Items received I get and Enter Parameter Value box Purchase_Orders.ID and Purchase_Orders.PONumber
------ This issues is solved thanks to Wayne!
Having the Qty on Hand for the Items table to automatically update once an item is Received through the PO form (adding to it) and Materials Used form (Subtracting)
Database Relationship
Since you will be working in a multi-user update environment, you will need to make sure there are no conflicts with other users. The safest approach is to use a TRANSACTION.
Next, you need to decide how and when to make the updates to your two tables. Let's go with 'Option 1' which is to have a button the user clicks when they are finished. You would need to call the following subroutine when they click the button. You should also keep track if the user made any changes to the subform, but forgot to click the 'Save' button.
Then I strongly suggest keeping track of the changes you have made. For example, user enters qty of 5, saves changes. Tomorrow, looks at the data, sees the 5 and wants to change it to 6... that will corrupt the true inventory. One method to prevent is to have a 'flag' for the PO line items indicating they have been processed and preventing updates again.
The following code is just a sample... I coded what I think should be the input and output recordsets, but you will need to insure the correct input rows are selected to be processed and then select the output row(s) for the tables.
Look for the comments with ## in them.... fix the code to use YOUR control names.
Let me know if you need more of an explanation.
Option Compare Database
Option Explicit
' BeginTrans, CommitTrans, Rollback Methods Example
' After the BeginTrans method starts a transaction that isolates all the changes made,
' the CommitTrans method saves the changes.
' Notice that you can use the Rollback method to undo changes that you saved using
' the Update method. Furthermore, the main transaction is nested within another transaction
' that automatically rolls back any changes made by the user during this example.
' One or more table pages remain locked while the user decides whether or not to accept the changes.
' For this reason, make sure you only execute the transaction on some event - don't allow a user
' to be interactive, else he may go to lunch and may lock pages someone else needs!
' Add to: Receiving_Amount: ID(again autonumber), Item#, Amount, PONum
' Subtract from: Materials_Used: ID(just an Autonumber field), Project, Item#, Amount
Sub BeginTransX_Update_Inventory()
On Error GoTo Error_trap
Dim wrkDefault As DAO.Workspace
Dim dbs As DAO.Database
Dim tblInput As DAO.recordSet
Dim tblItems As DAO.recordSet
'Dim tblMaterials As DAO.recordSet
' Get default Workspace.
Set wrkDefault = DBEngine.Workspaces(0)
Set dbs = CurrentDb
' ## Change the following line to use the name of the form control that has your PONum
Set tblInput = dbs.OpenRecordset("select * from MaterialsRec where PONum = " & Me.txtPONum & ";") '<<< This will be the source of your changes. Can use a query to filter exact rows.
' Start transaction.
wrkDefault.BeginTrans
Do While Not tblInput.EOF
Set tblItems = dbs.OpenRecordset("select * from [Items] where [Item#] = " & tblInput![item] & ";") ' <<< This will be where the updates are applied.
' Increase Qty on Hand
tblItems.Edit
tblItems![Qty on Hand] = tblItems![Qty on Hand] + tblInput!Amount
tblItems.Update
'## Add a text field named 'ProcStatus' to table MaterialsRec, or delete the following update ... your choice...
tblInput.Edit
tblInput!ProcStatus = "updated"
tblInput.Update
tblInput.MoveNext
Loop
' You can remove the following code if desired...
' Ask if the user wants to commit to all the changes made above.
If MsgBox("Save changes?", vbYesNo) = vbYes Then
wrkDefault.CommitTrans
Else
wrkDefault.Rollback
End If
tblInput.Close
tblItems.Close
'tblMaterials.Close
Set tblItems = Nothing
'Set tblMaterials = Nothing
Set dbs = Nothing
Set wrkDefault = Nothing
Exit Sub
Error_trap:
wrkDefault.Rollback
MsgBox "An error was encountered, but all changes were rolled back." & vbCrLf & _
"Err: " & Err.Number & vbCrLf & _
"Desc: " & Err.Description
End Sub

How to have at most n number of duplicates in a field

My question is somewhat unique I assume. Everybody wants to get rid of duplicates, but me on the other hand, I want to allow a specified number of duplicates to appear.
I'm creating a database for reserving dates for Blood donation campaigns.
My database consists of the
Date of campaign,
Name of organizer,
Contact info & venue.
Additionally every campaign will get a unique ID number. The catch is, we can accommodate only five campaigns per day, that is: The date column should be allowed to have at most five duplicates
Any ideas on how this can be achieved?
If you are entering the information directly into the table from within Access 2010 itself then you can add the following Before Change data macro to the table:
For more information on Data Macros see
Create a data macro
This is what you need to do. Create a New Form, based on the table. A lot more neater and also can capture all the information you need along with special conditions, like the one you have right now. The form can have all or some fields that are present in the table. Once the forms has been created, we will call it frm_EventMgm
You can create another Dashboard/welcome form where you can have one TextBox, for collecting the date you want to enter (dateEntryTxt) in the table and one button (addNewEntryBtn), which on lick will have this.
Private Sub addNewEntryBtn_Click()
If Not IsDate(Me.dateEntryTxt) Then
MsgBox "Please enter a valid date before you proceed.", _
vbCritical, "Missing Information !"
Exit Sub
End If
If DCount("*", "tbl_EventList", "DateFieldName = " & _
Format(Me.dateEntryTxt, "\#mm\/dd\/yyyy\#")) > 5 Then
MsgBox "The Date you selected has already have 5 bookings. " & _
"So please choose another date and try again.", vbInformation, _
"Cannot Add info. !"
Else
DoCmd.OpenForm "frm_EventMgm", DataMode:=acFormAdd
End If
End Sub
This is the best and easy way to get around your issue. Hope this helps.

Record how long a user is modifying a form in Microsoft Access

I'm using Access as a front end to SQL Server. We have a split form where the users select a record, insert some new information with the form, then continue on to the next record. My manager would like to see how long it takes a user to modify a record. So I would like a timer to start when someone clicks on a record then it to stop when they click on the next record or when they select complete in the form. I would like this imformation exported to an excel sheet. It might be easier to get the average time for each user since most users are modifiying over 100 records per day. Is there anyway this is possible?
the simple solution : you can write a function in the On Dirty event of the form and add a record to a table with current record's ID,Username and current time (starting time).
in the On AfterUpdate of the form use a function to update the same record and add current time as (Ending time).
When a user starts editing or adding a record, the time is registered in this table. when he/she updates the record, the time is added as ending time.
Now you have a table which contains ID, username, startTime, endingTime. with a query, you can calculate how much time is spent for each record, starting from editing, ending to updating. You can export this table to a excel sheet whenever you need.
the complex method:
I had a similar situation. I was asked to close the database if the user is idle for a specified time (for network traffic problems)
I used the bellow function in timer event of the form. It reads the name of the active form every 5 seconds and saves it in a static variable. this function compares Screen.activeform.name with this static variable every 5 seconds.
if the name of active form is different with this static variable, it shows the user is active (doing something), so it resets the timer static variable. otherwise it means the user is idle and adds the timer.
when the timer reaches to a specified amount which is set in application's option (let's say 5 min) it means that the user has been idle for 5 min and I simply run the Application.Quit and close the database.
I'm busy at present and have no time to work on it. You can modify this function to check the current record or even current control (Instead of current form) and before resetting the static timer variable, export the timer variable, username and ID of the record to a table and calculate the spent time with a query and export it to excel.
Hope it helps.
If I find a spare time this weekend, I'll try to make a simple database to show how actually it works
MyTimer:
' IDLEMINUTES determines how much idle time to wait for before
' running the IdleTimeDetected subroutine.
IdleMinutes = fGetOption("Machine", "AutoLogOff", False)
If IdleMinutes = 0 Then Exit Sub
Static PrevControlName As String
Static PrevFormName As String
Static ExpiredTime
Dim ActiveFormName As String
Dim ActiveControlName As String
Dim ExpiredMinutes
On Error Resume Next
' Get the active form and control name.
ActiveFormName = Screen.ActiveForm.Name
If Err Then
ActiveFormName = "No Active Form"
Err = 0
End If
ActiveControlName = Screen.ActiveControl.Name
If Err Then
ActiveControlName = "No Active Control"
Err = 0
End If
' Record the current active names and reset ExpiredTime if:
' 1. They have not been recorded yet (code is running
' for the first time).
' 2. The previous names are different than the current ones
' (the user has done something different during the timer
' interval).
If (PrevControlName = "") Or (PrevFormName = "") _
Or (ActiveFormName <> PrevFormName) _
Or (ActiveControlName <> PrevControlName) Then
PrevControlName = ActiveControlName
PrevFormName = ActiveFormName
ExpiredTime = 0
Else
' ...otherwise the user was idle during the time interval, so
' increment the total expired time.
ExpiredTime = ExpiredTime + Me.TimerInterval
End If
' Does the total expired time exceed the IDLEMINUTES?
ExpiredMinutes = (ExpiredTime / 1000) / 60
'Debug.Print ExpiredMinutes
If ExpiredMinutes >= IdleMinutes Then
' ...if so, then reset the expired time to zero...
ExpiredTime = 0
' ...and call the IdleTimeDetected subroutine.
IdleTimeDetected ActiveFormName
End If
Sub IdleTimeDetected(ActiveFormName As String)
DoCmd.Close acForm, ActiveFormName
CloseAllForms
Application.Echo True
Application.Quit
End Sub
Here's a simple sample database to help you.
Sample Database
This database is written in Office 2013. I hope you can open it.
Open the frm Form and start editing a record or start inserting a new record.
the starting and ending of editing/inserting of a record will be registered in result table. You can export this table to a excel file at the end of the day.
Be careful that this database needs some modifications.
for example you must add some codes to recognize the current username
I think you can manage this section