I have a table that contains information about when employees started and ended and I want to get a report on how much was spent each month over time.
Here's the table (I'm simplifying a bit here for clarity)
Example:
EmployeeID, Name, Position, StartDate, EndDate, MonthlySalary
1, John Doe, Intern, 2/1/2010, 1/1/2013, $1,000
2, Jane Doe, CEO, 1/1/2010, , $10,000
3, Bob Doe, CFO, 2/1/2010, 2/1/2013, $8,000
...
The output I would like to get is a table that looks like this:
ExpenseDate, Amount, EmployeeCount
1/1/2010, $10,000, 1
2/1/2010, $11,000, 2
3/1/2010, $11,000, 2
4/1/2010, $19,000, 3
...
1/1/2013, $18,000, 2 -- intern left
2/1/2013, $10,000, 1 -- CFO left
...
3/1/2014, $10,000, 1 -- no end date for CEO
If the information was in this format below, I could pivot it pretty easily to get what I need above:
EmployeeID, ExpenseDate, Amount
1, 2/1/2010, $1,000
1, 3/1/2010, $1,000
1, 4/1/2010, $1,000
...
2, 2/1/2010, $10,000
2, 3/1/2010, $10,000
2, 4/1/2010, $10,000
...
Could one of these tables be created using some VBA code?
I'm using Access 2010 if it matters
The following code will use your existing data to build a table of payments for each employee, for each month employed. You need to address what to do for partial months pay (divide by 30?)
Option Compare Database
Option Explicit
Function Build_Emo_Pay_Table()
Dim strSQL As String
Dim dbs As DAO.Database
Dim rsIN As DAO.Recordset
Dim rsOT As DAO.Recordset
Dim iMonths As Integer
Dim iLoop As Integer
Dim datLast As Date
Set dbs = CurrentDb
On Error Resume Next
' !! NOTE !! Decide how to 'maintain' pay table. Choices are rebuild each time,
' or add new months, or adjust previous 'partial month'
' This code deletes table 'tblEmpPay' each time and rebuilds.
Debug.Print dbs.TableDefs("tblEmpPay").Name ' To raise error
If Err.Number = 0 Then
Debug.Print Err.Number & vbTab & Err.Description
dbs.TableDefs.Delete ("tblEmpPay")
End If
On Error GoTo 0
strSQL = "CREATE TABLE tblEmpPay (PayEmpID INT, PayDate Date, PayEmpPaid long);"
dbs.Execute strSQL
strSQL = "CREATE UNIQUE INDEX PayKey ON tblEmpPay (PayEmpID, PayDate) WITH DISALLOW NULL;"
dbs.Execute strSQL
strSQL = "select * from tblEmployee Order by EmpID;"
Set rsIN = dbs.OpenRecordset(strSQL)
Set rsOT = dbs.OpenRecordset("tblEmpPay", adOpenDynamic)
' Process each employee record
Do While Not rsIN.EOF
If IsDate(rsIN!empLeave) Then
datLast = rsIN!empLeave
Else
datLast = Date
End If
iMonths = DateDiff("m", rsIN!empStart, datLast) ' Get Months employeed (note will not get partial month!)
Debug.Print rsIN!empName & vbTab & rsIN!empStart & vbTab & rsIN!empLeave & vbTab & DateDiff("m", rsIN!empStart, rsIN!empLeave)
'!! NOTE !! Depending on how you want to handle partial months, change next line. i.e. If employee leaves
' on first day of month, or during the month, what is your formula for how much do they get paid?
For iLoop = 0 To iMonths - 1
rsOT.AddNew
rsOT!PayEmpID = rsIN!empId
rsOT!PayDate = DateAdd("m", iLoop, rsIN!empStart)
rsOT!PayEmpPaid = rsIN!empsalary
rsOT.Update
Next iLoop
rsIN.MoveNext
Loop
rsIN.Close
Set rsIN = Nothing
Set dbs = Nothing
End Function
Related
Alright, so here's what happened :
I had a wide table, that needed to be a long table. I used the code below (CODE 1) to fix that problem:
It seemed to have worked, though I am now finding minor errors in the data, while I will need to resolve those, that isn't what this question is about.
In the end, my table looks correctly, and here is an actual record from the database, in fact it is the record that called my attention to the issues:
tbl_CompletedTrainings:
ID
Employee
Training
CompletedDate
306
Victoria
Clozaril
5/18/2016
306
20
8
5/18/2016
the second row is to show what the database is actually seeing (FK with both Employee and Training tables) Those tables have the following formats:
tbl_employeeInformation:
ID
LastName
FirstName
Address
Line2
City
State
Zip
Site1
Site2
Site3
20
A.
Victoria
6 Street
City
State
00000
3NNNN
4
Eric
A.
15 Street
City
State
00000
3nnnnn
tbl_Trainings:
AutoID
TrainingName
Expiration
6
Bloodborne
Annual
8
Clozaril
Annual
When the query in (CODE 2) is run on this table, the following record is returned
report Query:
LastName
FirstName
Training
CompletedDate
Site1
Site2
Site3
ID
Accccc
Eric
Bloodborne Pathogens
5/18/2016
3NN-NN
N/A
N/A
306
Notice that the ID in the report Query is only there as I was checking records, and is called from the tbl_CompletedTrainings. So here's the question, What is happening?! If the record was just wrong, and not pulled I could understand it, but that's not what's happening. Worse still is the date is the correct date for the training the query returns, but not for the training listed in the table.
Related issue, possibly, I had noticed that when I queried the table with a call on the foreign key, it returns records that are 2 off of the requested training number. Notice that this is the case here as well. The training listed, Clozaril, is exactly two further down the line than the training Bloodborne Pathogens, Key 8 and 6 respectively.
Any help would be very much appreciated in this matter, as I can't seem to catch what is causing the issue. Yet it must be something.
(CODE 1)
Option Compare Database
Option Explicit
Sub unXtab()
On Error GoTo ErrHandler
Dim db As DAO.Database
Dim rsxtab As DAO.Recordset
Dim rsutab As DAO.Recordset
Dim counter As Integer
Dim loopint As Integer
Dim qryGetNameID As DAO.Recordset
Dim qryGetTrainingNameID As DAO.Recordset
Dim expires As Date
Dim namevar As String
Dim lname As String
Dim fname As String
Set db = CurrentDb
Set rsxtab = db.OpenRecordset("SELECT * FROM [Employee Training Log];")
If Not (rsxtab.BOF And rsxtab.EOF) Then
db.Execute "DELETE * FROM tbl_CompletedTrainings;"
Set rsutab = db.OpenRecordset("SELECT * FROM tbl_CompletedTrainings WHERE 1 = 2;")
counter = rsxtab.Fields.Count - 1
Do
For loopint = 2 To counter
namevar = rsxtab.Fields(loopint).Name
lname = rsxtab("[Last Name]")
fname = rsxtab("[First Name]")
Select Case namevar
Case "First Name"
Case "Last Name"
Case "Date of Hire"
Case Else
If rsxtab.Fields(loopint) <> "" Or Not IsNull(rsxtab.Fields(loopint)) Then
Set qryGetTrainingNameID = db.OpenRecordset("SELECT AutoID FROM Trainings WHERE [Training Name] = " & Chr(34) & namevar & Chr(34) & ";")
Set qryGetNameID = db.OpenRecordset("SELECT ID FROM tbl_EmployeeInformation WHERE LastName = " & Chr(34) & lname & Chr(34) & _
" AND " & Chr(34) & fname & Chr(34) & ";")
rsutab.AddNew
Debug.Print lname
Debug.Print fname
Debug.Print namevar
Debug.Print qryGetNameID.Fields(0)
Debug.Print qryGetTrainingNameID.Fields(0)
rsutab.AddNew
rsutab("Employee") = qryGetNameID.Fields(0)
rsutab("Training") = qryGetTrainingNameID.Fields(0)
rsutab("CompletedDate") = rsxtab.Fields(loopint)
rsutab.Update
End If
End Select
Next loopint
rsxtab.MoveNext
Loop Until rsxtab.EOF
End If
exitSub:
On Error Resume Next
rsxtab.Close
rsutab.Close
Set rsxtab = Nothing
Set rsutab = Nothing
Set db = Nothing
Exit Sub
ErrHandler:
MsgBox Err.Number & " : " & Err.Description & vbCrLf & vbCrLf & " on this field: " & namevar, vbOKOnly + vbCritical
End Sub
(CODE 2)
SELECT EI.LastName, EI.FirstName, T.TrainingName AS Training, CT.CompletedDate, EI.Site1, EI.Site2, EI.Site3, CT.ID
FROM tbl_EmployeeInformation AS EI
INNER JOIN (tbl_CompletedTrainings AS CT
INNER JOIN tbl_Trainings AS T ON CT.Training = T.AutoID) ON EI.ID = CT.Employee;
Using Access 2010 and relatively new to Access in general. For simplicity say I have the following two tables:
Tbl 1: Employee_Info
(Fields: Employee_ID (primary key), Employee_Name, & Employee_Status (active, inactive, termed))
Tbl 2: Monthly_Sales
(Fields: Month/Year, Sales, & Employee_ID (foreign key))
Every month a member of our team has to enter in the monthly sales for all active employees and I would like to design a form where all active employees are displayed as records and the person doing the data entry only needs to enter the month and year and sales. Something similar to this:
Date: User inputs date here once and pre-populates all the records below
Column 1: Employee_ID: All active employee IDs are displayed
Column 2: Sales:These fields are blank and user enters in the monthly sales.
I have looked all over the internet and have been unable to find a solution to this problem. I don't think it is as simple as using an append query but again I am relatively new to access. Thanks in advance for your help.
You can use the following code to add records for a month... just change table / field names to match your DB. Your table design should prevent duplicate Employee_ID and YearMonth combinations. If so, code will ignore errors if someone runs code twice for same month. If not, you need method of insuring no dups are added.
Option Compare Database
Option Explicit
Function Create_New_Rows()
Dim strSQL As String
Dim i As Integer
Dim iAdd As Integer
Dim iDuration As Integer
Dim lCampaignID As Long
Dim dbs As DAO.Database
Dim rsIN As DAO.recordSet
Dim rsOT As DAO.recordSet
Dim DateRange As Date
Dim dStart As Date
Dim dEnd As Date
Dim InDate As String
On Error GoTo Error_Trap
InDate = InputBox("Input the Year and Month to process. i.e. 201610", "Enter YYYYMM", _
Format(YEAR(Date) & month(Date), "000000"))
' Add some validation to insure they enter a proper month and year!!
dStart = Mid(InDate, 5, 2) & "/01/" & left(InDate, 4)
dEnd = DateSerial(YEAR(dStart), month(dStart) + 1, 0)
Set dbs = CurrentDb
strSQL = "SELECT Employee_ID, Employee_Status " & _
"FROM Table1 " & _
"Where Employee_Status = 'active';"
Set rsIN = dbs.OpenRecordset(strSQL)
Set rsOT = dbs.OpenRecordset("Table2")
If rsIN.EOF Then
MsgBox "No Active Employees found!", vbOKOnly + vbCritical, "No Records"
GoTo Exit_Code
Else
rsIN.MoveFirst
End If
Do While Not rsIN.EOF
DateRange = dStart
Do
With rsOT
.AddNew
!Employee_ID = rsIN!Employee_ID
!MonthYear = Format(YEAR(DateRange) & month(DateRange), "000000")
.Update
End With
DateRange = DateAdd("d", 1, DateRange)
If DateRange > dEnd Then
Exit Do
End If
Loop
rsIN.MoveNext
Loop
Exit_Code:
If Not rsIN Is Nothing Then
rsIN.Close
Set rsIN = Nothing
End If
If Not rsOT Is Nothing Then
rsOT.Close
Set rsOT = Nothing
End If
dbs.Close
Set dbs = Nothing
MsgBox "Finished"
Exit Function
Error_Trap:
Debug.Print Err.Number & vbTab & Err.Description & vbCrLf & "In: Create_New_Rows"
' Ignore if duplicate record
If Err.Number = 3022 Then
Resume Next
End If
MsgBox Err.Number & vbTab & Err.Description & vbCrLf & "In: Create_New_Rows"
Resume Exit_Code
Resume
End Function
my project contains a MS Acces 2003 database, The table in the database contains a column called students name. The single column contains n numbers of names of student. For eg. John, Jim, Johny, Tom etc. They are dynamically added. Now what I want is, I want a complete list of all the names in the column.
Like for eg. if the column is
Student_name
John, Jim, Johny, Tom, Jack
I want output as:
Student_name
John
Jim
Johny
Tom
Jack
The query must support MS Access. as i'm fetching the data in html file and I've attached that html file to MS Aacess database
Sorry, but MS Access doesn't provide functionality to run query in recursive mode as CTE does. It's possible to use VBA macro to proceed through the collection of students to split comma separated values into set of records ;)
Let say, you have got table Student with fields:
ID (numeric - integer),
Students (string - char)
Sample data:
Id Students
1 John, Jim, Johny, Tom, Jack
2 Paula, Robert, Tim, Dorothy
5 Frank, Ramona, Giorgio, Teresa, Barbara
19 Isabell, Eve, Ewelina, Tadit
You need to create another table to store results of macro.
CREATE TABLE CTE1
(
ID INT,
OrigValue CHAR(255),
SingleValue CHAR(255),
Remainder CHAR(255)
);
To add macro, please do the following steps:
go to Visual Basic code Pane
insert new module
copy below code and paste it into previously added module
move the mouse cursor into **ModifyMyData** procedure by clicking whenever inside its body
run code (F5)
Option Compare Database
Option Explicit
'need reference to Microsoft ActiveX Data Object 2.8 Library
Sub ModifyMyData()
Dim sSQL As String
Dim rst As ADODB.Recordset
Dim vArray As Variant
Dim i As Integer
'clear CTE table
sSQL = "DELETE * FROM CTE;"
CurrentDb.Execute sSQL
'initial query
sSQL = "INSERT INTO CTE (ID, OrigValue, SingleValue, Remainder)" & vbCr & _
"SELECT ID, Students AS OrigValue, TRIM(LEFT(Students, InStr(1,Students,',')-1)) AS SingleValue, " & _
"TRIM(RIGHT(Students,LEN(Students)-InStr(1,Students,','))) AS Remainder" & vbCr & _
"FROM Student;"
CurrentDb.Execute sSQL
sSQL = "SELECT ID, OrigValue, SingleValue, Remainder" & vbCr & _
"FROM CTE"
Set rst = New ADODB.Recordset
rst.Open sSQL, CurrentProject.Connection, adOpenStatic
With rst
'fill rst object
.MoveLast
.MoveFirst
'proccess through the
Do While Not rst.EOF
'Split Remainder into array
vArray = Split(.Fields("Remainder"), ",")
'add every single value
For i = LBound(vArray) To UBound(vArray)
sSQL = "INSERT INTO CTE (ID, OrigValue, SingleValue, Remainder)" & vbCr & _
"VALUES(" & .Fields("ID") & ", '" & .Fields("OrigValue") & "','" & vArray(i) & "','" & GetRemainder(vArray, i + 1) & "');"
CurrentDb.Execute sSQL
Next
.MoveNext
Loop
.Close
End With
Set rst = Nothing
MsgBox "Ready!"
DoCmd.OpenTable "CTE"
End Sub
Function GetRemainder(vList As Variant, startpos As Integer) As String
Dim i As Integer, sTmp As String
For i = startpos To UBound(vList)
sTmp = sTmp & vList(i) & ","
Next
If Len(sTmp) > 0 Then sTmp = Left(sTmp, Len(sTmp) - 1)
GetRemainder = sTmp
End Function
I am using Vb6 ! I have one datagrid named "Datagrid1" and i display certain contents such as subjectname, subjectcode, theory_practical from the table named "subjectcode" in Datagrid1 from access database.
And i have another table named "feedetail". My doubt is, if the "theory_practical" value is theory means, then it should display the theoryfee from the table named feedetail or if "theroy_practical" value is practical means, then it should display practical fee in the new column named "Fee" in datagrid1.
I am having confusion with the sql statement and displaying in datagrid ! here is my code that i used!
I want to display the corresponding fee in the next column to the Theory_Practical heading ! I can't attach a screenshot file n it shows error! so here is the link of the screenshot file! Thanks in advance !
Public con As New ADODB.Connection
Public rs As New ADODB.Recordset
Public rs2 As New ADODB.Recordset
Private Sub Command1_Click()
Dim semesternew As String
semesternew = semester.Caption
Select Case semesternew
Case "I"
semester1 = 1
Case "II"
semester1 = 2
Case "III"
semester1 = 3
Case "IV"
semester1 = 4
Case "V"
semester1 = 5
Case "VI"
semester1 = 6
End Select
DataGrid1.ClearFields
rs.Open "select Subjectcode,Subjectname,Theory_Practical from subjectcode as s where s.Degree='" & Degree & "' and s.Branch='" & course & "' and s.Year1='" & year1 & "' and s.Year2='" & year2 & "' and s.Semester='" & semester1 & "' ", con, 1, 3
Set DataGrid1.DataSource = rs
End Sub
Private Sub Command2_Click()
examfee2.Hide
examfee1.Show
End Sub
Private Sub Command4_Click()
If rs!Theory_Practical = "theory" Then
rs2.Open "select Theoryfee from Degreelevel", con, 1, 3
Set DataGrid2.DataSource = rs2
ElseIf rs!Theory_Practical = "practical" Then
rs2.Open "select Practicalfee from Degreelevel", con, 1, 3
Set DataGrid2.DataSource = rs2
End If
End Sub
Private Sub Form_Load()
Set con = New ADODB.Connection
con.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=.\college.mdb;Persist Security Info=False"
con.CursorLocation = adUseClient
Set rs = New ADODB.Recordset
End Sub
Fee table:
Heading(Year1,Year2,Theoryfee,Practicalfee)
values (2001,2003,440,320)
All other values like this only with different values !
subjectcode table :
Heading(Year1,Year2,Subjectcode,Subjectname,Theory_Practical)
values (2001,2003,RCCS10CS1,C programming, Theory)
You can use a query like so:
SELECT subjectcode.Year1, subjectcode.Year2,
subjectcode.Subjectcode, subjectcode.Subjectname,
subjectcode.Theory_Practical, q.fee
FROM subjectcode
INNER JOIN (
SELECT fees.Year1, fees.Year2, "Theory" As FeeType,
fees.Theoryfee As Fee
FROM fees
UNION ALL
SELECT fees.Year1, fees.Year2, "Practical" As FeeType,
fees.Practicalfee As Fee
FROM fees) AS q
ON (subjectcode.Theory_Practical = q.FeeType)
AND (subjectcode.Year2 = q.Year2)
AND (subjectcode.Year1 = q.Year1)
However, you would be much better off redesigning your fees table to match the data returned by the inner sql, that is, a different line for theory and practical fees:
Year1 Year2 FeeType Fee
2001 2003 Theory 440
2001 2003 Practical 320
How can i compare two MS ACCESS 2007 databases.Both databases contain same tables with same feilds ad structure.i need to compare the record values between two databases to detect any difference in record values.
ACCESS 2007 Database1
serial no. | NAME | ADDRESS
1 smith street 1
2 john street 4
3 alix street 8
ACCESS 2007 Database2
serial no.| NAME | ADDRESS
1 smith street 1
2 jhn stret 4
3 alix street 8
I need a VBA code for ms access that can detect the differece of records,just as the records at serial number two.
First thing you should do is link in one of the tables to the other database, e.g link the Database 2 table into database one (this allows both to be queried together) then you could use this simple example with concatenation to determine if all the fields strung together match based on the serial number:
SELECT T1.*, T2.*
FROM Table1 As T1, Table2 As T2
WHERE T2.[serial no.] = T1.[serial no.]
AND T2.[NAME] & T2.[ADDRESS] <> T1.[NAME] & T1.[ADDRESS]
You could also specify the columns with each of their own condition if you prefer.
NOTE: This is assuming you are only looking for differences where the serial no matches, if you also need to identify records that may appear in one table but not the other then you will need to use an "Un-matched" query, the query designer can help you with this or post back and I can update my answer.
Option Compare Database
Private Sub Command4_Click()
Dim tablename1, tablename2 As String
tablename1 = Text0.Value
tablename2 = Text2.Value
'On Error GoTo Err_cmdValidateGeneralInfo_Click
Dim F As DAO.Field
Dim rs As DAO.Recordset
Dim rs1 As DAO.Recordset
Set curDB = CurrentDb()
'If Me.DateModified = Date Then
'Adds new employees to the TT_GeneralInfo table in the FTEI_PhoneBook.mdb - which is used thru out the AP databases.
' DoCmd.OpenQuery "qryEmpData_TT_General"
strsql = "Select * from " & tablename1
Set rs = curDB.OpenRecordset(strsql)
strsql1 = "Select * from " & tablename2
DoCmd.CopyObject , "Unmatched_records", acTable, tablename1
curDB.Execute "DELETE FROM Unmatched_records"
Set rs1 = curDB.OpenRecordset(strsql1)
Do Until rs.EOF
For Each F In rs.Fields
If rs.Fields(F.Name) <> rs1.Fields(F.Name) Then
'rs.Edit
strsql = "Select * into test from " & tablename1 & " where " & F.Name & " = """ & rs.Fields(F.Name) & """"
DoCmd.RunSQL strsql
If DCount(F.Name, "test") <> 0 Then
GoTo append_unmatch
'appending unmacthed records
append_unmatch:
strsql2 = "insert into Unmatched_records Select * from test"
DoCmd.RunSQL strsql2
'if record doesnt match move to next one
GoTo Nextrecord
End If
' rs.Fields(F.Name) = rs1.Fields(F.Name)
' rs.Update
End If
Next F
Nextrecord:
rs.MoveNext
rs1.MoveNext
Loop
'To check whether tables matched or not
Dim rs2 As DAO.Recordset
strsql3 = "select * from Unmatched_records"
Set rs2 = curDB.OpenRecordset(strsql3)
For Each F In rs2.Fields
If DCount(F.Name, "Unmatched_records") <> 0 Then
MsgBox ("The two tables didnt match. Check table test for unmatching reocrds.")
Else
MsgBox ("Tables match!")
End If
Exit Sub
Next F
rs2.Close
End Sub