Create a history /Log table based on status change - ms-access

So my client wants is
If a user changes the status of the case then a log needs to be generated in a history table.
Basically, a new history record needs to be made in the history table as soon as the case status is changed everytime.
So the history table new record needs to based on only status Column.
How can I achieve this

After lot of digging, i was able to find the solution.
I know its not much work...But I am fairly new to the VBA like very basic...This is a small win for me :D
Private Sub Form_beforeUpdate(Cancel As Integer)
Dim ststatus As String
Dim ststatus1 As String
ststatus = Me.Case_Status.OldValue
ststatus1 = Me.Case_Status
If ststatus <> ststatus1 Then
DoCmd.RunSQL "Insert Into case_history select * from cases " & _
"Where case_id=" & Case_ID
End If
End Sub

Related

vba code to find a blank reord hanging up

I have an access database that I have employer information. Such as name, address, phone number, contact person, business type, etc. There are multiple people entering data & occasionally there is a blank record, because there was an entry started & not finished.
I am trying to use VBA to find the blank record, so I can enter new data in the blank record. Here is the current code.
Private Sub Command107_Click()
If DCount("*", "Blank Query") = "0" Then
MsgBox ("No blank records found. Thank You!")
Else
DoCmd.GoToRecord , , [Queries]![Blank Query2], offset:=1
End If
End Sub
Currently if there is a blank record it hangs on
DoCmd.GoToRecord , , [Queries]![Blank Query2], offset:=1
If there is no blank records, it runs & give the appropriate response.
The only field I am concerned about is, name and address.
Ideally, I would like to have it go to the blank record.
You could use this code:
Dim rst As DAO.Recordset
Dim strSQL As String
strSQL = "select * from tblContacts where " & _
"IsNull([Name]) or IsNull(Address)"
Set rst = CurrentDb.OpenRecordset(strSQL)
If rst.RecordCount <> 0 Then
Me.Recordset.FindFirst "id = " & rst!ID
Else
MsgBox "no blank reocrds found"
End If
rst.Close
DoCmd.GoToRecord will only work if your form is based on your query [Blank Query2].
Apart from that, your syntaxis is incorrect, referring to https://msdn.microsoft.com/en-us/library/office/ff194117.aspx
If this issue occurs on a regular basis, I'd create a form based on [Blank Query2] and add this form to your maintenance / application management frontend (assuming you've split your database into a backend and frontend).
This will give you the ID of the first incomplete Record
RecordID=Nz(DLookup("TablePrimaryKey","TableName","FieldThatCouldBEEmpty IS NULL"),0)
assuming your table has a proper Primary Key. If it does not you can request any field that would help you identify the record, just be sure to change 0 to an appropriate "no record found" value for whatever field you are looking up.
This will just delete any reocrds that are incomplete.
DoCmd.RunSQL "DELETE FROM TableName WHERE FieldThatCouldBEEmpty IS NULL"

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

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: Save form data to 2 tables at the click of a button

I am creating an asset management database with 2 tables (Assets and AssetMovements) and one form (Assets).
I need to keep records of every asset movement, so every time a new asset is added to the Assets table or the 'Location' value for an existing asset record is modified, the record should be saved to the AssetMovements table. The AssetMovements table is just there to record the transactions.
How can I achieve this? I would be grateful for any pointers I can get, or if anyone can suggest a better method of keeping the movement records.
Thank you.
Seeing you are using Access 2010, this looks like a good excuse for a Data Macro A data macros will run even when the data is updated from outside of MS Access.
I created an Assets table and an AssetMovements table, the AssetMovements table has a field ActionDate with a default value Now(), which sets the date the action occurred.
You will need two macros on the Assets table:
And that is all you need to do, as is shown below.
After adding or changing a record, the data is automatically recorded in the AssetMovements table:
You can the run a little sample VBScript ...
strCon = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=z:\docs\demo.accdb"
Set cn = CreateObject("ADODB.Connection")
Set rs = CreateObject("ADODB.Recordset")
cn.Open strCon
sSQL="INSERT INTO Assets (Asset,Location) Values ('Printer',7)"
cn.Execute sSQL
sSQL="Update Assets Set Location=5 Where Asset='Printer'"
cn.Execute sSQL
To see that this also updates the AssetMovements table.
There is also a LogEvent data macro for more complete recording of changes.
The button has a click event that is fired when you click it. Use VBA to write some code that is executed when the button is clicked.
When you click the button, you would then save the record to Assets. Then copy that record to the AssetMovements table using a query. So, the code will look something like this:
Dim OldLocation As String
Private Sub CmdSave_Click()
DoCmd.RunCommand acCmdSaveRecord
End Sub
Private Sub Form_AfterUpdate()
Dim strSQL
If OldLocation <> Location.Value Then
strSQL = "INSERT INTO AssetMovements SELECT T1.* FROM Assets WHERE Assets.ID = "
strSQL = strSQL & Me.ID
CurrentDb.Execute strSQL
End If
End Sub
Private Sub Form_BeforeUpdate(Cancel As Integer)
OldLocation = Me.Location.OldValue
End Sub
Private Sub Form_Current()
OldLocation = Me.Location.Value
End Sub
This will then copy the current record of the form, using a unique ID (I guessed at AssetID), to the AssetMovement table.

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.