diff --git a/src/ExcelView.ts b/src/ExcelView.ts index 873c5fe..c43ab89 100644 --- a/src/ExcelView.ts +++ b/src/ExcelView.ts @@ -4,6 +4,7 @@ import Spreadsheet from "x-data-spreadsheet"; import * as XLSX from "xlsx"; import { stox, xtos } from "./utils/xlsxspread"; import { VIEW_TYPE_EXCEL, FRONTMATTER } from "./constants"; +import { getExcelData } from "./utils/DataUtils"; export class ExcelView extends TextFileView { public plugin: ExcelPlugin; @@ -37,18 +38,6 @@ export class ExcelView extends TextFileView { return this.data; } - getExcelData(): string { - const tagText = "# Excel\n"; - const trimLocation = this.data.search(tagText); - if (trimLocation == -1) return this.data; - const excelData = this.data.substring( - trimLocation + tagText.length, - this.data.length - ); - // console.log("trimLocation", trimLocation, excelData, this.data); - return excelData; - } - headerData() { return FRONTMATTER + "\n# Excel\n"; } @@ -117,8 +106,18 @@ export class ExcelView extends TextFileView { } handleEmbedLink(e: Event) { - if (this.file) { - navigator.clipboard.writeText(`![[${this.file.path}]]`); + const data = this.cellsSelected.sheet; + const sri = this.cellsSelected.sri; + const sci = this.cellsSelected.sci; + const eri = this.cellsSelected.eri; + const eci = this.cellsSelected.eci; + + + // 格式 sri-sci:eri-eci + if (this.file && data && sri && sci && eri && eci) { + const link = `![[${this.file.basename}#${data.name}|${sri}-${sci}:${eri}-${eci}]]` + console.log(this.file, link) + navigator.clipboard.writeText(link); new Notice("Copy embed link to clipboard"); } else { new Notice("Copy embed link failed"); @@ -137,9 +136,9 @@ export class ExcelView extends TextFileView { this.handleExportClick(ev) ); - // this.embedLinkEle = this.addAction("link", "copy embed link", (ev) => - // this.handleEmbedLink(ev) - // ); + this.embedLinkEle = this.addAction("link", "copy embed link", (ev) => + this.handleEmbedLink(ev) + ); this.copyHTMLEle = this.addAction("file-code", "copy to HTML", (ev) => this.copyToHTML() @@ -179,7 +178,7 @@ export class ExcelView extends TextFileView { ); // 初始化 sheet - const jsonData = JSON.parse(this.getExcelData() || "{}") || {}; + const jsonData = JSON.parse(getExcelData(this.data) || "{}") || {}; //@ts-ignore this.sheet = new Spreadsheet(this.sheetEle, { diff --git a/src/MarkdownPostProcessor.ts b/src/MarkdownPostProcessor.ts index 42d425f..c5677d8 100644 --- a/src/MarkdownPostProcessor.ts +++ b/src/MarkdownPostProcessor.ts @@ -6,6 +6,7 @@ import { } from "obsidian"; import ExcelPlugin from "./main"; import Spreadsheet from "x-data-spreadsheet"; +import { getExcelData, getExcelAreaData } from "./utils/DataUtils"; let plugin: ExcelPlugin; let vault: Vault; @@ -100,8 +101,17 @@ const tmpObsidianWYSIWYG = async ( internalEmbedDiv.empty(); const data = await vault.read(file); + + const src = internalEmbedDiv.getAttribute("src") ?? "" + const alt = internalEmbedDiv.getAttribute("alt") ?? "" + const split = src.split("#") + var excelData = getExcelData(data) + if (split.length > 1) { + excelData = getExcelAreaData(data, split[1], alt, internalEmbedDiv.clientWidth) + } + console.log('internalEmbedDiv', excelData, src, alt) const sheetDiv = createSheetEl( - getExcelData(data), + excelData, internalEmbedDiv.clientWidth ); if (markdownEmbed) { @@ -121,6 +131,7 @@ const createSheetEl = (data: string, width: number): HTMLDivElement => { }); const jsonData = JSON.parse(data || "{}") || {}; + // console.log("createSheetEl", jsonData, data) //@ts-ignore const sheet = new Spreadsheet(sheetEle, { mode: "read", @@ -137,18 +148,6 @@ const createSheetEl = (data: string, width: number): HTMLDivElement => { return sheetEle; }; -const getExcelData = (data: string): string => { - const tagText = "# Excel\n"; - const trimLocation = data.search(tagText); - if (trimLocation == -1) return data; - const excelData = data.substring( - trimLocation + tagText.length, - data.length - ); - // console.log("trimLocation", trimLocation, excelData, this.data); - return excelData; -}; - /** * * @param el @@ -161,7 +160,7 @@ export const markdownPostProcessor = async ( //check to see if we are rendering in editing mode or live preview //if yes, then there should be no .internal-embed containers const embeddedItems = el.querySelectorAll(".internal-embed"); - console.log("markdownPostProcessor", embeddedItems.length); + // console.log("markdownPostProcessor", embeddedItems.length); if (embeddedItems.length === 0) { tmpObsidianWYSIWYG(el, ctx); return; @@ -174,7 +173,7 @@ const processReadingMode = async ( embeddedItems: NodeListOf | [HTMLElement], ctx: MarkdownPostProcessorContext ) => { - console.log("processReadingMode"); + // console.log("processReadingMode"); //We are processing a non-excalidraw file in reading mode //Embedded files will be displayed in an .internal-embed container diff --git a/src/utils/DataUtils.ts b/src/utils/DataUtils.ts new file mode 100644 index 0000000..d21a735 --- /dev/null +++ b/src/utils/DataUtils.ts @@ -0,0 +1,101 @@ +import { Notice } from "obsidian"; +/** + * 获取 sheet 数据 + * @param data markdown 文件原始data + * @returns 去掉头部数据的 sheet data + */ +export const getExcelData = (data: string): string => { + const tagText = "# Excel\n"; + const trimLocation = data.search(tagText); + if (trimLocation == -1) return data; + const excelData = data.substring( + trimLocation + tagText.length, + data.length + ); + // console.log("trimLocation", trimLocation, excelData, this.data); + return excelData; +}; + +/** + * 获取指定 sheet 中指定 cells 的数据 + * @param data markdown 文件原始data + * @param sheet sheet 名称 + * @param cells 选中的cells 格式为: sri-sci:eri-eci 例如 6-6:7-8 + * @returns + */ +export const getExcelAreaData = ( + data: string, + sheet: string, + cells: string, + clientWidth: number +): string => { + const excelData = getExcelData(data) || "{}"; + const jsonData = JSON.parse(excelData) || []; + + var sri: number | null = null; + var sci: number | null = null; + var eri: number | null = null; + var eci: number | null = null; + + var cellArray = cells.split(":"); + const start = cellArray[0].split("-"); + sri = parseInt(start[0]); + sci = parseInt(start[1]); + + const end = cellArray[1].split("-"); + eri = parseInt(end[0]); + eci = parseInt(end[1]); + + var newData = new Map(); + newData.set("name", sheet); + newData.set("autofilter", {}); + newData.set("freeze", "A1"); + newData.set("styles", [{ "0": { bgcolor: "#fe0000" } }]); + newData.set("validations", []); + + if (jsonData instanceof Array) { + const sheetData = jsonData.filter((item) => { + return item.name === sheet; + })[0]; + var rowLen = eri - sri + 1; + if (sheetData && sri && sci && eri && eci) { + var rows = new Map(); + for (var row = 0; row <= eri - sri; row++) { + const rowsData = sheetData.rows[`${row + sci}`]; + // console.log("getExcelAreaData", sheetData, rowsData, row + eri); + var newCells = new Map(); + if (rowsData) { + var cellsData = new Map(); + for (var col = 0; col <= eci - sci; col++) { + const cell = rowsData.cells[`${col + sci}`]; + if (cell) { + cellsData.set(`${col}`, cell); + if (row == eri - sri && cell.merge) { + rowLen = Math.max( + rowLen, + eri - sri + 1 + cell.merge[0] + ); + console.log(rowLen); + } + } + } + newCells.set("cells", Object.fromEntries(cellsData)); + } + rows.set(`${row}`, Object.fromEntries(newCells)); + } + // const rowLen = Math.max(9, eri - sri + 1) + + rows.set("len", rowLen); + newData.set("rows", Object.fromEntries(rows)); + // const colLen = Math.max(Math.ceil(clientWidth / 91), eci - sci + 1) + const colLen = eci - sci + 1; + newData.set("cols", { len: colLen }); + } else { + new Notice("Please first select the data to copy"); + } + } + + const newJsonData = JSON.stringify(Object.fromEntries(newData)); + // console.log("newData", Object.fromEntries(newData)) + return newJsonData; +}; diff --git a/styles.css b/styles.css index 6eac624..d6c6a8a 100644 --- a/styles.css +++ b/styles.css @@ -16,8 +16,9 @@ /* Markdown 文档引入样式设置*/ .sheet-iframe { width: 100%; - height: 300px; + height: 308px; background-color: var(--background-primary-alt); + border: 5px solid #f5f6f7; } ul.x-spreadsheet-menu {