At work I began to need to track how often my team (or myself) was being interrupted, especially for un-ticketed or non-Jira task duties..
- Who was being interrupted (the me or my team part)
- Who interrupted us
- How much time did it take
- What was the method of interruption
- what the interruption involved.
This allowed us to better guide people to follow process, or review/create KB material if needed to help deter interruptions.
Since one option is to open a Read Only report in a CSV file, you can safely play around with the report in excel, pivot data, graph charts etc to help visualize metrics if needed, without corrupting the data file. (Read only as in, changes to the report do not write to the database file, but you can still do whatever you want to the CSV file.)
As with all things, i'm sure someone here can look at this and make it even better (especially the GUI which I am sure is laughable), but we've discovered that the data provided by tracking productivity interruptions has helped us identify offenders and schedule process training or other automations to help minimize or eliminate future interruptions from frequent offenders, or help with making cases about project interruptions due to other priorities (say a severity incident, or impromptu emergency from someone you probably shouldn't say no to).
Quick Start Guide:
on first use:
1) click New Database
2) Create a TXT file in a location of your choosing, then select that file
3) you can now save input with the GUI.
Other notes:
- The LogonID field is freeform, so if you wanted to track against something other than people, you may (like a cross-team project name for example)
- The Minutes/duration is also freeform if you want a custom value.
- The "report" opens data in CSV. If you are using excel you can then Pivot table & Graph out any datapoint you would like.
- If you only use this for yourself, you can create a local or home-drive file
- if you want this accessible for a team, you can create a file on a team's network drive
- if you want this available through out an entire department/business, you can create a file on a network share available by all teams
Code: Select all
;---------------------------------------------------------------
; Rudimentary Tracker. CTRL + WinKey + T
; While the LogonID field was built in mind with AD User IDs, it is Free Form so you can track against a person or a project if desired.
;---------------------------------------------------------------
;-----------------
; Set Hotkey to desired hotkey
^#t::
;-----------------
; Check for INI settings file which houses the DB path and dropdown menu settings
; If no existing settings, create some basic settings.
IfNotExist, %A_MyDocuments%\distracktersettings.ini
{
defaultdb = Please Connect to or Create a Database
timedurdropdown = 5||10|15|20|25|30|35|40|45|50|55|60
interruptname = Phone|Walk-up|Email|IM / Skype|Slack / Teams
IniWrite, %timedurdropdown%, %A_MyDocuments%\distracktersettings.ini, timeduration, Key
IniWrite, %interruptname%, %A_MyDocuments%\distracktersettings.ini, categories, Key
IniWrite, %defaultdb%, %A_MyDocuments%\distracktersettings.ini, DBpath, Key
}
;-----------------
; Check if Window is already open and activate it.
IfWinExist, DisTrackter
{
WinActivate, DisTrackter
}
else,
{
;-----------------
; GUI
; Import settings from INI
IniRead, timetrackerdb, %A_MyDocuments%\distracktersettings.ini, DBpath, Key
IniRead, timedurdropdown, %A_MyDocuments%\distracktersettings.ini, timeduration, Key
IniRead, interruptname, %A_MyDocuments%\distracktersettings.ini, categories, Key
; Button/Text for Instructions Connect Database and New Database
Gui, 99:Add, Text, x12 y3 w110 r1 ginstructions cblue, Click for instructions
Gui, 99:Add, text, x130 y3 w110 r1 gchangedb vchangedb cgray, [ Connect Database ]
Gui, 99:Add, Text, x250 y3 w110 r1 gnewdb vnewdb cgray, `+[ ] New database
; ; ComboBox Group (To replace Radio Buttons and allow for custom Interruption Type)
Gui, 99:Add, GroupBox, x5 y21 h44 w335 cpurple center, Interruption Type / Project Name / Ticket#
Gui, 99:Add, ComboBox, x12 y37 w320 vdistruptiontype, %interruptname%
; Text Fields
Gui, 99:Add, Text, x5 y72 w40, LogonID:
Gui, 99:Add, Edit, x50 y70 w75 voffender,
Gui, 99:Add, Text, x5 y100 w40, Desc:
Gui, 99:Add, Edit, x50 y95 w290 vdetails,
Gui, 99:Add, Text, x128 y72 w40, Duration/Min:
Gui, 99:add,ComboBox, x195 y70 w50 vtimespent, %timedurdropdown%
; Buttons
Gui, 99:Add, Button, x252 y70 w90 h20 gcheckname checkname, Check LogonID
Gui, 99:Add, Button, x5 y130 w65 h20 greport vreport, View Report
Gui, 99:Add, Button, x73 y130 h20 gdbopen vdbopent cgrey, Edit DB
Gui, 99:Add, Button, x252 y120 w90 h30 Default gsubmit vsubmit, Submit
Gui, 99:Add, Button, x160 y130 w90 h20 gcancel vcancel, Cancel/Close
Gui, 99:Add, Text, x5 y155 w100 r1 cgray gabout, `? About
Gui, 99:Add, Text, x290 y155 w100 r1 h15 cgray gsettings, < Settings >
Gui, 99:Add, StatusBar,, DB: %timetrackerdb%
Gui, 99:Show, w350 h195, DisTrackter
return
;-----------------
; AD Query to check for names.
checkname:
gui, submit, nohide
if offender =
{
MsgBox, You didn't enter any information! Try Again!
return
}
userdata =
loopnumber =
savefile = %a_mydocuments%\userdata.txt
FileDelete, %savefile%
;*******GetADObjectArray Function********;
GetADObjectArray(Query) {
objConnection := ComObjCreate("ADODB.Connection")
objConnection.Open("Provider=ADsDSOObject;")
objCommand := ComObjCreate("ADODB.Command")
objCommand.ActiveConnection := objConnection
objCommand.Properties("Page Size") := 100000
objCommand.CommandText := Query
objRecordSet := objCommand.Execute
;Create and populate a generic object with the data.
ADObjectArray := Object()
while objRecordSet.EOF = 0
{
ADObject := Object()
for f in objRecordSet.fields
{
ADObject[f.name] := f.value
}
ADObjectArray[a_index] := ADObject
try {
objRecordSet.MoveNext
}
catch e {
msgbox, No Dice.
break
}
}
objRecordSet.Close
objConnection.Close
query =
return ADObjectArray
}
;*******END - GetADObjectArray Function********;
;Build AD Query String
UserQuery = SELECT pwdlastset, title, description, mail, sAMAccountName, employeeID, displayName, name, cn, sn, homeDirectory, telephoneNumber FROM 'LDAP://dc=rgl,dc=net' where objectCategory='user' AND samaccountname='*%offender%*'
Data := GetADObjectArray(UserQuery)
;Loop through Each record row returned from ADQuery
for k,v in Data
{
thename := v["displayName"]
thefullname := v["name"]
themail := v["mail"]
thephone := v["telephoneNumber"]
thepdrive := v["homeDirectory"]
thepwdls := v["pwdlastset"]
thetitle := v["title"]
thedesc := v["description"]
thefirstname := v["cn"]
thelastname := v["sn"]
thesaman := v["sAMAccountName"]
;~ loopnumber := (a_index - 1)
loopnumber := a_index
;~ MsgBox, Loop`#%loopnumber%`nquery: %offender%`nName: %thename%
userdata = %userdata%RESULT %loopnumber%: %thesaman% | %thefullname% | %thetitle%`n
if thesaman =
{
MsgBox, The user doesn't appear to exist.
return
}
}
; Clear Variables
thename:=themail:=thephone:=thepdrive:=thepwdls:=thetitle:=thedesc:=thefirstname:=thelastname:=thesaman:=adstatus:=theregion:=theoffice:=""
if userdata !=
{
userdata = ***Please Choose a UserID below ***`n`n`n%userdata%
FileAppend, %userdata%, %savefile%
sleep, 200
run, %savefile%
sleep, 200
}
return
return
;-----------------
; Submits data to the DB using the field information
submit:
gui, submit, nohide
; Check for empty Fields
if timetrackerdb = %defaultdb%
{
MsgBox, Before you can save data you need to do one of the following:`n1) Change/Select an existing database, or... `n2) Create a new database TXT file.
return
}
if distruptiontype =
{
MsgBox, Choose an interruption type from the Drop Down`n(Such as Slack, IM, Walkup etc.)
return
}
if details =
{
MsgBox, You didn't enter any information! Try Again!
return
}
; If Offender/Login ID field is left empty, adds your own username to this field. Maybe you had to do some KB documentation or something.
if offender =
{
offender := A_UserName
}
StringReplace, offender, offender, `|,, all
StringReplace, offender, offender, %A_Space%,, all
StringReplace, details, details, `,, `;, all
FileAppend, %A_MM%/%A_DD%/%A_YYYY%`,%A_Hour%:%A_Min%`,%a_username%`,%distruptiontype%`,%offender%`,%timespent%`,%details%`n, %timetrackerdb%
;~ gosub, 99GuiClose
GuiControl,, offender,
GuiControl,, details,
GuiControl,, Submit, Data Entered!
sleep, 1000
GuiControl,, Submit, Submit
return
;-----------------
; Change Database file
changedb:
gui, submit, nohide
MsgBox, Locate the Database file you wish to Connect to.
FileSelectFile, dbfilepath, ,,Choose your Team's Database file, *.txt
if errorlevel
return
IniWrite, %dbfilepath%, %A_MyDocuments%\distracktersettings.ini, DBpath, Key
IniRead, timetrackerdb, %A_MyDocuments%\distracktersettings.ini, DBpath, Key
SB_SetText("DB: " timetrackerdb)
return
;-----------------
; Create new DB
newdb:
gui, submit, nohide
MsgBox, Create a new TXT file for your database in a location of your choosing.
FileSelectFile, dbfilepath, ,,Choose your Team's Database file, *.txt
if errorlevel
return
FileAppend, DATE`,TIME`,LOGGED_BY`,TYPE`,WHO`,TimeSpent`,DETAILS`n, %dbfilepath%
IniWrite, %dbfilepath%, %A_MyDocuments%\distracktersettings.ini, DBpath, Key
IniRead, timetrackerdb, %A_MyDocuments%\distracktersettings.ini, DBpath, Key
SB_SetText("DB: " timetrackerdb)
return
;-----------------
; INSTRUCTIONS Message Box
instructions:
MsgBox, ** FIRST TIME USE: Be sure to Connect Database to your team's Tracker Database.`nOptionally you can create a new database for your team or for private use.`n`n--Standard Use--`n1) Choose an interruption type.`n2) Enter user's Logon name.`n3) Enter a Description (include ticket if required)`n4) Choose a duration in munutes of the interruption (dropdown or enter custom).`n5) Click Submit!`n`n--Other Notes--`n- Your Login (as interruptee) is automatically saved to the Database and time-stamped with each entry.`n- If LoginID (interrupter) is left empty it defaults to yourself.`n- VIEW REPORT is read only. If you need to make a correction`, please use the Edit DB button.`n- You can use Check Username to confirm user's actual logon. This is to keep data entry consistent so that a user isn't being entered in multiple ways. (joe.smith, jsmith etc.)
return
;-----------------
; Runs a read only report on tracked data by reading the DB and putting it into a separate CSV file for viewing, pivoting, graphing in Excel
report:
IfWinExist, timetracker.csv
{
WinActivate, timetracker.csv
}
else,
{
FileDelete, %A_MyDocuments%\timetracker.csv
FileRead, timetrackerdata, %timetrackerdb%
FileAppend, %timetrackerdata%, %A_MyDocuments%\timetracker.csv
run, %A_MyDocuments%\timetracker.csv
}
return
;-----------------
; Opens the "Database" text file if corrections need to be made.
dbopen:
run, %timetrackerdb%
return
about:
MsgBox, Created by Alley Artwork`nUsing AutoHotkey v1.1.30.00
return
settings:
MsgBox, If you change any settings`nCLOSE AND RE-LAUNCH the application.`n`nValues are separated by Pipe:`nValue1|Value2|Value3
run, %A_MyDocuments%\distracktersettings.ini
return
;-----------------
; Close GUI by cancel button
Cancel:
Gui Destroy
ExitApp
return
;-----------------
; Close GUI by Windows "X" button
99GuiClose:
Gui Destroy
ExitApp
return
return
}
return
- I removed the radio button menu and replaced with a dropdown. This means you can have a much larger variety of things to track and not take up additional space.
- Added utilization of INI file to save settings.
- This way if others that don't use AHK but want to use the tracker, you can compile it and they can still customize the settings, or simply customize without editing the script directly.
- INI settings store Interruption type list, time increments, and database file location
- INI file can be launched directly from the GUI. (Requires relaunching the tracker after saving new settings to load them)
- Fixed a couple minor bugs such as save without entering an interruption type, not properly exiting app when clicking X etc.