Last active
March 11, 2021 15:00
-
-
Save airglow923/a8fe6b99516ade715137e921b7f50e67 to your computer and use it in GitHub Desktop.
Parsing Excel file into JSON with JavaScript XLSX library
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import XLSX from 'xlsx'; | |
const readExcelFile = async (filename) => { | |
const workbook = XLSX.readFile(filename); | |
return workbook.SheetNames.reduce((acc, name) => { | |
acc[name] = XLSX.utils.sheet_to_json(workbook.Sheets[name]); | |
return acc; | |
}, {}); | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Syntax of mapping: | |
// | |
// { | |
// DIRECTION: { | |
// ... | |
// SHEET: { | |
// [name: NEW_SHEET], | |
// columns: { | |
// COLUMN: [NEW_COLUMN, [, CALLBACK]], | |
// ... | |
// } | |
// }, | |
// ... | |
// } | |
// } | |
// | |
// DIRECTION: 'input' | 'output' | |
// - Direction of parsing | |
// | |
// SHEET: string | |
// - Name of a sheet | |
// | |
// NEW_SHEET: string | |
// - New name of a sheet | |
// | |
// COLUMN: string | |
// - Name of a column | |
// | |
// NEW_COLUMN: string | |
// - New name of a column | |
// | |
// CALLBACK: (cell) => result | |
// - Callback to be performed on a cell value; it returns a processed result | |
const readExcelFileOptions = async (filename, direction, mapping) => { | |
const lookupCell = (value, header, table) => { | |
if (table === undefined) { | |
return { header, result: value }; | |
} | |
const lookupResult = table.columns[header]; | |
if (lookupResult === undefined) { | |
return { header: undefined, result: undefined }; | |
} | |
return { | |
header: lookupResult[0], | |
result: (lookupResult[1] && lookupResult[1](value)) || value, | |
}; | |
}; | |
// cellDates flag parses date as is when set to true | |
const workbook = XLSX.readFile(filename, { cellDates: true ); | |
const sheetNames = workbook.SheetNames; | |
const dirOptions = mapping[direction]; | |
if (dirOptions === undefined) { | |
throw new Error(`Invalid direction: ${direction}`); | |
} | |
return sheetNames.reduce((acc, name) => { | |
const worksheet = workbook.Sheets[name]; | |
const sheetNameLookup = dirOptions[name]; | |
const headers = {}; | |
const data = []; | |
// cell === alphabetical column + numerical row | |
// Ex. A1 | |
Object.keys(worksheet).forEach((cell) => { | |
if (cell[0] === "!") return; | |
const col = cell.substring(0, 1); | |
const row = parseInt(cell.substring(1), 10); | |
const value = worksheet[cell].v; | |
// store header names | |
if (row === 1 && value) { | |
headers[col] = value; | |
return; | |
} | |
if (!data[row]) data[row] = {}; | |
const { header, result } = lookupCell( | |
value, | |
headers[col], | |
sheetNameLookup | |
); | |
if (header !== undefined) data[row][header] = result; | |
}); | |
// drop those first two rows which are empty | |
data.shift(); | |
data.shift(); | |
const sheetName = (sheetNameLookup && sheetNameLookup.name) || name; | |
acc[sheetName] = data; | |
return acc; | |
}, {}); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Usage: