Explains the structure and layout of PTO Excel spreadsheets used in the DWP Hours Tracker data migration process.
Explains the structure and layout of PTO Excel spreadsheets used in the DWP Hours Tracker data migration process, including calendar areas, legend sections, PTO calculation data, and color coding schemes.
Activate when users ask about Excel spreadsheet structure, PTO data layout, calendar organization, legend interpretation, or how to navigate the legacy Excel files for data migration.
This skill integrates with the data-migration task and provides foundational knowledge for the ExcelJS-based migration implementation. It helps developers understand the source data structure before implementing extraction logic.
Given a 1-based month number M (1=Jan, 12=Dec) and a day-of-month D, compute the Excel cell:
colGroup = floor((M - 1) / 4) // 0, 1, or 2
rowGroup = (M - 1) % 4 // 0, 1, 2, or 3
headerRow = 4 + rowGroup * 9 // 4, 13, 22, or 31
startCol = 2 + colGroup * 8 // 2 (B), 10 (J), or 18 (R)
dataRow = headerRow + 2 // first row of day numbers
firstDow = dayOfWeek(year, M, 1) // 0=Sun, 6=Sat
week = floor((D - 1 + firstDow) / 7)
dow = (D - 1 + firstDow) % 7 // 0=Sun..6=Sat
row = dataRow + week
col = startCol + dow
Quick reference table (headerRow / startCol):
| Month | M | colGroup | rowGroup | headerRow | startCol | Cols |
|---|---|---|---|---|---|---|
| January | 1 | 0 | 0 | 4 | 2 (B) | B–H |
| February | 2 | 0 | 1 | 13 | 2 (B) | B–H |
| March | 3 | 0 | 2 | 22 | 2 (B) | B–H |
| April | 4 | 0 | 3 | 31 | 2 (B) | B–H |
| May | 5 | 1 | 0 | 4 | 10 (J) | J–P |
| June | 6 | 1 | 1 | 13 | 10 (J) | J–P |
| July | 7 | 1 | 2 | 22 | 10 (J) | J–P |
| August | 8 | 1 | 3 | 31 | 10 (J) | J–P |
| September | 9 | 2 | 0 | 4 | 18 (R) | R–X |
| October | 10 | 2 | 1 | 13 | 18 (R) | R–X |
| November | 11 | 2 | 2 | 22 | 18 (R) | R–X |
| December | 12 | 2 | 3 | 31 | 18 (R) | R–X |
Verified example — December 19, 2018 (Wednesday):
colGroup=2, rowGroup=3, headerRow=31, startCol=18 (R)firstDow=6week = floor((19-1+6)/7) = 3, dow = (18+6)%7 = 3 (Wed)Day-of-week column order within each 7-column block:
| Offset | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
|---|---|---|---|---|---|---|---|
| Day | Sun | Mon | Tue | Wed | Thu | Fri | Sat |
parseCarryoverHours() in shared/excelParsing.ts to set employee.carryover_hours during import. For subsequent months (rows 43–53), columns L-M contain the running balance carried forward from the previous month within the same year.J42+(IF(L42="", 0, L42)) for the January row.cell.fill.fgColor.argb or cell.fill.fgColor.rgb properties{texts: [{font: {bold: true, ...}, text: "Author Name:"}, {font: {...}, text: "\nNote content"}]}FFFFC000 fill) often have notes specifying actual hours taken when less than a full 8-hour dayreports/2018.xlsx:
"Mandi Davenport:\n2 HRS PTO" — 2 hours PTO"Mandi Davenport:\n5 HRS PTO" — 5 hours PTO"Mandi Davenport:\n5 HRS PTO" — 5 hours PTO/^(\d+(?:\.\d+)?)\s*(?:hrs?|hours?)\s+(?:pto|sick|bereavement)/icell.note property; for rich text notes, concatenate cell.note.texts[].text to get the full display stringTASKS/legacy-data-import.md Known Issues.reports/2018.xlsx, the "Deanna Allen" sheet has an extra blank row in the July area (colGroup=1, rowGroup=2). The date array formula starts at J25 instead of the expected J24. All other months on the same sheet (and all months on other sheets like "A Bylenga") use the standard headerRow + 2 offset.(headerRow + 2, startCol + firstDow) contains the numeric value 1 (day 1 of the month). If not, scan ±3 rows at the same column. If day 1 is found at an offset, log a recovery warning and use the corrected start row. If day 1 cannot be located, skip the month with an error warning.</content>
<parameter name="filePath">/home/ca0v/code/ca0v/dwp-hours/.github/skills/pto-spreadsheet-layout/SKILL.md