-
Notifications
You must be signed in to change notification settings - Fork 71
/
tlg_wrapper.ahk
344 lines (331 loc) · 12.9 KB
/
tlg_wrapper.ahk
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
; Link: https://raw.githubusercontent.com/rcalimlim/tlg/master/tlgmacro.ahk
; Author:
; Date:
; for: AHK_L
/*
*/
;//////////////////////////////////////////////////////////////////////////////
; SCRIPT SETTINGS
;//////////////////////////////////////////////////////////////////////////////
#SingleInstance force
#NoEnv ; Recommended for performance and compatibility with future
; AutoHotkey releases.
#Warn ; Enable warnings to assist with detecting common errors.
SendMode Input ; Recommended for new scripts due to its superior
; speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
;//////////////////////////////////////////////////////////////////////////////
; TLG ROSS v4
;//////////////////////////////////////////////////////////////////////////////
; This script translates shorthand TLG information entered by a user into
; properly formatted time logging strings. This script, in general, defaults
; to silent errors and returns nothing due to usability concerns when keying
; information in quick succession.
;
; Update: 2018 November 7
;//////////////////////////////////////////////////////////////////////////////
; DEFINE GLOBALS
;//////////////////////////////////////////////////////////////////////////////
; determine file path of excel tlg matrix based on current username
if (A_UserName == "rcalimli") {
path := "C:\AutoHotkey\matrix.xlsx"
}
else {
path := "D:\Documents\matrix.xlsx"
}
; make a safe array from passed excel matrix and sheet name
__all__maintable := make_table(path, "Main")
;//////////////////////////////////////////////////////////////////////////////
; DEFINE HOTKEYS
;//////////////////////////////////////////////////////////////////////////////
; Run and send
; Shift + Alt + J
+!j::
send % tlg_wrapper(__all__maintable, "_def", "0", "tr")
send {Enter}
return
; Run and alert
; Shift + Alt + K
+!k::
msgbox % tlg_wrapper(__all__maintable, "_def", "0", "tr")
return
; Reload
; Shift + Alt + S
+!s::
reload
return
;//////////////////////////////////////////////////////////////////////////////
; DEFINE FUNCTIONS
;//////////////////////////////////////////////////////////////////////////////
; Name: get_input
; Description: Prompts and returns a user's input.
; Parameters: none
; Called by: format_inputs
; Returns: string (if user enters information)
; -1 (otherwise)
get_input() {
msg := "org + tlp + bill, desc"
inputbox, str, TLG Ross, %msg%,, 150, 130 ; inputbox size 200x150
if (errorlevel != 0 || str == "") { ; return -1 if anything but user entry
return -1
}
else return str ; otherwise return the string input
}
;//////////////////////////////////////////////////////////////////////////////
; Name: str_to_arr
; Description: Converts string to array using passed delimeter. Also omits
; passed characters.
; Parameters: str: string to create array from
; delim: delimiter string (defaults to nothing so every char is
; parsed)
; omit: characters to exclude from strings (defaults to nothing)
; Called by: format_inputs
; Returns: arr: if string exists
; -1: if string is empty or an error (-1)
str_to_arr(str, delim:="", omit:="") {
if (!str || str == -1) {
return -1
}
else {
return arr := strsplit(str, delim, omit)
}
}
;//////////////////////////////////////////////////////////////////////////////
; Name: arr_to_str
; Description: Flattens array into human readable string. Good for testing,
; not actually called for tlg process.
; Parameters: arr: array to convert to string
; Called by: format_inputs
; Returns: string
arr_to_str(arr) {
string := "{"
for key, value in arr {
if(A_index != 1)
string .= ","
if key is number
string .= key ":"
else if(isobject(key))
string .= arr_to_str(key) ":"
else {
string .= key . ":"
}
if value is number
string .= value
else if (isobject(value))
string .= arr_to_str(value)
else
string .= value
}
return string . "}"
}
;//////////////////////////////////////////////////////////////////////////////
; Name: format_inputs
; Description: Calls get_input and returns two arrays. Array 1 contains TLG
; information before the comma, Array 2 contains the description
; override if any.
; Parameters: byref variables passed out by name when called
; Called by: tlg_wrapper
; Returns: tlgarr: array from string delimited by spaces,
; excluding commas
; descrip: array containing all information after a comma,
; if any
format_inputs(byref tlg_arr, byref des_str) {
user_inp := get_input(), has_comma := instr(user_inp, ",")
if (user_inp == -1 or user_inp == "") {
tlg_arr := des_str := -1
return ; quit out
}
else if (has_comma) {
tlg := substr(user_inp, 1, has_comma - 1)
, des_str := trim(substr(user_inp, has_comma + 1))
}
else {
tlg := substr(user_inp, 1, strlen(user_inp))
, des_str := ""
}
tlg_arr := str_to_arr(trim(tlg), " ", ",")
}
;//////////////////////////////////////////////////////////////////////////////
; Name: decode_num
; Description: Takes an integer and returns its alphabetic equivalent. Errors
; if parameter is a non-integer or outside of range 1-26.
; Parameters: int: integer to convert to alpha character
; Called by: decode_col
; Returns: single alphabetic character (good input)
; error message (bad input)
decode_num(int) {
alphabet := "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
if int is not integer
return "Non-integer input"
else if (int < 0 || !int || int > 27)
return "Integer out of bounds"
else return substr(alphabet, int, 1)
}
;//////////////////////////////////////////////////////////////////////////////
; Name: decode_col
; Description: I cannot for the life of me figure out how VBA works, so I had
; to write a function that converts the numeric column returned
; from a SpecialCell lookup into familiar alphabetic excel
; notation. This is a recursive function.
; Parameters: col: Excel numeric column ID
; divisor: modulo divisor (should always be 26 but whatever)
; Called by: decode_col (recursively)
; make_table
; Returns: alphabetic translation of col ID (good input)
; error message (bad input)
decode_col(col) {
errormsg := "Parameters must be positive integers"
if col is not integer
return % errormsg
else if (col <= 0)
return % errormsg
else if (col <= 26)
return % decode_num(col)
else {
remainder := mod(col, 26)
, col := floor(col/26)
return % decode_col(col) . decode_num(remainder)
}
}
;//////////////////////////////////////////////////////////////////////////////
; Name: make_table
; Description: Gets an excel workbook from passed file path and returns a safe
; array object.
; Parameters: sheet: sheet name, defaults to 1
; file_path: path to excel matrix
; Called by: __all__maintable (global)
; Returns: array object
make_table(file_path, sheet) {
oWorkbook := comobjget(file_path)
, lastrow := oWorkbook.Sheets(sheet).Range("A:A").SpecialCells(11).Row
, lastcol := oWorkbook.Sheets(sheet).Range("1:1").SpecialCells(11).Column
, rng := "A1:" . decode_col(lastcol) . lastrow
return oWorkbook.Sheets(sheet).Range(rng).Value
}
;//////////////////////////////////////////////////////////////////////////////
; Name: make_keys
; Description: Create a key array based on the passed format.
; Parameters: frmt: row - across
; col - down
; array: array from which to extract keys for key array
; Called by: format_tlg
; Returns: key_array: array object containing keys with values of their
; own original index
make_keys(array, frmt) {
key_array := {}
if (frmt == "row") {
loop % array.maxindex(2) {
key := array[1, a_index], val := array[3, a_index]
key_array.insert(key, {"index": a_index, "description": val})
}
return key_array
}
else if (frmt == "col") {
loop % array.maxindex(1) {
key := array[a_index, 2], val := array[a_index, 1]
key_array.insert(key, {"index": a_index, "description": val})
}
return key_array
}
else {
msgbox, "Format must be 'row' or 'col'"
return
}
}
;//////////////////////////////////////////////////////////////////////////////
; Name: format_tlg
; Description: This function translates the tlg and description arrays into
; usable TLG formats. Returns final TLG string to be sent to
; calendar.
; Parameters: safe_arr: safe array from excel table
; tlg_arr: formatted user input array
; des_arr: formatted user input string
; def_row: default row mnemonic
; def_col: default col mnemonic
; last_col: last default col
; Called by: format_tlg
; Returns: key_array: array object containing keys with values of their
; own original index.
format_tlg(safe_arr, tlg_arr, des_str, def_row, def_col, last_col) {
; define vars
proj_arr := make_keys(safe_arr, "col")
, head_arr := make_keys(safe_arr, "row")
, row_num := proj_arr[def_row]["index"]
, col_num := head_arr[def_col]["index"]
, def_true := 1 ; default by default
, tlg_desc := des_str, tlg_bill := "", tlg_bill_des := ""
, bill_arr := {"nb": {"index": 22, "description": "non-bill"}
, "ed": {"index": 7, "description": "education"}}
; initial iterative formatting--bulk of the final output
for key, value in tlg_arr {
if % head_arr.haskey(value) {
def_true := 0
col_num := head_arr[value]["index"]
if (!des_str)
tlg_desc .= head_arr[value]["description"] . " "
}
else if % proj_arr.haskey(value) {
row_num := proj_arr[value]["index"]
if (!des_str)
tlg_desc .= proj_arr[value]["description"] . " "
}
else if % bill_arr.haskey(value) {
tlg_bill := bill_arr[value]["index"]
if (!des_str)
tlg_desc .= bill_arr[value]["description"] . " "
}
else return
}
; final formatting and edge cases
def_row_num := proj_arr[def_row]["index"]
, def_col_num := head_arr[last_col]["index"]
, prj := safe_arr[row_num, head_arr["ID"]["index"]]
if (safe_arr[row_num, col_num]) {
; if TLP is exists, assign it
tlp := safe_arr[row_num, col_num]
if (!des_str && def_true) { ; assign def desc if no desc override
tlg_desc := strreplace(tlg_desc
, " "
, " "
. head_arr[def_col]["description"] . " "
,, 1)
}
}
else { ; assign def if tlp val doesn't exist
tlp := safe_arr[def_row_num, col_num]
if (!des_str && def_true) { ; assign def desc if no desc override
tlg_desc := strreplace(tlg_desc
, " "
, " "
. head_arr[def_col]["description"] . " "
,, 1)
}
}
return % tlp . "/" . prj . "////" . tlg_bill . "," . tlg_desc
}
;//////////////////////////////////////////////////////////////////////////////
; Name: tlg_wrapper
; Description: Wraps all the tlg functions together.
; Parameters: safe_arr: array from excel file
; def_row: default row mnemonic
; def_col: default column abbreviation
; last_col: last column abbreviation to be considered for
; default assignment functionality
; Called by: script
; Returns: final_tlg: formatted tlg string
tlg_wrapper(safe_arr, def_row, def_col, last_col) {
format_inputs(tlg_arr, des_str)
if (tlg_arr == -1)
return
else {
return final_tlg := format_tlg(safe_arr
, tlg_arr
, des_str
, def_row
, def_col
, last_col)
}
}
;//////////////////////////////////////////////////////////////////////////////
; Copyright © 2018 Ross F. Calimlim - LIC: GNU GPLv3
;//////////////////////////////////////////////////////////////////////////////