diff --git a/src/Views/spreadsheetData.json b/spreadsheetData.json similarity index 100% rename from src/Views/spreadsheetData.json rename to spreadsheetData.json diff --git a/src/Settings.ts b/src/Settings.ts index 244f392..f2453d6 100644 --- a/src/Settings.ts +++ b/src/Settings.ts @@ -1,11 +1,11 @@ export interface SheetjsSettings { addRibbonIcon: boolean; - + enableSaveToFile: boolean } export const DEFAULT_SETTINGS: SheetjsSettings = { - addRibbonIcon: true, - + addRibbonIcon: false, + enableSaveToFile: true } diff --git a/src/Views/SheetView.ts b/src/Views/SheetView.ts index cd0894e..eedee5e 100644 --- a/src/Views/SheetView.ts +++ b/src/Views/SheetView.ts @@ -5,41 +5,21 @@ import { MarkdownPostProcessorContext, MarkdownView, - debounce, parseYaml, stringifyYaml, Notice, } from "obsidian"; import { SheetjsSettings } from "src/Settings"; -import Spreadsheet from "x-data-spreadsheet"; // import "x-data-spreadsheet/dist/xspreadsheet.css"; // import * as fs from "fs/promises" // import * as path from "path" import * as XLSX from "xlsx"; import * as ExcelJS from "exceljs"; -import { stox, xtos } from "../utils/xlsxpread"; +import { stox } from "../utils/xlsxpread"; import { toSpreadsheet } from "src/utils/excelConverter"; +import { createSpreadSheet, saveToFile } from "./spreadSheetWrapper"; -const saveIcon = - "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/PjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+PHN2ZyB0PSIxNTc3MTc3MDkyOTg4IiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjI2NzgiIHdpZHRoPSIxOCIgaGVpZ2h0PSIxOCIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPjxkZWZzPjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+PC9zdHlsZT48L2RlZnM+PHBhdGggZD0iTTIxMy4zMzMzMzMgMTI4aDU5Ny4zMzMzMzRhODUuMzMzMzMzIDg1LjMzMzMzMyAwIDAgMSA4NS4zMzMzMzMgODUuMzMzMzMzdjU5Ny4zMzMzMzRhODUuMzMzMzMzIDg1LjMzMzMzMyAwIDAgMS04NS4zMzMzMzMgODUuMzMzMzMzSDIxMy4zMzMzMzNhODUuMzMzMzMzIDg1LjMzMzMzMyAwIDAgMS04NS4zMzMzMzMtODUuMzMzMzMzVjIxMy4zMzMzMzNhODUuMzMzMzMzIDg1LjMzMzMzMyAwIDAgMSA4NS4zMzMzMzMtODUuMzMzMzMzeiBtMzY2LjkzMzMzNCAxMjhoMzQuMTMzMzMzYTI1LjYgMjUuNiAwIDAgMSAyNS42IDI1LjZ2MTE5LjQ2NjY2N2EyNS42IDI1LjYgMCAwIDEtMjUuNiAyNS42aC0zNC4xMzMzMzNhMjUuNiAyNS42IDAgMCAxLTI1LjYtMjUuNlYyODEuNmEyNS42IDI1LjYgMCAwIDEgMjUuNi0yNS42ek0yMTMuMzMzMzMzIDIxMy4zMzMzMzN2NTk3LjMzMzMzNGg1OTcuMzMzMzM0VjIxMy4zMzMzMzNIMjEzLjMzMzMzM3ogbTEyOCAwdjI1NmgzNDEuMzMzMzM0VjIxMy4zMzMzMzNoODUuMzMzMzMzdjI5OC42NjY2NjdhNDIuNjY2NjY3IDQyLjY2NjY2NyAwIDAgMS00Mi42NjY2NjcgNDIuNjY2NjY3SDI5OC42NjY2NjdhNDIuNjY2NjY3IDQyLjY2NjY2NyAwIDAgMS00Mi42NjY2NjctNDIuNjY2NjY3VjIxMy4zMzMzMzNoODUuMzMzMzMzek0yNTYgMjEzLjMzMzMzM2g4NS4zMzMzMzMtODUuMzMzMzMzeiBtNDI2LjY2NjY2NyAwaDg1LjMzMzMzMy04NS4zMzMzMzN6IG0wIDU5Ny4zMzMzMzR2LTEyOEgzNDEuMzMzMzMzdjEyOEgyNTZ2LTE3MC42NjY2NjdhNDIuNjY2NjY3IDQyLjY2NjY2NyAwIDAgMSA0Mi42NjY2NjctNDIuNjY2NjY3aDQyNi42NjY2NjZhNDIuNjY2NjY3IDQyLjY2NjY2NyAwIDAgMSA0Mi42NjY2NjcgNDIuNjY2NjY3djE3MC42NjY2NjdoLTg1LjMzMzMzM3ogbTg1LjMzMzMzMyAwaC04NS4zMzMzMzMgODUuMzMzMzMzek0zNDEuMzMzMzMzIDgxMC42NjY2NjdIMjU2aDg1LjMzMzMzM3oiIHAtaWQ9IjI2NzkiIGZpbGw9IiMyYzJjMmMiPjwvcGF0aD48L3N2Zz4="; - -function resolve_book_type(fileName: string): XLSX.BookType { - const _BT: any = { - xls: "biff8", - htm: "html", - slk: "sylk", - socialcalc: "eth", - Sh33tJS: "WTF", - }; - let bookType = "xlsx"; - const ext = fileName.slice(fileName.lastIndexOf(".")).toLowerCase(); - if (ext.match(/^\.[a-z]+$/)) { - bookType = ext.slice(1); - } - bookType = _BT[bookType] || bookType; - return bookType as XLSX.BookType; -} const DEFAULT_OPTIONS = { height: 540, @@ -51,10 +31,9 @@ const DEFAULT_OPTIONS = { cellWidth: 100, }; -interface SheetOptions { - filename?: string; - data?: any; -} +const saveIcon = + "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/PjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+PHN2ZyB0PSIxNTc3MTc3MDkyOTg4IiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjI2NzgiIHdpZHRoPSIxOCIgaGVpZ2h0PSIxOCIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPjxkZWZzPjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+PC9zdHlsZT48L2RlZnM+PHBhdGggZD0iTTIxMy4zMzMzMzMgMTI4aDU5Ny4zMzMzMzRhODUuMzMzMzMzIDg1LjMzMzMzMyAwIDAgMSA4NS4zMzMzMzMgODUuMzMzMzMzdjU5Ny4zMzMzMzRhODUuMzMzMzMzIDg1LjMzMzMzMyAwIDAgMS04NS4zMzMzMzMgODUuMzMzMzMzSDIxMy4zMzMzMzNhODUuMzMzMzMzIDg1LjMzMzMzMyAwIDAgMS04NS4zMzMzMzMtODUuMzMzMzMzVjIxMy4zMzMzMzNhODUuMzMzMzMzIDg1LjMzMzMzMyAwIDAgMSA4NS4zMzMzMzMtODUuMzMzMzMzeiBtMzY2LjkzMzMzNCAxMjhoMzQuMTMzMzMzYTI1LjYgMjUuNiAwIDAgMSAyNS42IDI1LjZ2MTE5LjQ2NjY2N2EyNS42IDI1LjYgMCAwIDEtMjUuNiAyNS42aC0zNC4xMzMzMzNhMjUuNiAyNS42IDAgMCAxLTI1LjYtMjUuNlYyODEuNmEyNS42IDI1LjYgMCAwIDEgMjUuNi0yNS42ek0yMTMuMzMzMzMzIDIxMy4zMzMzMzN2NTk3LjMzMzMzNGg1OTcuMzMzMzM0VjIxMy4zMzMzMzNIMjEzLjMzMzMzM3ogbTEyOCAwdjI1NmgzNDEuMzMzMzM0VjIxMy4zMzMzMzNoODUuMzMzMzMzdjI5OC42NjY2NjdhNDIuNjY2NjY3IDQyLjY2NjY2NyAwIDAgMS00Mi42NjY2NjcgNDIuNjY2NjY3SDI5OC42NjY2NjdhNDIuNjY2NjY3IDQyLjY2NjY2NyAwIDAgMS00Mi42NjY2NjctNDIuNjY2NjY3VjIxMy4zMzMzMzNoODUuMzMzMzMzek0yNTYgMjEzLjMzMzMzM2g4NS4zMzMzMzMtODUuMzMzMzMzeiBtNDI2LjY2NjY2NyAwaDg1LjMzMzMzMy04NS4zMzMzMzN6IG0wIDU5Ny4zMzMzMzR2LTEyOEgzNDEuMzMzMzMzdjEyOEgyNTZ2LTE3MC42NjY2NjdhNDIuNjY2NjY3IDQyLjY2NjY2NyAwIDAgMSA0Mi42NjY2NjctNDIuNjY2NjY3aDQyNi42NjY2NjZhNDIuNjY2NjY3IDQyLjY2NjY2NyAwIDAgMSA0Mi42NjY2NjcgNDIuNjY2NjY3djE3MC42NjY2NjdoLTg1LjMzMzMzM3ogbTg1LjMzMzMzMyAwaC04NS4zMzMzMzMgODUuMzMzMzMzek0zNDEuMzMzMzMzIDgxMC42NjY2NjdIMjU2aDg1LjMzMzMzM3oiIHAtaWQ9IjI2NzkiIGZpbGw9IiMyYzJjMmMiPjwvcGF0aD48L3N2Zz4="; + export function processCodeBlock( source: string, @@ -78,7 +57,7 @@ export function processCodeBlock( if ((ctx as any).spreadsheet) return; const options = { ...DEFAULT_OPTIONS, ...parseYaml(source) }; - + const { filename, height, @@ -143,39 +122,40 @@ export function processCodeBlock( // } }; - if (!filename) { + if (!filename || settings.enableSaveToFile) { spreadsheet_options.extendToolbar = { left: [ { tip: "Save", icon: saveIcon, shortcut: "Ctrl+S", - onClick: (s: any, d: any) => saveDataIntoBlock(s, d, ctx), + onClick: (s: any, d: any) => { + if(!filename) saveDataIntoBlock(s, d, ctx); + else { + saveToFile((ctx as any).spreadsheet, filename) + } + }, }, ], }; } - if (filename) { + if (filename !== undefined) { (async () => { - const fileContent = await app.vault.adapter.readBinary(filename); - - const xlsx = XLSX.read(fileContent, { - cellStyles: true, - sheetStubs: true, // > - }); - const workbook = new ExcelJS.Workbook(); - - const excelWorkbook = await workbook.xlsx.load(fileContent); - - const data2 = toSpreadsheet(excelWorkbook); - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const data = stox(xlsx); + let data = undefined + try { + const fileContent = await app.vault.adapter.readBinary(filename); + + data = await parseFileContent(filename, fileContent); + } catch (e) { + console.warn(e) + } + + (ctx as any).spreadsheet = createSpreadSheet( container, spreadsheet_options, - { ...options, data: data2 }, + { ...options, data: data }, ctx ); // .loadData(); @@ -199,6 +179,26 @@ export function processCodeBlock( // https://github.com/wolf-table/table } +async function parseFileContent(filename:string, fileContent:ArrayBuffer){ + + const ext = filename.slice(filename.lastIndexOf(".")).toLowerCase(); + if(ext === ".xlsx" || ext === ".csv") { + const workbook = new ExcelJS.Workbook(); + const excelWorkbook = await workbook.xlsx.load(fileContent); + const data2 = toSpreadsheet(excelWorkbook); + return data2; + } else { + const xlsx = XLSX.read(fileContent, { + cellStyles: true, + sheetStubs: true, // > + }); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const data = stox(xlsx); + return data; + } + +} + function saveDataIntoBlock( data: any, sheet: any, @@ -224,85 +224,8 @@ function saveDataIntoBlock( } } else { // preview - new Notice("Sheet not saved while in read mode"); + new Notice("Sheet not saved while in reading mode"); } } -function createSpreadSheet( - container: HTMLElement, - spreadsheet_options: any, - options: SheetOptions, - ctx: MarkdownPostProcessorContext -) { - const spreadSheet = new Spreadsheet( - container, - spreadsheet_options - ).loadData(options.data || {}); - spreadSheet.change( - debounce((data) => { - // save data - // console.log(data) - if (options.filename) { - const spreadsheetData = spreadSheet.getData() as any[]; - const wb = xtos(spreadsheetData) as XLSX.WorkBook; - applyStyles(spreadsheetData, wb); - const bookType = resolve_book_type(options.filename); - const bytes = XLSX.write(wb, { - bookType: bookType, - type: "buffer", - compression: true, - bookSST: true, - cellStyles: true, - }); - // fs.writeFile(filename,bytes); - app.vault.adapter.writeBinary(options.filename, bytes); - console.log(`data saved tp ${options.filename}`); - } else { - // tentative - // saveDataIntoBlock(null,null,ctx) - } - // XLSX.writeFile(xtos(s.getData(data)) as any, filename); - }, 1000) - ); - - return spreadSheet; -} - -function applyStyles(ssdata: any, wb: XLSX.WorkBook) { - console.log(ssdata, wb); - for (const sheet of ssdata) { - const { name, styles, rows } = sheet; - for (const rowId in rows) { - const cells = rows[rowId]["cells"]; - for (const cellId in cells) { - const cell = cells[cellId]; - if (cell.style !== undefined) { - const wbStyle = styleSS2WB(styles[cell.style]); - //TODO: apply to the right WB cell - const cellRef = XLSX.utils.encode_cell({ - r: Number(rowId), - c: Number(cellId), - }); - wb.Sheets[name][cellRef].s = wbStyle; - } - } - } - } -} - -function styleSS2WB(ssstyle: any) { - const style: any = { patternType: "solid" }; - if (ssstyle.bgcolor) { - style.bgColor = { - rgb: ssstyle.bgcolor.substring(1), - }; - } - - if (ssstyle.color) { - style.fgColor = { - rgb: ssstyle.color.substring(1), - }; - } - return style; -} diff --git a/src/Views/spreadSheetWrapper.ts b/src/Views/spreadSheetWrapper.ts new file mode 100644 index 0000000..fa66d9f --- /dev/null +++ b/src/Views/spreadSheetWrapper.ts @@ -0,0 +1,131 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { MarkdownPostProcessorContext, debounce } from "obsidian"; +import Spreadsheet from "x-data-spreadsheet"; +import * as XLSX from "xlsx"; +import { xtos } from "../utils/xlsxpread"; +import { toExcelJS } from "src/utils/excelConverter"; + + +function resolve_book_type(fileName: string): XLSX.BookType { + const _BT: any = { + xls: "biff8", + htm: "html", + slk: "sylk", + socialcalc: "eth", + Sh33tJS: "WTF", + }; + let bookType = "xlsx"; + const ext = fileName.slice(fileName.lastIndexOf(".")).toLowerCase(); + if (ext.match(/^\.[a-z]+$/)) { + bookType = ext.slice(1); + } + bookType = _BT[bookType] || bookType; + return bookType as XLSX.BookType; +} + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +function applyStyles(ssdata: any, wb: XLSX.WorkBook) { + console.log(ssdata, wb); + for (const sheet of ssdata) { + const { name, styles, rows } = sheet; + for (const rowId in rows) { + const cells = rows[rowId]["cells"]; + for (const cellId in cells) { + const cell = cells[cellId]; + if (cell.style !== undefined) { + const wbStyle = styleSS2WB(styles[cell.style]); + //TODO: apply to the right WB cell + const cellRef = XLSX.utils.encode_cell({ + r: Number(rowId), + c: Number(cellId), + }); + wb.Sheets[name][cellRef].s = wbStyle; + } + } + } + } +} + + + + +export interface SheetOptions { + filename?: string; + data?: any; +} + +export function createSpreadSheet( + container: HTMLElement, + spreadsheet_options: any, + options: SheetOptions, + ctx: MarkdownPostProcessorContext +) { + const spreadSheet = new Spreadsheet( + container, + spreadsheet_options + ).loadData(options.data || {}); + spreadSheet.change( + debounce((_data) => { + // save data + // console.log(data) + if (options.filename) { + saveToFile(spreadSheet, options.filename); + } else { + // at the moment we avoid since this would cause re-rendering + // saveDataIntoBlock(null,null,ctx) + } + + // XLSX.writeFile(xtos(s.getData(data)) as any, filename); + }, 1000) + ); + + return spreadSheet; +} + +export async function saveToFile(spreadSheet: Spreadsheet, filename: string) { + + const spreadsheetData = spreadSheet.getData() as any[]; + const bookType = resolve_book_type(filename); + if(bookType === 'xlsx' || bookType === 'csv'){ + const workbook = toExcelJS(spreadsheetData); + const buffer = await workbook.xlsx.writeBuffer(); + app.vault.adapter.writeBinary(filename, buffer); + console.log(`data saved tp ${filename}`); + } else { + const wb = xtos(spreadsheetData) as XLSX.WorkBook; + // applyStyles(spreadsheetData, wb); + const bytes = XLSX.write(wb, { + bookType: bookType, + type: "buffer", + compression: true, + bookSST: true, + cellStyles: true, + }); + app.vault.adapter.writeBinary(filename, bytes); + console.log(`data saved tp ${filename}`); + } + + + + + + + // fs.writeFile(filename,bytes); + +} + +function styleSS2WB(ssstyle: any) { + const style: any = { patternType: "solid" }; + if (ssstyle.bgcolor) { + style.bgColor = { + rgb: ssstyle.bgcolor.substring(1), + }; + } + + if (ssstyle.color) { + style.fgColor = { + rgb: ssstyle.color.substring(1), + }; + } + return style; +} diff --git a/src/utils/excelConverter.ts b/src/utils/excelConverter.ts index c975cfe..f7ad3f0 100644 --- a/src/utils/excelConverter.ts +++ b/src/utils/excelConverter.ts @@ -1,72 +1,78 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { Borders, Workbook } from "exceljs"; +import { Borders, Column, Workbook } from "exceljs"; import { convertThemeColorToRGB, rgbToHex } from "./excelColors"; import { CellData, CellStyle, RowData, SheetData } from "x-data-spreadsheet"; +// import { SpreadsheetData } from "x-data-spreadsheet"; declare module "x-data-spreadsheet" { interface RowData { height?: number; } - - } -type borderDir = "top"|"bottom"|"left"|"right"; +type borderDir = "top" | "bottom" | "left" | "right"; export function toSpreadsheet(wb: Workbook) { - - function mapColor(oStyle: CellStyle,border: Partial, what: borderDir){ - if(border[what] && border[what].style && oStyle.border){ + function mapColor( + oStyle: CellStyle, + border: Partial, + what: borderDir + ) { + if (border[what] && border[what]?.style && oStyle.border) { oStyle.border[what] = [ - border[what].style?.toString(), - "#" + getColor(border[what].color) - ] + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + border[what]!.style!.toString(), + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + "#" + getColor(border[what]!.color), + ]; } } console.log(wb); const out = wb.worksheets.map((ws) => { - const ows : SheetData = { + const ows: SheetData = { name: ws.name, rows: {}, cols: {}, - merges: [] , - + merges: [], + // freezes: }; ows.styles = []; - for(const col of ws.columns){ - if(col.width && ows.cols && col.number) { - ows.cols[col.number-1] = {width: width2px(col.width)} + if (ws.columns) { + for (const col of ws.columns) { + if (col.width && ows.cols && col.number) { + ows.cols[col.number - 1] = { width: width2px(col.width) }; + } } - } + } ws.eachRow((row, rowNumber) => { - const rowId = (row.number - 1); + const rowId = row.number - 1; const rowob: RowData = { - cells: {} + cells: {}, }; - - if(ows.rows){ + + if (ows.rows) { ows.rows[rowId] = rowob; } - if(row.height){ + if (row.height) { // px = pt * ( 72pt / 96 ) rowob.height = pt2px(row.height); } - if(row.hidden) { + if (row.hidden) { rowob.hidden = true; // TODO: implementit! } row.eachCell((cell, cellNumber) => { - const cellOb : CellData = { - text: cell.text - } ; + const cellOb: CellData = { + text: cell.text, + }; if (cell.formula) cellOb.text = "=" + cell.formula; // style @@ -76,59 +82,56 @@ export function toSpreadsheet(wb: Workbook) { const fgColor = cell.style.fill.fgColor; if (fgColor) { const hexColor = getColor(fgColor); - if(hexColor) { + if (hexColor) { oStyle.bgcolor = "#" + hexColor; } } } - } if (cell.style.border) { - const border = cell.style.border; - console.log(border) + console.log(border); oStyle.border = {}; - ["top","bottom","left","right"].forEach(what=>{ - mapColor(oStyle,border,what as borderDir); + ["top", "bottom", "left", "right"].forEach((what) => { + mapColor(oStyle, border, what as borderDir); }); - } if (cell.style.font) { const font = cell.style.font; - - if(font.bold) { - oStyle.font = oStyle.font || {} + + if (font.bold) { + oStyle.font = oStyle.font || {}; oStyle.font.bold = true; } - if(font.color) { + if (font.color) { const hexColor = getColor(font.color); - if(hexColor) { + if (hexColor) { oStyle.color = "#" + hexColor; } } - if(font.italic) { + if (font.italic) { oStyle.font = oStyle.font || {}; // oStyle.font - (oStyle.font).italic = true; + oStyle.font.italic = true; } - if(font.strike) { - (oStyle).strike = true; + if (font.strike) { + oStyle.strike = true; } - if(font.underline) { - (oStyle).underline = true; + if (font.underline) { + oStyle.underline = true; } - if(font.name) { + if (font.name) { oStyle.font = oStyle.font || {}; - (oStyle.font).name = font.name; + oStyle.font.name = font.name; } - if(font.family){ + if (font.family) { oStyle.font = oStyle.font || {}; oStyle.font.family = font.family; } - if(font.size) { + if (font.size) { oStyle.font = oStyle.font || {}; - (oStyle.font).size = font.size; + oStyle.font.size = font.size; } // if(font.vertAlign) { // console.log("here"); @@ -136,53 +139,51 @@ export function toSpreadsheet(wb: Workbook) { } if (cell.style.alignment) { // - const alig = cell.style.alignment - if(alig.vertical){ + const alig = cell.style.alignment; + if (alig.vertical) { (oStyle as any).valign = alig.vertical; } - if(alig.horizontal){ + if (alig.horizontal) { (oStyle as any).align = alig.horizontal; } - if(cell.style.alignment.wrapText) { + if (cell.style.alignment.wrapText) { oStyle.textwrap = true; } - } if (cell.style.numFmt) { const numFmt = cell.style.numFmt; - if(numFmt.endsWith('%')){ - (oStyle as any).format = 'percent'; + if (numFmt.endsWith("%")) { + (oStyle as any).format = "percent"; // TODO: 0.00% - } else if (numFmt.contains('€')) { - (oStyle as any).format = 'eur'; - } else if (numFmt.contains('$')) { - (oStyle as any).format = 'usd'; + } else if (numFmt.contains("€")) { + (oStyle as any).format = "eur"; + } else if (numFmt.contains("$")) { + (oStyle as any).format = "usd"; } else if (numFmt === "@") { - (oStyle as any).format = 'text'; + (oStyle as any).format = "text"; } // TODO: dates mm-dd-yy // TODO: [$-F800]dddd, mmmm dd, yyyy // TODO: 0.00 // TODO: [$-F400]h:mm:ss AM/PM // TODO: 0.00E+00 - console.log(numFmt) + console.log(numFmt); } if (cell.style.protection) { //TODO: } - if(Object.keys(oStyle).length>0 && ows.styles){ - const j = JSON.stringify(oStyle) - let styleIndex = ows.styles.findIndex(s => - JSON.stringify(s) == j - ) - if(styleIndex<0) { + if (Object.keys(oStyle).length > 0 && ows.styles) { + const j = JSON.stringify(oStyle); + let styleIndex = ows.styles.findIndex( + (s) => JSON.stringify(s) == j + ); + if (styleIndex < 0) { ows.styles?.push(oStyle); - styleIndex = ows.styles.length-1; + styleIndex = ows.styles.length - 1; } cellOb.style = styleIndex; } - if (!cell.isMerged || !cell.model.master) { rowob.cells[Number(cell.col) - 1] = cellOb; @@ -212,7 +213,11 @@ export function toSpreadsheet(wb: Workbook) { return out; } function pt2px(pt: number) { - return Math.round(pt * 1.33333); + return Math.round(pt * 1.3333333); +} + +function px2pt(px: number) { + return Math.round(px * 0.75); } function width2px(w: number) { @@ -221,6 +226,10 @@ function width2px(w: number) { return Math.round(w * 6.4); } +function px2width(px: number) { + return Math.round(px * 0.15625); +} + function getColor(fgColor: any) { if (fgColor.argb) { const hex = fgColor.argb.substring(2); @@ -234,3 +243,57 @@ function getColor(fgColor: any) { } } +export function toExcelJS(data: SheetData[]): Workbook { + const workbook = new Workbook(); + console.log(data); + for (const ssheet of data) { + const wsheet = workbook.addWorksheet(ssheet.name); + + if (ssheet.cols !== undefined) { + const colIds = Object.keys(ssheet.cols) + .filter((key) => !isNaN(Number(key))) + .map((key) => Number(key)); + + const maxColid = Math.max(...colIds); + + const wscols: Partial[] = []; + for (let colid = 0; colid <= maxColid; colid++) { + const num = colid + 1; + const col: Partial = { + number: num, + key: num.toString(), + }; + const scol = ssheet.cols[colid]; + + if (scol?.width) { + col.width = px2width(scol.width); + } + wscols.push(col); + } + + wsheet.columns = wscols; + } + + if (ssheet.rows !== undefined) { + for (const rowId in ssheet.rows) { + if (!isNaN(Number(rowId))) { + const rowNum = Number(rowId); + const rowdata = ssheet.rows[rowNum]; + + const row = wsheet.getRow(rowNum + 1); + // cells, height, hidden + if (rowdata.hidden) { + row.hidden = true; + } + for (const cellId in rowdata.cells) { + const cellNum = Number(cellId); + const celldata = rowdata.cells[cellNum]; + const cell = row.getCell(cellNum + 1); + cell.value = celldata.text; + } + } + } + } + } + return workbook; +} diff --git a/tsconfig.json b/tsconfig.json index baade22..bfb0a8b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -23,5 +23,6 @@ }, "include": [ "**/*.ts","**/*.tsx","**/*.svg" - ] + ], + "exclude": ["node_modules"] }