Skip to content

Instantly share code, notes, and snippets.

@floscr
Last active February 11, 2021 14:49
Show Gist options
  • Save floscr/3268436e0eac6adf61d9ed3e0abf30fc to your computer and use it in GitHub Desktop.
Save floscr/3268436e0eac6adf61d9ed3e0abf30fc to your computer and use it in GitHub Desktop.
Personio Export Timetracking Sheet to CSV
  • Edit the first 3 variables with your personal information
  • Navigate to your wanted months attendance page
  • Paste the contents of the js file to your console
  • This script only works with english language settings in personio
(function() {
// Edit these values with your personal information
let EMPLOYEE_NAME = 'Max Mustermann';
let DEFAULT_DESCRIPTION = 'Description'
let FULL_DAY_WORKING_HOURS = '8';
/** HELPERS **/
let HOME_OFFICE = 'Home office';
let PAID_VACATION = 'Paid vacation';
let SICK_DAYS = 'Sick days';
let downloadFile = function(filename, text) {
var element = document.createElement('a');
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
element.setAttribute('download', filename);
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
let mmyyyy = function(x = new Date()) {
var y = x.getFullYear().toString();
var m = (x.getMonth() + 1).toString();
(m.length == 1) && (m = '0' + m);
return m + y
}
let isWorkColumn = function(x) {
const absenceColumn = x[1].innerText;
const isPaidAbsence = absenceColumn === SICK_DAYS || absenceColumn === HOME_OFFICE || absenceColumn === PAID_VACATION;
if (isPaidAbsence) return true;
const clockedStartColumn = x[2];
const hasClockedTime = clockedStartColumn?.querySelector('input')?.value
if (!!hasClockedTime) return true;
}
let csvHeaderColumn = 'Date,Start,End,Total,Employee,Description';
let makeFullDayLine = (date, comment) => `${date},,,${FULL_DAY_WORKING_HOURS},${EMPLOYEE_NAME},${comment}`;
let toCSVLine = function(x) {
const absenceColumn = x[1].innerText;
const dateColumn = x[0].innerText;
if (absenceColumn === SICK_DAYS) return makeFullDayLine(dateColumn, SICK_DAYS);
if (absenceColumn.startsWith(PAID_VACATION)) return makeFullDayLine(dateColumn, PAID_VACATION);
const clockedStartColumn = x[2].querySelector('input').value;
const clockedEndColumn = x[3].querySelector('input').value;
const commentColumn = x[5].innerText;
const description = commentColumn || DEFAULT_DESCRIPTION;
const totalColumn = x[6].innerText
return `${dateColumn},${clockedStartColumn},${clockedEndColumn},${totalColumn},${EMPLOYEE_NAME},${description}`;
}
/** MAIN **/
let [_columnHeader, ...rows] = [...document.querySelector('#attendance-table-container').querySelectorAll('.f-table')];
let cols = rows.map(x => [...x.querySelectorAll('.f-td')]);
let date = cols[0][0].innerText.match(/(Mon|Tue|Wed|Thu|Fri|Sat|Sun) (\d\d)\.(\d\d)/);
let dateObj = {
original: date[0],
weekday: date[1],
day: date[2],
month: date[3],
};
let year = document
.querySelector('.tab-content > .tab-pane > .row.gutter30.margin-bottom-10')
.querySelector("h5")
.innerText
.split(" ")[1];
let parsedDate = new Date(Date.parse(`${dateObj.month}.${dateObj.day}.${year}`))
let columns = cols
.filter(isWorkColumn)
.map(toCSVLine);
let text = csvHeaderColumn + "\n" + columns.join('\n');
let filename = `${mmyyyy(parsedDate)}-${EMPLOYEE_NAME.replace(' ', '_').toLowerCase()}.csv`;
console.log(text);
downloadFile(filename, text);
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment