Data Analytics
PRICE ON REQUEST
Contact me to help with
data driven decisions
Prices depend on the data set size, your goals, budget, timeframe…..
AHK Data Analytics 2005-2024
Questions to AHK
YEAR IN BRIEF
Why do income and costs mirror one another
INCOME
Why do both, ‘Income from damages to property of the Authority’ and ‘Net income from maintenance of public lighting and sale of materials’ end in 2013?
What is ‘interest income: other’?
What is ‘finance income’ and did it end in 2022?
Why does ‘interest income from bank balances’ follow almost exactly the ‘finance income’?
What is included in ‘Sundry Income’?
What is ‘Electricity market income’?
why is desalination power accounted for separately from standard commercial electricity sales?
COSTS
Why do costs follow so closely with income?
Why does income from the sale of electricity almost match the total costs?
EMPLOYEES
Why the steady decline in numbers of employees?
Greenhouse Gas Emission Allowances Cost
Is this cost included in the calculation of electricity tariffs for customers?
Why is AHK reluctant to purchase more electricity from third party suppliers?
Why in the last five years at least, has AHK not done more to reduce this cost by reducing oil consumption and investing in more renewable energy?
KODAP/COSMOS
Why is it both income and cost or neither from 2011 to 2017?
Will KODAP cease after stopping oil powered electricity generation?
Cyprus Transmission System Operator
Why is it both income and cost?
Generation
Why the decrease in generation in 1994 to 1995?
AHK INVESTMENTS
Why is AHK investing in the financial markets in Equity securities and mutual funds and why €226 million?
Subsidiaries & Joint Ventures
What is the reason for continuing with the three dormant subsidiaries?
Are annual accounts available for AIK-IAK AHERA Ananeosimes?
Why did AHK transfer 50.1% of its ownership to the Holy Archbishopric of Cyprus?
Why the continued investment in the loss making Natural Gas Infrastructure Company, ETYFA deal?
Leases & Assets
Is AHK interested in doing a data analysis on the leases and assets to make data driven decisions?
Tseri Photovoltaic Park
Did AHK buy this land? Is it part of the ‘innovative solutions for land acquisition’ leases and partnerships?
Electricity Storage
Is there any update on the GROW-DERS “Grid reliability and operability with distributed generation using transportable storage” project?
What electricity storage options have been researched?
Is unbundling preventing storage investment?
Board of Directors
In conjunction with the AHK INVESTMENTS questions, why is a religious institution an active investment partner in national electricity generation?
Methodology & Data Sources
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut elit tellus, luctus nec ullamcorper mattis, pulvinar dapibus leo.
function batchExtractPdfsFromFolder() {
const folderId = "PASTE_YOUR_FOLDER_ID_HERE"; // Put your ID here
const folder = DriveApp.getFolderById(folderId);
const files = folder.getFilesByType(MimeType.PDF);
const ss = SpreadsheetApp.getActiveSpreadsheet();
while (files.hasNext()) {
const file = files.next();
Logger.log("Processing: " + file.getName());
// 1. Create a new sheet tab for this file
// We limit the name length to 30 chars (Sheets limit)
let sheetName = file.getName().substring(0, 30);
let sheet = ss.getSheetByName(sheetName) || ss.insertSheet(sheetName);
sheet.clear(); // Clear existing data if sheet exists
// 2. OCR Conversion (PDF to Temp Doc)
const resource = {
title: 'Temp_OCR_' + file.getName(),
mimeType: file.getMimeType()
};
// Uses the Advanced Drive Service (ensure it is enabled in 'Services')
const tempDocFile = Drive.Files.insert(resource, file.getBlob(), {ocr: true});
// 3. Extract text from the temporary Doc
const doc = DocumentApp.openById(tempDocFile.id);
const textContent = doc.getBody().getText();
// 4. Split text into rows and write to the sheet
const rows = textContent.split('\n').map(row => [row]);
if (rows.length > 0) {
sheet.getRange(1, 1, rows.length, 1).setValues(rows);
}
// 5. Cleanup
Drive.Files.remove(tempDocFile.id);
}
Logger.log("All files processed!");
}"
function batchExtractPdfsFromFolder() {
const folderId = "-------------------"; // Put your ID here
const folder = DriveApp.getFolderById(folderId);
const files = folder.getFilesByType(MimeType.PDF);
const ss = SpreadsheetApp.getActiveSpreadsheet();
while (files.hasNext()) {
const file = files.next();
Logger.log("Processing: " + file.getName());
// 1. Create a new sheet tab for this file
// We limit the name length to 30 chars (Sheets limit)
let sheetName = file.getName().substring(0, 30);
let sheet = ss.getSheetByName(sheetName) || ss.insertSheet(sheetName);
sheet.clear(); // Clear existing data if sheet exists
// 2. OCR Conversion (PDF to Temp Doc)
const resource = {
title: 'Temp_OCR_' + file.getName(),
mimeType: file.getMimeType()
};
// Uses the Advanced Drive Service (ensure it is enabled in 'Services')
const tempDocFile = Drive.Files.insert(resource, file.getBlob(), {ocr: true});
// 3. Extract text from the temporary Doc
const doc = DocumentApp.openById(tempDocFile.id);
const textContent = doc.getBody().getText();
// 4. Split text into rows and write to the sheet
const rows = textContent.split('\n').map(row => [row]);
if (rows.length > 0) {
sheet.getRange(1, 1, rows.length, 1).setValues(rows);
}
// 5. Cleanup
Drive.Files.remove(tempDocFile.id);
}
Logger.log("All files processed!");
}
___________________
function tidyAllAHKSheets() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheets = ss.getSheets();
sheets.forEach(sheet => {
const sheetName = sheet.getName();
// Only process the raw year tabs (4 digits)
if (sheetName.match(/^\d{4}$/)) {
const targetName = sheetName + "b";
let targetSheet = ss.getSheetByName(targetName);
if (!targetSheet) {
targetSheet = ss.insertSheet(targetName);
}
const range = sheet.getDataRange();
const data = range.getValues();
const cleanedData = data.map(row => {
return row.map(cell => {
// Convert everything to string for processing, then try to parse
let val = String(cell).trim();
if (val === "" || val === "-" || val === "null") return "";
let isNegative = false;
// Check for brackets: (1.000,00)
if (val.indexOf('(') === 0 && val.indexOf(')') === (val.length - 1)) {
isNegative = true;
val = val.replace(/[\(\)]/g, '');
}
// Check for standard minus sign
else if (val.indexOf('-') === 0) {
isNegative = true;
val = val.substring(1);
}
// Tidy the number: Remove Greek thousands (.) and replace decimal (,) with (.)
// We use a regex to remove all dots and then switch the comma.
let numericCandidate = val.replace(/\./g, '').replace(',', '.');
// Try to convert to a number
let num = parseFloat(numericCandidate);
// If it's a valid number and NOT just a year (like 2024), return formatted number
// We check if it's a number and if the original string contained a comma or dot
// to avoid accidentally turning "Page 1" into "1"
if (!isNaN(num) && /[\d,.]+/.test(val)) {
return isNegative ? -num : num;
}
return cell; // Return original if it's text
});
});
targetSheet.clear();
targetSheet.getRange(1, 1, cleanedData.length, cleanedData[0].length).setValues(cleanedData);
// Formatting the result
const lastCol = targetSheet.getLastColumn();
const lastRow = targetSheet.getLastRow();
if (lastCol > 1) {
targetSheet.getRange(1, 2, lastRow, lastCol - 1).setNumberFormat("#,##0.00");
}
}
});
}
- Tabula
- Google: Docs, Sheets & Slides
- Microsoft: Excel, PowerPoint
- Inkscape
- Audacity
- Svgator
Gantt chart challenges
Various methods of visually presenting 65 members of the board of directors of AHK over a period of 20 years was tried.
Modified bar graphs in sheets and excel were tight and restrictive.
Gantt charts were to high to fit on a slide.
This chart uses https://developers.google.com/chart
The data table is the directors name, start date, end date and a calculation of days between the two. The data is grouped by each director so that their tenure appears on one line. You can hover over each tenure period to see the months and days.
Graphics & Video challenges
I created some graphics using vectors in Inkscape and animated them using svgator. The resulting animation can be exported as high-resolution Lotties and animated svgs and lower resolution video formats.
Google Slides does not support lotties or animated vectors despite it being an web based presentation app.
Excel likewise does not support lotties or animated vectors so videos shown are mp4 video exports.
This graphic shows a small file size high resolution scalable animation.






