Compare commits

..

48 commits

Author SHA1 Message Date
ljcoder
d9df140382
Update README.md 2024-06-04 15:27:46 +08:00
雷军
04dc273d80 feat: readme 2024-05-08 14:59:00 +08:00
雷军
5e149efaa7 feat: readme 2024-05-06 18:29:15 +08:00
雷军
583c46a828 feat: readme 2024-05-06 18:24:21 +08:00
雷军
5397aade29 feat: excel plus readme 2024-05-06 14:50:12 +08:00
雷军
82a6a7d1f9 feat: excel plus readme 2024-05-06 14:48:55 +08:00
雷军
56ca68dde1 feat: excel plus readme 2024-05-06 14:47:50 +08:00
雷军
5380c7a6e9 feat: Obsidian Excel Pro Plugin doc 2024-04-29 11:24:25 +08:00
雷军
b018f956a7 feat: Obsidian Excel Pro Plugin doc 2024-04-29 11:20:50 +08:00
雷军
ff08a53c06 feat: Obsidian Excel Pro Plugin doc 2024-04-29 11:19:15 +08:00
雷军
05ea79123b feat: Obsidian Excel Pro Plugin doc 2024-04-29 11:17:35 +08:00
雷军
2135848b38 feat: 1.3.24 2024-03-20 10:45:10 +08:00
雷军
8d2a44df50 feat: 1.3.23 2024-02-18 15:00:40 +08:00
雷军
34f35f9822 feat: github action 2024-02-18 15:00:01 +08:00
雷军
42cbe19ad0 feat: github action 2024-02-18 14:03:22 +08:00
雷军
6dc364519b feat: selected all 2024-02-18 13:49:48 +08:00
雷军
9898398afc feat: selected all 2024-02-18 10:48:51 +08:00
雷军
ae4426b24f fix: input hidden 2023-12-29 11:04:28 +08:00
雷军
0346ab7ca3 feat: add sheet default rows stting 2023-12-29 10:57:11 +08:00
雷军
63c041ba05 feat: add sheet default rows stting 2023-12-29 10:54:09 +08:00
雷军
a1c620d4e2 fix: import excel bug 2023-12-29 10:27:56 +08:00
雷军
578a3388c6 fix: import excel bug 2023-12-29 10:20:28 +08:00
雷军
1bb57398d2 fix: cut paste bug 2023-12-27 17:38:14 +08:00
雷军
4d784ac627 fix: copy paste bug 2023-12-27 14:58:43 +08:00
雷军
2e8ee0f5ac fix: copy paste bug 2023-12-27 14:58:20 +08:00
雷军
231ab55de6 fix: import excel file bug 2023-12-15 16:29:36 +08:00
雷军
8908dd9da4 fix: import excel file bug 2023-12-15 16:29:14 +08:00
雷军
5e98093f49 feat: show sheet button config 2023-12-15 15:22:39 +08:00
雷军
3aa557087a feat: show sheet button config 2023-12-15 15:17:06 +08:00
雷军
8bbebb9a6f feat: 1.3.16 2023-12-15 14:00:03 +08:00
雷军
ed685da21c fix: import bug 2023-12-15 13:58:47 +08:00
雷军
2457eff3d1 fix: 1.3.15 search dark model 2023-12-08 18:13:21 +08:00
雷军
8ad8fe21e6 fix: 1.3.15 search dark model 2023-12-08 18:05:02 +08:00
雷军
a8ce218640 feat: 1.3.14 css update 2023-12-08 17:51:55 +08:00
雷军
10f2e6742a feat: 1.3.14 2023-12-08 17:38:08 +08:00
雷军
c70a1aa080 feat: search 2023-12-08 17:37:15 +08:00
雷军
c3c97b9204 feat: readme update 2023-12-08 09:38:17 +08:00
雷军
914a90021b feat: embed link show html 2023-12-06 15:52:02 +08:00
雷军
9aa99436b9 fix: row col resize not save 2023-12-04 15:57:11 +08:00
雷军
d31a59c76a feat: change dark mode default text color 2023-11-06 16:49:03 +08:00
雷军
a12cb3a222 feat: add create excel command 2023-11-06 10:32:43 +08:00
雷军
a52bc92027 feat: 1.3.11 2023-11-06 10:23:24 +08:00
雷军
437a3d4a3f fix: delete sheet not save, dark mode setting bug, sheet name bug 2023-11-06 10:22:39 +08:00
雷军
e19c7ced50 fix: 导出中文提示词错误 2023-11-06 09:45:27 +08:00
雷军
c8bf177971 feat: 1.3.10 2023-11-03 15:05:02 +08:00
雷军
fcbf77855e fix: add sheet dark mode input text color 2023-11-03 15:04:36 +08:00
雷军
e5a36707ff feat: 1.3.9 2023-11-03 14:17:18 +08:00
雷军
4cfdda2059 feat: dark mode 2023-11-03 14:16:45 +08:00
18 changed files with 2958 additions and 938 deletions

View file

@ -19,6 +19,7 @@ jobs:
- name: Build plugin
run: |
npm config set strict-ssl false
npm install
npm run build

View file

