This commit is contained in:
Gabriele Cannata 2023-08-05 18:02:46 +02:00
parent 7bb91b9856
commit f8147bc696
6 changed files with 316 additions and 198 deletions

View file

@ -1,11 +1,11 @@
export interface SheetjsSettings {
addRibbonIcon: boolean;
enableSaveToFile: boolean
}
export const DEFAULT_SETTINGS: SheetjsSettings = {
addRibbonIcon: true,
addRibbonIcon: false,
enableSaveToFile: true
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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<Borders>, what: borderDir){
if(border[what] && border[what].style && oStyle.border){
function mapColor(
oStyle: CellStyle,
border: Partial<Borders>,
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<Column>[] = [];
for (let colid = 0; colid <= maxColid; colid++) {
const num = colid + 1;
const col: Partial<Column> = {
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;
}

View file

@ -23,5 +23,6 @@
},
"include": [
"**/*.ts","**/*.tsx","**/*.svg"
]
],
"exclude": ["node_modules"]
}