A USPS HR Training Department ran on paper logs and copy-paste chaos. This is the rebuild: a validated Excel + VBA intake, a Power Query master log, and a dashboard the Training Specialist actually uses.
Train_Log table, one row per class entry
Sub SubmitToTrainingSpecialist()
Dim ws As Worksheet: Set ws = ThisWorkbook.Sheets("Intake")
Dim csvPath As String, dept As String, classDate As String
Dim fileNum As Integer, r As Long, lastRow As Long
dept = ws.Range("Department").Value
classDate = Format(ws.Range("ClassDate").Value, "yyyymmdd")
csvPath = "\\hrssc\training\intake\" & dept & "_" & classDate & ".csv"
lastRow = ws.Cells(ws.Rows.Count, "B").End(xlUp).Row
fileNum = FreeFile
Open csvPath For Output As #fileNum
Print #fileNum, "Name,EIN,Modifier,CreditHours"
For r = 6 To lastRow
If ws.Cells(r, "B").Value <> "" Then
Print #fileNum, ws.Cells(r, "B").Value & "," & ws.Cells(r, "C").Value & "," & _
RoundToQuarterHour(ws.Cells(r, "D").Value) & "," & ws.Range("CreditableHours").Value
End If
Next r
Close #fileNum
SendConfirmationEmail dept, classDate, lastRow - 5
End Sub
Function RoundToQuarterHour(hrs As Double) As Double
RoundToQuarterHour = Application.WorksheetFunction.Round(hrs * 4, 0) / 4
End Function
Sub SendConfirmationEmail(dept As String, classDate As String, empCount As Long)
Dim outApp As Object, outMail As Object
Set outApp = CreateObject("Outlook.Application")
Set outMail = outApp.CreateItem(0)
With outMail
.To = "training.specialist@usps.gov"
.Subject = "Attendance logged: " & dept & " " & classDate
.Body = empCount & " employees logged. CSV saved to intake folder."
.Send
End With
End Sub
' Attrition — Yes/No/tardy against hours available vs. earned
=IF(C2="Yes", 1, IF(C2="no", 0, IF(C2="tardy", SUM(J2/I2), "")))
' Department — parsed from "DEPT - TOPIC" course name
=LEFT(Train_Log[[#This Row],[COURSE NAME:]], FIND(" - ", Train_Log[[#This Row],[COURSE NAME:]]) - 1)
' Course Topic — same course name, right-hand side
=MID(Train_Log[[#This Row],[COURSE NAME:]], FIND(" - ", Train_Log[[#This Row],[COURSE NAME:]]), 13)
' Code — unique key: topic + start date + end date
=MID(E2, FIND(" - ", E2) + 3, LEN(E2)) & "_" & TEXT(F2, "yyyymmdd") & "_" & TEXT(H2, "yyyymmdd")
' Dashboard — single-employee lookup against the live table
=VLOOKUP(B4, Train_Log[], 3, FALSE)
=VLOOKUP($B$4, Train_Log[], 17, )
' thematrix — live per-employee row spill for whoever is in Dashboard!B4
=FILTER(Train_Log[], Train_Log[NAME] = Dashboard!B4, "not found")