Skip to content

Commit 746a5d6

Browse files
authored
Merge pull request #6 from zemien/feature/enrich-content
UI enhancements
2 parents 8303469 + 181face commit 746a5d6

File tree

6 files changed

+381
-156
lines changed

6 files changed

+381
-156
lines changed

docs/extract-skills-from-excel.ts

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
/**
2+
* Extracts the skills data from SFIA 9 Excel file and converts it
3+
* into a JSON format expected by NIWA's Position Description Generator tool.
4+
*
5+
* Run this in the Code Editor and copy the Console.log output into a
6+
* json_source.json file.
7+
*
8+
* Future SFIA versions may have different Excel formats. At minimum, check:
9+
* 1. Worksheet name is "Skills"
10+
* 2. Skills table with the important info is between columns I to V
11+
* 3. Column headers exactly match SkillsTableData interface definition,
12+
* including spaces and casing
13+
* 4. Skills are already grouped by Category and Subcategory.
14+
* If not, uncomment the optional grouping block.
15+
*/
16+
function main(workbook: ExcelScript.Workbook): void {
17+
let worksheet = workbook.getWorksheet("Skills");
18+
19+
if (worksheet.getTables().length === 0)
20+
{
21+
// Create an Excel table for easier looping later
22+
let newTable = workbook.addTable(worksheet.getRange("A1:V148"), true);
23+
24+
// Optional: Group table by Category and Subcategory if needed
25+
// newTable.getSort().apply([
26+
// { key: 11, ascending: true }, //column L
27+
// { key: 12, ascending: true }], //column M
28+
// false);
29+
}
30+
31+
const table = worksheet.getTables()[0];
32+
33+
// Get all the values from the table as text.
34+
const texts = table.getRange().getTexts();
35+
36+
// Create an array of JSON objects that match the row structure.
37+
let tableRows: SkillsTableData[] = [];
38+
if (table.getRowCount() > 0) {
39+
tableRows = returnObjectFromValues(texts);
40+
}
41+
42+
// Create the JSON object expected by NIWA's Position Description Generator tool
43+
let displayStructure = mapToDisplayStructure(tableRows);
44+
45+
// Log the information for copying into the json_source.json file
46+
console.log(JSON.stringify(displayStructure));
47+
return;
48+
}
49+
50+
// This function converts a 2D array of values into a SkillsTableData array.
51+
function returnObjectFromValues(values: string[][]): SkillsTableData[] {
52+
let objectArray: SkillsTableData[] = [];
53+
let objectKeys: string[] = [];
54+
for (let i = 0; i < values.length; i++) {
55+
if (i === 0) {
56+
objectKeys = values[i];
57+
continue;
58+
}
59+
60+
let object = {};
61+
for (let j = 0; j < values[i].length; j++) {
62+
object[objectKeys[j]] = values[i][j];
63+
}
64+
65+
objectArray.push(object as SkillsTableData);
66+
}
67+
68+
return objectArray;
69+
}
70+
71+
// This function converts SkillsTableData to the structure expected by NIWA
72+
function mapToDisplayStructure(table: SkillsTableData[]): object {
73+
let result = {};
74+
75+
let categoryWatermark = "";
76+
let subcategoryWatermark = "";
77+
78+
let category = {};
79+
let subcategory = {};
80+
81+
let maxIndex = table.length-1;
82+
83+
for (let i = 0; i < table.length; i++){
84+
let row = table[i];
85+
86+
//build the Levels
87+
let levels: Levels = {
88+
1: getLevelDescription(row["Level 1 description"]),
89+
2: getLevelDescription(row["Level 2 description"]),
90+
3: getLevelDescription(row["Level 3 description"]),
91+
4: getLevelDescription(row["Level 4 description"]),
92+
5: getLevelDescription(row["Level 5 description"]),
93+
6: getLevelDescription(row["Level 6 description"]),
94+
7: getLevelDescription(row["Level 7 description"])
95+
};
96+
97+
// build the Skill
98+
let skill: Skill = {
99+
code: row.Code,
100+
description: row["Overall description"],
101+
levels: levels,
102+
url: row.URL
103+
};
104+
105+
// update both watermarks
106+
categoryWatermark = row.Category;
107+
subcategoryWatermark = row.Subcategory;
108+
109+
// add to subcategory
110+
subcategory[row.Skill] = skill;
111+
112+
// peek ahead: if this is the last row or next subcategory is different,
113+
// then add this subcategory to the category and re-initialise
114+
if (i == maxIndex || table[i+1].Subcategory != subcategoryWatermark){
115+
//console.log(JSON.stringify(subcategory));
116+
category[subcategoryWatermark] = subcategory;
117+
subcategory = {};
118+
}
119+
120+
// peek ahead: if this is the last row or next category is different,
121+
// then add this category to the result and re-initialise
122+
if (i == maxIndex || table[i + 1].Category != categoryWatermark) {
123+
result[categoryWatermark] = category;
124+
category = {};
125+
}
126+
}
127+
128+
return result;
129+
}
130+
131+
// this function ensures that empty levels do not have a property defined
132+
function getLevelDescription(description: string): string | undefined {
133+
return description && description.trim() !== "" ? description : undefined;
134+
}
135+
136+
interface SkillsTableData {
137+
Code: string;
138+
URL: string;
139+
Skill: string;
140+
Category: string;
141+
Subcategory: string;
142+
"Overall description": string;
143+
"Guidance notes": string;
144+
"Level 1 description": string;
145+
"Level 2 description": string;
146+
"Level 3 description": string;
147+
"Level 4 description": string;
148+
"Level 5 description": string;
149+
"Level 6 description": string;
150+
"Level 7 description": string;
151+
}
152+
153+
interface Skill {
154+
code: string;
155+
levels: Levels;
156+
description: string;
157+
url: string;
158+
}
159+
160+
interface Levels {
161+
1?: string;
162+
2?: string;
163+
3?: string;
164+
4?: string;
165+
5?: string;
166+
6?: string;
167+
7?: string;
168+
}

docs/preparing-skills-data.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
Preparing skills data
2+
============
3+
4+
You require:
5+
6+
1. Access to a Microsoft Excel version and license that allows you to run Office Scripts built in TypeScript.
7+
2. [SFIA skills in Excel format](https://sfia-online.org/en/sfia-9/documentation/sfia-9_excel) (free registration and login required).
8+
9+
Steps:
10+
11+
1. Open the Excel file of SFIA skills.
12+
2. Go to Automate ribbon and click on New Script.
13+
3. Copy the contents of [extract-skills-from-excel.ts](extract-skills-from-excel.ts) into the Code Editor.
14+
4. Review the comments, especially the point about skills being grouped by Categories and Subcategories. For example, the SFIA 9 US Excel file is not grouped as the script expects,
15+
so the optional sorting code should be un-commented.
16+
5. Run the script in the Code Editor, so you can see the Console.log output. Copy the output into a new json_source.json file.

0 commit comments

Comments
 (0)