mr-excel
Version:
A versatile JavaScript library for effortlessly generating .xlsx files from input objects. Seamlessly create Excel spreadsheets with data, formatting, formulas, and more.
238 lines (234 loc) • 7.81 kB
text/typescript
import { type ReadResult } from "../data-model/excel-table";
export const defaultConfig = {
firstHeader: true,
returnTableNodes: false,
emptyNodeDefaultString: " ",
removeContainerChildNode: true,
containerNodeStyle: {
display: "flex",
flexDirection: "column",
},
tableStyle: {
borderSpacing: "0",
border: "1px solid #EEEEEEF1",
},
cellStyle: {
width: "68px",
height: "24px",
border: "1px solid #EEEEEEF1",
},
buttonContainerStyle: {
display: "flex",
},
buttonStyle: {
height: "40px",
width: "80px",
display: "flex",
justifyContent: "center",
alignItems: "center",
border: "0",
background: "transparent",
cursor: "pointer",
},
activeButtonStyle: {
background: "#EEEDEB",
},
};
export async function excelToNode(
uri: string,
queryForTable?: string | null,
containerElement?: HTMLDivElement | null,
fetchFunc?: Function,
firstHeader: boolean = true,
returnTableNodes: boolean = false,
emptyNodeDefaultString: string = " ",
removeContainerChildNode = true,
containerNodeStyle: object = {
display: "flex",
flexDirection: "column",
},
tableStyle: object = {
borderSpacing: "0",
border: "1px solid #EEEEEEF1",
},
cellStyle: object = {
width: "68px",
height: "24px",
border: "1px solid #EEEEEEF1",
},
buttonContainerStyle: object = {
display: "flex",
},
buttonStyle: object = {
height: "40px",
width: "80px",
display: "flex",
justifyContent: "center",
alignItems: "center",
border: "0",
background: "transparent",
cursor: "pointer",
},
activeButtonStyle: object = {
background: "#EEEDEB",
}
) {
let excelData: ReadResult = await import("../utils/read-utils").then(
async (m) => await m.extractExcelData(uri, false, fetchFunc)
);
let containerNode: HTMLElement | null = null;
if (queryForTable) {
containerNode = document.querySelector(queryForTable)!;
} else if (containerElement) {
containerNode = containerElement;
}
if (containerNode == null && !returnTableNodes) {
throw "Container Node not found";
}
const containerNodeStyleKeys = Object.keys(containerNodeStyle);
const tableStyleKeys = Object.keys(tableStyle);
const cellStyleKeys = Object.keys(cellStyle);
const buttonContainerStyleKeys = Object.keys(buttonContainerStyle);
const buttonStyleKeys = Object.keys(buttonStyle);
const activeButtonStyleKeys = Object.keys(activeButtonStyle);
let tabButtonContainer = document.createElement("div");
buttonContainerStyleKeys.forEach((keyStyle: string) => {
tabButtonContainer.style[keyStyle as keyof object] =
buttonContainerStyle[keyStyle as keyof object];
});
if (!returnTableNodes) {
if (removeContainerChildNode && containerNode != null) {
containerNode.innerText = "";
}
containerNodeStyleKeys.forEach((keyStyle: string) => {
containerNode!.style[keyStyle as keyof object] =
containerNodeStyle[keyStyle as keyof object];
});
containerNode!.appendChild(tabButtonContainer);
}
let resultTables: HTMLTableElement[] = [];
let isDone = false;
let displayTab = "unset";
let sheetCounter = 0;
do {
sheetCounter++;
const element = excelData.sheetName.next();
if (!element.value) {
break;
}
const tabContentContainer = document.createElement("div");
tabContentContainer.style.display = "none";
if (!returnTableNodes) {
const button = document.createElement("button");
buttonStyleKeys.forEach((keyStyle: string) => {
button.style[keyStyle as keyof object] =
buttonStyle[keyStyle as keyof object];
});
button.addEventListener("click", (ev: MouseEvent) => {
const sheetId = button.getAttribute("data-sheet");
const element: HTMLDivElement | null = containerNode!.querySelector(
'div[data-sheet="' + sheetId + '"]'
);
if (element) {
activeButtonStyleKeys.forEach((styleKey: string) => {
button.style[styleKey as keyof object] =
activeButtonStyle[styleKey as keyof object];
});
const perviousBtn: HTMLElement | null = containerNode!.querySelector(
"[data-sheet-button-activate]"
);
let perviousElement: HTMLElement | null =
containerNode!.querySelector("[data-sheet-activate]");
element.setAttribute("data-sheet-activate", "1");
element.style.display = "flex";
button.setAttribute("data-sheet-button-activate", "1");
if (perviousBtn) {
buttonStyleKeys.forEach((styleKey: string) => {
perviousBtn.style[styleKey as keyof object] =
buttonStyle[styleKey as keyof object];
});
perviousBtn.removeAttribute("data-sheet-button-activate");
}
if (perviousElement) {
perviousElement.style.display = "none";
perviousElement.removeAttribute("data-sheet-activate");
}
} else {
console.error("Sheet content not found!!" + " id is " + sheetId);
}
});
button.setAttribute("data-sheet", sheetCounter + "");
tabContentContainer.setAttribute("data-sheet", sheetCounter + "");
button.innerText = element.value[1] || element.value[0];
tabButtonContainer.appendChild(button);
containerNode!.appendChild(tabContentContainer);
}
let nodeType = firstHeader ? "th" : "td";
const tableNode = document.createElement("table");
tableStyleKeys.forEach((keyStyle: string) => {
tableNode.style[keyStyle as keyof object] =
tableStyle[keyStyle as keyof object];
});
const sheetData: (string | null | undefined)[][] =
excelData.data[element.value[0]] || excelData.data[element.value[1]];
const colLength =
excelData.maxLengthOfColumn[element.value[0]] ||
excelData.maxLengthOfColumn[element.value[1]];
if (Array.isArray(sheetData)) {
const len = sheetData.length;
for (let index = 0; index < len; index++) {
const v = sheetData[index];
const tr = document.createElement("tr");
const isArray = Array.isArray(v);
for (let index = 0; index <= colLength; index++) {
let text = emptyNodeDefaultString;
if (isArray) {
const el = v[index];
if (typeof el === "string") {
text = el;
}
}
const docNode = document.createElement(nodeType);
cellStyleKeys.forEach((keyStyle: string) => {
docNode.style[keyStyle as keyof object] =
cellStyle[keyStyle as keyof object];
});
docNode.innerText = text;
tr.appendChild(docNode);
}
tableNode.appendChild(tr);
nodeType = "td";
}
}
if (returnTableNodes) {
resultTables.push(tableNode);
} else {
tabContentContainer.appendChild(tableNode);
containerNode?.appendChild(tabContentContainer);
}
isDone = element.done!;
displayTab = "hidden";
} while (!isDone);
if (returnTableNodes) {
return resultTables;
} else {
const one: HTMLElement | null = containerNode!.querySelector(
'div[data-sheet="1"]'
);
if (one) {
one.style.display = "flex";
one.setAttribute("data-sheet-activate", "1");
}
const oneButton: HTMLElement | null = containerNode!.querySelector(
'button[data-sheet="1"]'
);
if (oneButton) {
activeButtonStyleKeys.forEach((styleKey: string) => {
oneButton.style[styleKey as keyof object] =
activeButtonStyle[styleKey as keyof object];
});
oneButton.setAttribute("data-sheet-button-activate", "1");
}
return "Done";
}
}