@ -1,3 +1,6 @@
> ### The Obsidian-Excel plugin will no longer be maintained or updated. To download Obsidian-Sheet-Plus, please visit [https://github.com/ljcoder2015/obsidian-sheet-plus](https://github.com/ljcoder2015/obsidian-sheet-plus)
> ### Obsidian-Excel插件不再更新维护旧功能不满足可以尝试使用新插件Obsidian-Sheet-Plus。下载地址 [https://github.com/ljcoder2015/obsidian-sheet-plus](https://github.com/ljcoder2015/obsidian-sheet-plus)
# Obsidian Excel Plugin
## Excel
@ -15,7 +18,15 @@ If you are using Microsoft Office 365 to create xlsx files, you need to import t
embed link rule:
> ![[`file-folder`/`file-name`#`sheet-name`|`sri`-`sci`:`eri`-`eci`<`sheet-height`>]]
```![[file-folder/file-name#sheet-name|sri-sci:eri-eci<sheet-height>{html}]]```
- `sri`: Start row index
- `eri`: End row index
- `sci`: Start column index
- `eci`: End column index
- `{html}`: Whether to display as HTML
- `<sheet-height>`: Sheet height, dispaly HTML not work
![link](./doc/img/link.gif)
@ -23,6 +34,8 @@ embed link rule:
![link](./doc//img/embed-link-height.gif)
![link](./doc//img/embed_html.gif)
### copy selected cells to HTML
![html](./doc/img/html.gif)
@ -39,4 +52,7 @@ embed link rule:
- ljcoder@163.com
### buy a Coffee
[https://ko-fi.com/ljcoder](https://ko-fi.com/ljcoder)

BIN
doc/img/embed_html.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 502 KiB

File diff suppressed because one or more lines are too long

View file

@ -1,10 +1,11 @@
{
"id": "excel",
"name": "Excel",
"version": "1.3.8",
"version": "1.3.24",
"minAppVersion": "0.15.0",
"description": "Create spreadsheets and easily embed them in Markdown",
"author": "ljcoder",
"authorUrl": "https://github.com/ljcoder2015",
"fundingUrl": "https://ko-fi.com/ljcoder",
"isDesktopOnly": false
}

2859
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -6,8 +6,7 @@
"scripts": {
"dev": "node esbuild.config.mjs",
"build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production",
"version": "node version-bump.mjs && git add manifest.json versions.json",
"postinstall": "patch-package"
"version": "node version-bump.mjs && git add manifest.json versions.json"
},
"keywords": [],
"author": "",
@ -24,13 +23,12 @@
"esbuild": "0.17.3",
"esbuild-plugin-less": "^1.2.4",
"obsidian": "latest",
"patch-package": "^8.0.0",
"tslib": "2.4.0",
"typescript": "4.7.4"
},
"dependencies": {
"monkey-around": "^2.3.0",
"x-data-spreadsheet": "^1.1.9",
"x-data-spreadsheet": "git+ssh://git@github.com:ljcoder2015/x-spreadsheet.git#1.1.4",
"xlsx": "https://cdn.sheetjs.com/xlsx-0.20.0/xlsx-0.20.0.tgz"
}
}

View file

@ -1,113 +0,0 @@
diff --git a/node_modules/x-data-spreadsheet/src/component/event.js b/node_modules/x-data-spreadsheet/src/component/event.js
index cdbc0fa..cb2a9db 100644
--- a/node_modules/x-data-spreadsheet/src/component/event.js
+++ b/node_modules/x-data-spreadsheet/src/component/event.js
@@ -74,6 +74,7 @@ export function bindTouch(target, { move, end }) {
starty = pageY;
}
evt.preventDefault();
+ evt.stopPropagation();
});
bind(target, 'touchend', (evt) => {
if (!end) return;
diff --git a/node_modules/x-data-spreadsheet/src/component/sheet.js b/node_modules/x-data-spreadsheet/src/component/sheet.js
index 086b8c4..cd01f6e 100644
--- a/node_modules/x-data-spreadsheet/src/component/sheet.js
+++ b/node_modules/x-data-spreadsheet/src/component/sheet.js
@@ -77,11 +77,11 @@ function selectorSet(multiple, ri, ci, indexesUpdated = true, moving = false) {
const cell = data.getCell(ri, ci);
if (multiple) {
selector.setEnd(ri, ci, moving);
- this.trigger('cells-selected', cell, selector.range);
+ this.trigger('cells-selected', this.data, selector.range);
} else {
// trigger click event
selector.set(ri, ci, indexesUpdated);
- this.trigger('cell-selected', cell, ri, ci);
+ this.trigger('cell-selected', this.data, ri, ci);
}
toolbar.reset();
table.render();
diff --git a/node_modules/x-data-spreadsheet/src/index.d.ts b/node_modules/x-data-spreadsheet/src/index.d.ts
index 948a8e9..7fe36b3 100644
--- a/node_modules/x-data-spreadsheet/src/index.d.ts
+++ b/node_modules/x-data-spreadsheet/src/index.d.ts
@@ -45,18 +45,18 @@ declare module 'x-data-spreadsheet' {
export interface SpreadsheetEventHandler {
(
envt: CELL_SELECTED,
- callback: (cell: Cell, rowIndex: number, colIndex: number) => void
+ callback: (sheetData: Record<string, any>, rowIndex: number, colIndex: number) => void
): void;
(
envt: CELLS_SELECTED,
callback: (
- cell: Cell,
+ sheetData: Record<string, any>,
parameters: { sri: number; sci: number; eri: number; eci: number }
) => void
): void;
(
evnt: CELL_EDITED,
- callback: (text: string, rowIndex: number, colIndex: number) => void
+ callback: (sheetData: Record<string, any>, rowIndex: number, colIndex: number) => void
): void;
}
@@ -182,6 +182,19 @@ declare module 'x-data-spreadsheet' {
* @param callback
*/
change(callback: (json: Record<string, any>) => void): this;
+
+ /**
+ * 添加sheet监听回调
+ * @param callback
+ */
+ onAddSheet(callback: () => void): this;
+
+ /**
+ * 重命名Sheet
+ * @param callback
+ */
+ onRenameSheet(callback: () => void): this;
+
/**
* set locale
* @param lang
diff --git a/node_modules/x-data-spreadsheet/src/index.js b/node_modules/x-data-spreadsheet/src/index.js
index 479a0b7..96d0f3a 100644
--- a/node_modules/x-data-spreadsheet/src/index.js
+++ b/node_modules/x-data-spreadsheet/src/index.js
@@ -20,6 +20,7 @@ class Spreadsheet {
this.bottombar = this.options.showBottomBar ? new Bottombar(() => {
const d = this.addSheet();
this.sheet.resetData(d);
+ this.sheet.trigger('add-sheet', "")
}, (index) => {
const d = this.datas[index];
this.sheet.resetData(d);
@@ -27,6 +28,7 @@ class Spreadsheet {
this.deleteSheet();
}, (index, value) => {
this.datas[index].name = value;
+ this.sheet.trigger('rename-sheet', value)
}) : null;
this.data = this.addSheet();
const rootEl = h('div', `${cssPrefix}`)
@@ -120,6 +122,16 @@ class Spreadsheet {
return this;
}
+ onAddSheet(cb) {
+ this.sheet.on('add-sheet', cb);
+ return this;
+ }
+
+ onRenameSheet(cb) {
+ this.sheet.on('rename-sheet', cb);
+ return this;
+ }
+
static locale(lang, message) {
locale(lang, message);
}

View file

@ -15,6 +15,22 @@ export class ExcelSettingTab extends PluginSettingTab {
containerEl.empty()
containerEl.createEl("h1", { text: t("BASE_COLOR") });
new Setting(containerEl)
.setName(t("BASE_COLOR"))
.setDesc(t("BASE_COLOR_DESC"))
.addDropdown((dropdown) =>
dropdown
.addOption("light","Light")
.addOption("dark","Dark")
.setValue(this.plugin.settings.theme)
.onChange(async (value) => {
this.plugin.settings.theme = value
this.plugin.saveSettings()
}),
);
containerEl.createEl("h1", { text: t("FILE_SETTING") });
new Setting(containerEl)
@ -98,5 +114,46 @@ export class ExcelSettingTab extends PluginSettingTab {
this.plugin.saveSettings()
})
)
new Setting(containerEl)
.setName(t("DEFAULT_ROWS_LEN"))
.setDesc(t("DEFAULT_ROWS_LEN_DESC"))
.addText((text) =>
text
.setPlaceholder("100")
.setValue(this.plugin.settings.defaultRowsLen)
.onChange(async (value) => {
this.plugin.settings.defaultRowsLen = value
this.plugin.saveSettings()
})
)
new Setting(containerEl)
.setName(t("DEFAULT_COLS_LEN"))
.setDesc(t("DEFAULT_COLS_LEN_DESC"))
.addText((text) =>
text
.setPlaceholder("26")
.setValue(this.plugin.settings.defaultColsLen)
.onChange(async (value) => {
this.plugin.settings.defaultColsLen = value
this.plugin.saveSettings()
})
)
new Setting(containerEl)
.setName(t("SHOW_SHEET_BUTTON"))
.setDesc(t("SHOW_SHEET_BUTTON_DESC"))
.addDropdown((dropdown) =>
dropdown
.addOption("true","True")
.addOption("false","False")
.setValue(this.plugin.settings.showSheetButton)
.onChange(async (value) => {
this.plugin.settings.showSheetButton = value
this.plugin.saveSettings()
}),
);
}
}

View file

@ -1,5 +1,5 @@
import ExcelPlugin from "src/main";
import { TextFileView, WorkspaceLeaf, Platform, Notice, moment } from "obsidian";
import { TextFileView, WorkspaceLeaf, Platform, Notice, moment, TFile } from "obsidian";
import Spreadsheet from "x-data-spreadsheet";
import * as XLSX from "xlsx";
import { stox, xtos } from "./utils/xlsxspread";
@ -8,6 +8,7 @@ import { getExcelData } from "./utils/DataUtils";
import zhCn from "./lang/locale/sheet-zh-cn"
import en from "./lang/locale/sheet-en"
import { t } from "./lang/helpers"
import { updateSheetTheme } from "./utils/ThemeUtils";
export class ExcelView extends TextFileView {
public plugin: ExcelPlugin;
@ -48,6 +49,13 @@ export class ExcelView extends TextFileView {
saveData(data: string) {
this.data = this.headerData() + data;
// console.log("saveData", this.data)
this.save(false)
.then(() => {
console.log("save data success", this.file)
})
.catch((e) => {
console.log("save data error", e)
})
}
clear(): void {
@ -58,8 +66,8 @@ export class ExcelView extends TextFileView {
this.data = data;
this.app.workspace.onLayoutReady(async () => {
// console.log('setViewData')
await this.refresh();
// console.log('setViewData', this.file)
this.refresh();
});
}
@ -78,11 +86,12 @@ export class ExcelView extends TextFileView {
}
const f = files[0];
const reader = new FileReader();
const self = this
reader.onload = (e) => {
const data = e.target?.result;
console.log('handleFile', self.file)
if (data) {
this.process_wb(XLSX.read(data));
self.process_wb(XLSX.read(data));
} else {
new Notice(t("READ_FILE_FAILED"));
}
@ -93,8 +102,16 @@ export class ExcelView extends TextFileView {
process_wb(wb: XLSX.WorkBook) {
const sheetData = stox(wb);
if (sheetData) {
this.sheet.loadData(sheetData);
this.saveData(JSON.stringify(sheetData));
sheetData.forEach((sheet) => {
var sheetAny = sheet as any
if (sheetAny.rows) {
const last = Object.keys(sheetAny.rows).last() || "100"
const max = parseInt(this.plugin.settings.defaultRowsLen)
sheetAny.rows.len = Math.max(max, parseInt(last) + 20)
}
})
this.saveData(JSON.stringify(sheetData))
this.refresh()
} else {
new Notice(t("DATA_PARSING_ERROR"));
}
@ -128,6 +145,7 @@ export class ExcelView extends TextFileView {
onload(): void {
this.ownerWindow = this.containerEl.win;
console.log("onload", this.file)
// 添加顶部导入按钮
this.importEle = this.addAction("download", t("IMPORT_XLSX_FILE"), (ev) =>
@ -179,6 +197,7 @@ export class ExcelView extends TextFileView {
// 初始化 sheet
const jsonData = JSON.parse(getExcelData(this.data) || "{}") || {};
// console.log("refresh", jsonData, this.file)
// 设置多语言
if (moment.locale() === 'zh-cn') {
@ -186,6 +205,41 @@ export class ExcelView extends TextFileView {
} else {
Spreadsheet.locale('en', en)
}
// 设置 sheet 样式
var style = {
bgcolor: '#ffffff',
align: 'left',
valign: 'middle',
textwrap: false,
strike: false,
underline: false,
color: '#0a0a0a',
font: {
name: 'Helvetica',
size: 10,
bold: false,
italic: false,
},
}
if (this.plugin.settings.theme === "dark") {
style = {
bgcolor: '#363636',
align: 'left',
valign: 'middle',
textwrap: false,
strike: false,
underline: false,
color: '#e6e6e6',
font: {
name: 'Helvetica',
size: 10,
bold: false,
italic: false,
},
}
}
//@ts-ignore
this.sheet = new Spreadsheet(this.sheetEle, {
@ -195,21 +249,23 @@ export class ExcelView extends TextFileView {
width: () => this.contentEl.clientWidth - 32,
},
row: {
len: 100,
len: parseInt(this.plugin.settings.defaultRowsLen),
height: parseInt(this.plugin.settings.rowHeight),
},
col: {
len: 26,
len: parseInt(this.plugin.settings.defaultColsLen),
width: parseInt(this.plugin.settings.colWidth),
indexWidth: 60,
minWidth: 60,
},
//@ts-ignore
style: style,
isDark: this.plugin.settings.theme === "dark"
})
.loadData(jsonData) // load data
.change(() => {
// save data to db
const data = this.sheet.getData();
// console.log("save data to db", data);
this.saveData(JSON.stringify(data));
})
.onAddSheet(() => {
@ -221,6 +277,11 @@ export class ExcelView extends TextFileView {
const data = this.sheet.getData();
// console.log('onRenameSheet', data)
this.saveData(JSON.stringify(data));
})
.onDeleteSheet(() => {
const data = this.sheet.getData();
// console.log('onDeleteSheet', data)
this.saveData(JSON.stringify(data));
});
this.sheet.on("cells-selected", (sheetData, { sri, sci, eri, eci }) => {
@ -241,6 +302,8 @@ export class ExcelView extends TextFileView {
this.cellsSelected.eci = ci;
});
updateSheetTheme(this.plugin.settings.theme === "dark")
// @ts-ignore
this.sheet.validate();
}

View file

@ -6,7 +6,13 @@ import {
} from "obsidian";
import ExcelPlugin from "./main";
import Spreadsheet from "x-data-spreadsheet";
import { getExcelData, getExcelAreaData } from "./utils/DataUtils";
import {
getExcelData,
getExcelAreaData,
getExcelAreaHtml,
} from "./utils/DataUtils";
import { updateSheetTheme } from "./utils/ThemeUtils";
import da from "./lang/locale/da";
let plugin: ExcelPlugin;
let vault: Vault;
@ -80,26 +86,45 @@ const tmpObsidianWYSIWYG = async (
internalEmbedDiv.empty();
const data = await vault.read(file);
const src = internalEmbedDiv.getAttribute("src") ?? "";
const alt = internalEmbedDiv.getAttribute("alt") ?? "";
var src = internalEmbedDiv.getAttribute("src") ?? "";
// 是否转换成HTML
var toHTML = false;
if (src.includes("{html}")) {
toHTML = true;
src = src.replace("{html}", "");
}
alt = internalEmbedDiv.getAttribute("alt") ?? "";
if (alt.includes("{html}")) {
// 单 sheet 中的某一区域
toHTML = true;
alt = alt.replace("{html}", "");
}
const split = src.split("#");
var excelData = getExcelData(data);
if (split.length > 1) {
excelData = getExcelAreaData(
data,
split[1],
alt
excelData = getExcelAreaData(data, split[1], alt);
}
// 生成内容
if (toHTML) {
const table = createEditSheetHtml(data, file, split[1], alt)
internalEmbedDiv.appendChild(table);
} else {
const sheetDiv = createSheetEl(
excelData,
file,
internalEmbedDiv.clientWidth
);
internalEmbedDiv.appendChild(sheetDiv);
}
const sheetDiv = createSheetEl(excelData, file, internalEmbedDiv.clientWidth);
if (markdownEmbed) {
//display image on canvas without markdown frame
internalEmbedDiv.removeClass("markdown-embed");
internalEmbedDiv.removeClass("inline-embed");
}
internalEmbedDiv.appendChild(sheetDiv);
// console.log('internalEmbedDiv', internalEmbedDiv, markdownEmbed)
}
el.empty();
@ -112,73 +137,234 @@ const tmpObsidianWYSIWYG = async (
internalEmbedDiv.empty();
const data = await vault.read(file);
const src = internalEmbedDiv.getAttribute("src") ?? "";
const alt = internalEmbedDiv.getAttribute("alt") ?? "";
var range = alt
var src = internalEmbedDiv.getAttribute("src") ?? "";
var heigh = parseInt(plugin.settings.sheetHeight)
// 是否转换成HTML
var toHTML = false;
if (src.includes("{html}")) {
// 单 sheet
toHTML = true;
src = src.replace("{html}", "");
}
var alt = internalEmbedDiv.getAttribute("alt") ?? "";
if (alt.includes("{html}")) {
// 单 sheet 中的某一区域
toHTML = true;
alt = alt.replace("{html}", "");
}
var heigh = parseInt(plugin.settings.sheetHeight);
const matchResult = alt.match(/<(\d+)>/);
if (matchResult && matchResult.length > 1) {
const extractedValue = matchResult[1]; // 获取匹配到的数字
// console.log("Extracted value:", extractedValue);
heigh = parseInt(extractedValue)
range = range.replace(/<\d+>/, '');
const extractedValue = matchResult[1]; // 获取匹配到的数字
// console.log("Extracted value:", extractedValue);
heigh = parseInt(extractedValue);
alt = alt.replace(/<\d+>/, "");
} else {
// console.log("No match found.");
// console.log("No match found.");
}
const split = src.split("#");
var excelData = getExcelData(data);
if (split.length > 1) {
excelData = getExcelAreaData(
data,
split[1],
range
);
excelData = getExcelAreaData(data, split[1], alt);
}
// console.log('internalEmbedDiv', excelData, src, alt)
const sheetDiv = createSheetEl(excelData, file, internalEmbedDiv.clientWidth, heigh);
if (toHTML) {
const table = createEditSheetHtml(data, file, split[1], alt)
internalEmbedDiv.appendChild(table);
} else {
const sheetDiv = createSheetEl(
excelData,
file,
internalEmbedDiv.clientWidth,
heigh
);
internalEmbedDiv.appendChild(sheetDiv);
}
if (markdownEmbed) {
//display image on canvas without markdown frame
internalEmbedDiv.removeClass("markdown-embed");
internalEmbedDiv.removeClass("inline-embed");
}
internalEmbedDiv.appendChild(sheetDiv);
};
const createSheetEl = (data: string, file: TFile, width: number, height: number = 300): HTMLDivElement => {
const sheetDiv = createDiv()
/**
* HTML
* @param data markdown data
* @param sheet sheet
* @param cells cells 格式为: sri-sci:eri-eci 6-6:7-8
* @returns
*/
const createEditSheetHtml = (
excelData: string,
file: TFile,
sheet: string,
cells: string
): HTMLDivElement => {
const sheetDiv = createDiv();
if (plugin.settings.showSheetButton == "true") {
const fileEmbed = sheetDiv.createDiv({
cls: "internal-embed file-embed mod-generic is-loaded",
text: file.basename,
attr: {
src: file.basename,
alt: file.basename,
contenteditable: false,
tabindex: -1,
},
});
// 点击按钮打开 sheet
fileEmbed.onClickEvent((e) => {
e.stopPropagation();
plugin.app.workspace.getLeaf().openFile(file);
});
}
// <div class="internal-embed file-embed mod-generic is-loaded" tabindex="-1" src="Excel 2023-09-07 17.18.19.sheet" alt="Excel 2023-09-07 17.18.19.sheet" contenteditable="false"><div class="file-embed-title"><span class="file-embed-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="svg-icon lucide-file"><path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z"></path><polyline points="14 2 14 8 20 8"></polyline></svg></span> Excel 2023-09-07 17.18.19.sheet</div></div>
const fileEmbed = sheetDiv.createDiv({
cls: "internal-embed file-embed mod-generic is-loaded",
text: file.basename,
var table = getExcelAreaHtml(excelData, sheet, cells);
var div = createDiv({
cls: "sheet-html",
attr: {
src: file.basename,
alt: file.basename,
contenteditable: false,
tabindex: -1
tabindex: "-1",
contenteditable: "false"
}
})
div.appendChild(table)
sheetDiv.appendChild(div);
return sheetDiv;
};
// 点击按钮打开 sheet
fileEmbed.onClickEvent((e) => {
e.stopPropagation()
plugin.app.workspace.getLeaf().openFile(file)
})
/**
* HTML
* @param data markdown data
* @param sheet sheet
* @param cells cells 格式为: sri-sci:eri-eci 6-6:7-8
* @returns
*/
const createSheetHtml = (
data: string,
file: TFile,
sheet: string,
cells: string
): HTMLDivElement => {
const sheetDiv = createDiv();
if (plugin.settings.showSheetButton == "true") {
const fileEmbed = sheetDiv.createDiv({
cls: "internal-embed file-embed mod-generic is-loaded",
text: file.basename,
attr: {
src: file.basename,
alt: file.basename,
contenteditable: false,
tabindex: -1,
},
});
// 点击按钮打开 sheet
fileEmbed.onClickEvent((e) => {
e.stopPropagation();
plugin.app.workspace.getLeaf().openFile(file);
});
}
const sheetEl = createDiv({
attr: {
style: "overflow-x: auto;"
},
});
const table = getExcelAreaHtml(data, sheet, cells);
sheetEl.appendChild(table);
sheetDiv.appendChild(sheetEl);
return sheetDiv;
};
/**
* bembed link
*/
const createSheetEl = (
data: string,
file: TFile,
width: number,
height: number = 300
): HTMLDivElement => {
const sheetDiv = createDiv();
if (plugin.settings.showSheetButton == "true") {
const fileEmbed = sheetDiv.createDiv({
cls: "internal-embed file-embed mod-generic is-loaded",
text: file.basename,
attr: {
src: file.basename,
alt: file.basename,
contenteditable: false,
tabindex: -1,
},
});
// 点击按钮打开 sheet
fileEmbed.onClickEvent((e) => {
e.stopPropagation();
plugin.app.workspace.getLeaf().openFile(file);
});
}
// <div class="internal-embed file-embed mod-generic is-loaded" tabindex="-1" src="Excel 2023-09-07 17.18.19.sheet" alt="Excel 2023-09-07 17.18.19.sheet" contenteditable="false"><div class="file-embed-title"><span class="file-embed-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="svg-icon lucide-file"><path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z"></path><polyline points="14 2 14 8 20 8"></polyline></svg></span> Excel 2023-09-07 17.18.19.sheet</div></div>
const sheetEl = createDiv({
cls: "sheet-iframe",
attr: {
id: `x-spreadsheet-${new Date().getTime()}`,
style: `height: ${height}px`
style: `height: ${height}px`,
},
});
const jsonData = JSON.parse(data || "{}") || {};
// console.log("createSheetEl", jsonData, data)
// 设置 sheet 样式
var style = {
bgcolor: "#ffffff",
align: "left",
valign: "middle",
textwrap: false,
strike: false,
underline: false,
color: "#0a0a0a",
font: {
name: "Helvetica",
size: 10,
bold: false,
italic: false,
},
};
if (plugin.settings.theme === "dark") {
style = {
bgcolor: "#363636",
align: "left",
valign: "middle",
textwrap: false,
strike: false,
underline: false,
color: "#e6e6e6",
font: {
name: "Helvetica",
size: 10,
bold: false,
italic: false,
},
};
}
//@ts-ignore
const sheet = new Spreadsheet(sheetEl, {
mode: "read",
@ -186,23 +372,28 @@ const createSheetEl = (data: string, file: TFile, width: number, height: number
showBottomBar: true,
view: {
height: () => height,
width: () => width,
width: () => width - 10,
},
row: {
len: 100,
len: parseInt(plugin.settings.defaultRowsLen),
height: parseInt(plugin.settings.rowHeight),
},
col: {
len: 26,
len: parseInt(plugin.settings.defaultColsLen),
width: parseInt(plugin.settings.colWidth),
indexWidth: 60,
minWidth: 60,
},
// @ts-ignore
style: style,
isDark: plugin.settings.theme === "dark",
}).loadData(jsonData); // load data
updateSheetTheme(plugin.settings.theme === "dark");
// @ts-ignore
sheet.validate();
sheetDiv.appendChild(sheetEl)
sheetDiv.appendChild(sheetEl);
return sheetDiv;
};
@ -262,7 +453,7 @@ const processInternalEmbed = async (
internalEmbedEl: Element,
file: TFile
): Promise<HTMLDivElement> => {
const src = internalEmbedEl.getAttribute("src");
var src = internalEmbedEl.getAttribute("src");
//@ts-ignore
if (!src) return;
@ -272,16 +463,36 @@ const processInternalEmbed = async (
const data = await vault.read(file);
const alt = internalEmbedEl.getAttribute("alt") ?? "";
// 是否转换成HTML
var toHTML = false;
if (src.includes("{html}")) {
toHTML = true;
src = src.replace("{html}", "");
}
var alt = internalEmbedEl.getAttribute("alt") ?? "";
if (alt.includes("{html}")) {
// 单 sheet 中的某一区域
toHTML = true;
alt = alt.replace("{html}", "");
}
const split = src.split("#");
var excelData = getExcelData(data);
if (split.length > 1) {
excelData = getExcelAreaData(
data,
split[1],
alt
);
excelData = getExcelAreaData(data, split[1], alt);
}
return await createSheetEl(excelData, file, internalEmbedEl.clientWidth);
// console.log('internalEmbedDiv', excelData, src, alt, toHTML)
if (toHTML) {
return await createSheetHtml(data, file, split[1], alt);
} else {
return await createSheetEl(
excelData,
file,
internalEmbedEl.clientWidth
);
}
};

View file

@ -25,6 +25,8 @@ export default {
// ExcelSettingTab.ts
BASE_COLOR: "Base color scheme",
BASE_COLOR_DESC: "Choose default color scheme",
FILE_SETTING: "File Setting",
FOLDER: "FOLDER",
FOLDER_DESC: "Create files in this folder by default",
@ -40,4 +42,10 @@ export default {
ROW_HEIGHT_DESC: "Default row height",
COLUMN_WIDTH: "Column Width",
COLUMN_WIDTH_DESC: "Default column width",
DEFAULT_ROWS_LEN: 'Default render rows',
DEFAULT_ROWS_LEN_DESC: 'Default number of render rows',
DEFAULT_COLS_LEN: 'Default render columns',
DEFAULT_COLS_LEN_DESC: 'Default number of rendered columns',
SHOW_SHEET_BUTTON: "Show Sheet Button",
SHOW_SHEET_BUTTON_DESC: "Show Sheet Button",
};

View file

@ -21,9 +21,11 @@ export default {
PLEASE_SELECT_DATA: "请选择要拷贝的数据",
IMPORT_XLSX_FILE: "导入 xlsx 文件",
EXPORT_XLSX_FILE: "到处 xlsx 文件",
EXPORT_XLSX_FILE: "导出 xlsx 文件",
// ExcelSettingTab.ts
BASE_COLOR: "基础颜色",
BASE_COLOR_DESC: "选择默认基础色",
FILE_SETTING: "文件设置",
FOLDER: "文件夹",
FOLDER_DESC: "新建文件将放在此文件夹下",
@ -39,4 +41,10 @@ export default {
ROW_HEIGHT_DESC: "设置表格的默认行高",
COLUMN_WIDTH: "列宽",
COLUMN_WIDTH_DESC: "设置表格的默认列宽",
DEFAULT_ROWS_LEN: '默认渲染行数',
DEFAULT_ROWS_LEN_DESC: '创建表格时默认渲染最大行数',
DEFAULT_COLS_LEN: '默认渲染列数',
DEFAULT_COLS_LEN_DESC: '创建表格时默认渲染最大列数',
SHOW_SHEET_BUTTON: "显示标题按钮",
SHOW_SHEET_BUTTON_DESC: "是否显示标题按钮",
};

View file

@ -135,15 +135,22 @@ export default class ExcelPlugin extends Plugin {
});
};
this.registerEvent(
this.app.workspace.on("file-menu", fileMenuHandlerCreateNew),
);
this.registerEvent(
this.app.workspace.on("file-menu", fileMenuHandlerCreateNew),
);
this.addCommand({
id: "excel-autocreate",
name: t("CREATE_EXCEL"),
callback: () => {
this.createAndOpenExcel(getExcelFilename(this.settings), undefined, this.getBlackData());
},
});
}
private registerMonkeyPatches() {
const key =
"https://github.com/zsviczian/obsidian-excalidraw-plugin/issues";
"https://github.com/ljcoder2015/obsidian-excel";
this.register(
around(Workspace.prototype, {
getActiveViewOfType(old) {

View file

@ -1,6 +1,7 @@
import { Notice } from "obsidian";
import { t } from "../lang/helpers"
import { expr2expr } from "../utils/alphabet"
import { t } from "../lang/helpers";
import { expr2expr } from "../utils/alphabet";
import da from "src/lang/locale/da";
/**
* sheet
* @param data markdown data
@ -33,15 +34,6 @@ export const getExcelAreaData = (
const excelData = getExcelData(data) || "{}";
const jsonData = JSON.parse(excelData) || [];
var cellArray = cells.split(":");
const start = cellArray[0].split("-");
var sri = parseInt(start[0]); // 开始行
var sci = parseInt(start[1]); // 开始列
const end = cellArray[1].split("-");
var eri = parseInt(end[0]); // 结束行
var eci = parseInt(end[1]); // 结束列
var newData = new Map<string, any>();
if (jsonData instanceof Array) {
@ -49,15 +41,39 @@ export const getExcelAreaData = (
return item.name === sheet;
})[0];
newData.set("name", sheet);
newData.set("autofilter", sheetData.autofilter);
newData.set("freeze", sheetData.freeze);
newData.set("styles", sheetData.styles);
newData.set("validations", sheetData.validations);
newData.set("merges", sheetData.merges);
var rowLen = eri - sri + 1;
if (sheetData) {
newData.set("name", sheet);
newData.set("autofilter", sheetData.autofilter);
newData.set("freeze", sheetData.freeze);
newData.set("styles", sheetData.styles);
newData.set("validations", sheetData.validations);
newData.set("merges", sheetData.merges);
console.log("------", jsonData, cells, sheetData);
var sri = 0;
var sci = 0;
var eri = 100;
var eci = 26;
if (cells.includes(":")) {
var cellArray = cells.split(":");
const start = cellArray[0].split("-");
var sri = parseInt(start[0]); // 开始行
var sci = parseInt(start[1]); // 开始列
const end = cellArray[1].split("-");
var eri = parseInt(end[0]); // 结束行
var eci = parseInt(end[1]); // 结束列
} else {
if (sheetData.rows && sheetData.rows.len) {
eri = sheetData.rows.len - 1;
}
if (sheetData.cols && sheetData.cols.len) {
eci = sheetData.cols.len - 1;
}
}
var rowLen = eri - sri + 1;
// 用来存储新数据
var rows = new Map<string, any>();
// 解析 row并重 0 开始排数据
@ -75,10 +91,19 @@ export const getExcelAreaData = (
if (cell) {
// 如果当前cell是公式
if (cell.text) {
var text = cell.text as String
if (text && text[0] === '=') {
var text = cell.text as String;
if (text && text[0] === "=") {
// console.log('cell text', text, sri, sci)
cell.text = text.replace(/[a-zA-Z]{1,3}\d+/g, word => expr2expr(word, -sci, -sri, (x, y) => true));
cell.text = text.replace(
/[a-zA-Z]{1,3}\d+/g,
(word) =>
expr2expr(
word,
-sci,
-sri,
(x, y) => true
)
);
// console.log('update cell text', cell.text)
}
}
@ -100,7 +125,7 @@ export const getExcelAreaData = (
}
// const rowLen = Math.max(9, eri - sri + 1)
console.log("rows", sheetData, rows);
// console.log("rows", sheetData, rows);
rows.set("len", rowLen);
newData.set("rows", Object.fromEntries(rows));
// const colLen = Math.max(Math.ceil(clientWidth / 91), eci - sci + 1)
@ -115,3 +140,124 @@ export const getExcelAreaData = (
// console.log("newData", Object.fromEntries(newData))
return newJsonData;
};
/**
* sheet cells HTML
* @param data markdown data
* @param sheet sheet
* @param cells cells 格式为: sri-sci:eri-eci 6-6:7-8
* @returns
*/
export const getExcelAreaHtml = (
data: string,
sheet: string,
cells: string
): HTMLElement => {
const excelData = getExcelData(data) || "{}";
const jsonData = JSON.parse(excelData) || [];
var table = createEl("table");
if (jsonData instanceof Array) {
const sheetData = jsonData.filter((item) => {
return item.name === sheet;
})[0];
if (sheetData) {
var sri = 0;
var sci = 0;
var eri = 100;
var eci = 26;
if (cells.includes(":")) {
var cellArray = cells.split(":");
const start = cellArray[0].split("-");
var sri = parseInt(start[0]); // 开始行
var sci = parseInt(start[1]); // 开始列
const end = cellArray[1].split("-");
var eri = parseInt(end[0]); // 结束行
var eci = parseInt(end[1]); // 结束列
} else {
if (sheetData.rows && sheetData.rows.len) {
eri = sheetData.rows.len - 1;
}
if (sheetData.cols && sheetData.cols.len) {
eci = sheetData.cols.len - 1;
}
}
// console.log("getExcelAreaHtml", cells, sri, sci, eri, eci);
// 记录合并单元格数量
var mergeMap: Map<string, boolean> = new Map();
for (var row = sri; row <= eri; row++) {
var tr = createEl("tr");
table.appendChild(tr);
for (var col = sci; col <= eci; col++) {
// 获取当前行的数据
const cells = sheetData.rows[`${row}`];
if (cells) {
// 如果当前行有数据
// 获取单元格数据
const cell = cells.cells[`${col}`];
if (cell) {
// 如果单元格有数据展示数据
if (cell.merge) {
// 是否有合并单元格的操作
var mergeRow = cell.merge[0] + 1;
var mergeCol = cell.merge[1] + 1;
// 记录合并的行跟列
for (var r = 0; r < mergeRow; r++) {
const index = `${row + r}-${col}`;
mergeMap.set(index, true);
for (var c = 0; c < mergeCol; c++) {
const index = `${row + r}-${col + c}`;
mergeMap.set(index, true);
}
}
var td = createEl("td", {
text: cell.text || "",
attr: {
rowspan: mergeRow,
colspan: mergeCol,
},
});
tr.appendChild(td);
} else {
// 无合并单元格直接添加
var td = createEl("td", {
text: cell.text || "",
});
tr.appendChild(td);
}
} else {
// 添加空白单元格需要判断是否被合并了
const index = `${row}-${col}`;
if (!mergeMap.get(index)) {
// 单元格没数据添加空白单元格 & 没有被合并单元格
var td = createEl("td");
tr.appendChild(td);
}
}
} else {
const index = `${row}-${col}`;
// 添加空白单元格需要判断是否被合并了
if (!mergeMap.get(index)) {
// 单元格没数据添加空白单元格 & 没有被合并单元格
var td = createEl("td");
tr.appendChild(td);
}
}
}
}
} else {
}
}
return table;
};

View file

@ -4,7 +4,11 @@ export interface ExcelSettings {
excelFilenameDateTime: string,
sheetHeight: string,
rowHeight: string,
colWidth: string
colWidth: string,
theme: string,
showSheetButton: string,
defaultRowsLen: string,
defaultColsLen: string,
}
export const DEFAULT_SETTINGS: ExcelSettings = {
@ -13,5 +17,9 @@ export const DEFAULT_SETTINGS: ExcelSettings = {
excelFilenameDateTime: "YYYY-MM-DD HH.mm.ss",
sheetHeight: "300",
rowHeight: "25",
colWidth: "100"
colWidth: "100",
theme: "light",
showSheetButton: "true",
defaultRowsLen: "100",
defaultColsLen: "26",
};

28
src/utils/ThemeUtils.ts Normal file
View file

@ -0,0 +1,28 @@
export function updateSheetTheme(isDark: Boolean) {
const root = document.documentElement;
if (isDark) {
root.style.setProperty('--sheet-iframe-background-color', "#363636")
root.style.setProperty('--sheet-iframe-border-color', "#a5a0f8")
root.style.setProperty('--sheet-toolbar-background-color', "#a5a0f8")
root.style.setProperty('--sheet-toolbar-divider-color', "#a5a0f8")
root.style.setProperty('--sheet-dropdown-content-background-color', "#857fe6")
root.style.setProperty('--sheet-dropdown-content-color', "#dcdcdc")
root.style.setProperty('--sheet-dropdown-title-color', "rgba(0,0,0,0.9)")
root.style.setProperty('--sheet-menu-color', "#000")
root.style.setProperty('--sheet-menu-active-background-color', "#bdb9f9")
root.style.setProperty('--sheet-header-background-color', "#bdb9f9")
root.style.setProperty('--sheet-checked-before', "#025492")
} else {
root.style.setProperty('--sheet-iframe-border-color', "#f5f6f7")
root.style.setProperty('--sheet-iframe-background-color', "#fff")
root.style.setProperty('--sheet-toolbar-background-color', "#f5f6f7")
root.style.setProperty('--sheet-toolbar-divider-color', "#e0e2e4")
root.style.setProperty('--sheet-dropdown-content-background-color', "#fff")
root.style.setProperty('--sheet-dropdown-content-color', "rgba(0,0,0,0.9)")
root.style.setProperty('--sheet-dropdown-title-color', "rgba(0,0,0,0.9)")
root.style.setProperty('--sheet-menu-color', "#80868b")
root.style.setProperty('--sheet-menu-active-background-color', "#fff")
root.style.setProperty('--sheet-header-background-color', "#f8f8f9")
root.style.setProperty('--sheet-checked-before', "#4b89ff")
}
}

File diff suppressed because one or more lines are too long