简介
主要是为了解决从 Excel 或者 WPS 中复制表格粘贴到笔记中后,因合并单元格没处理好导致表格数据混乱的问题。
之前是用表格挂件的方式来解决,但是感觉使用挂件来放表格数据的话,表格的内容跟笔记内容割裂开了,在全局搜索的时候,表格中命中的内容无法作为搜索结果来呈现。
所以这次换个方式:将从 Excel 或者 WPS 中复制的表格转成笔记支持的表格并插入到笔记中,让表格内容成为笔记正文。
实现思路
使用方法
- 在设置(Alt+P)——外观——代码片段——设置——JS中添加并启用代码片段,启用后,笔记右上角多出一个
表格转换
的图标 - 在 WPS 中选中表格并复制,粘贴到 LuckSheet 表格挂件中;
- 粘贴到挂件后,表格还是选中状态,此时按Ctrl+C再次复制;
- 点击右上角的【表格转换】图标,提示成功后,对应表格模板字符串已经复制到剪切板;
- 到笔记中按Ctrl+V粘贴表格。
**注意:**第二步在 WPS 中选中表格时,表头(也就是第一行)不要有行合并(多行合并),这种情况还未进行处理。
如果你的表格第一行就有行合并,可以往上多选一行空单元格作为表头以免出现异常。
视频演示
演示环境:V2.7.2 Windows 10
表格挂件压缩包
备注:挂件中全屏按钮要生效的话,需要到主题的 theme.css 中添加一个样式:
.fullScreen2 {
position: fixed;
top: 30px;
left: 0;
width: 100vw !important;
height: 95vh !important;
z-index: 200;
}
代码片段
(() => {
// 请求函数
function request(url, data = null, method = "POST") {
return new Promise((resolve, reject) => {
if (method.toUpperCase() == "POST") {
fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
})
.then(
(data) => resolve(data.json()),
(error) => {
reject(error);
}
)
.catch((err) => {
console.error("请求失败:", err);
});
}
});
}
// 复制内容到剪切板
function patseIntoClipboard(txt) {
let status = false;
const input = document.createElement("textarea");
document.body.appendChild(input);
input.innerHTML = txt;
input.select();
if (document.execCommand("copy")) {
document.execCommand("copy");
status = true;
showMessage("表格内容已复制到剪切板");
} else {
showMessage("复制失败");
}
document.body.removeChild(input);
return status;
}
// 弹出提示信息
async function showMessage(msg, timeout = 2000) {
await request("/api/notification/pushMsg", { msg, timeout });
}
// 表格转换
async function convertTable() {
let tableStr = await navigator.clipboard.readText();
let parser = new DOMParser();
let doc = parser.parseFromString(tableStr, "text/html");
let tableDom = doc?.querySelector("table");
let trs = tableDom?.querySelectorAll("tr");
let status = doc && tableDom && trs;
if (!status) {
showMessage("操作失败");
return;
}
// 获取表格的行数
let rowNum = trs.length;
// 获取表格的列数
let firstRow = trs[0].querySelectorAll("td");
let colNum = firstRow.length;
for (let td of firstRow) {
if (td.getAttribute("colspan")) {
let colspan = td.getAttribute("colspan");
colNum += parseInt(colspan) - 1;
}
}
// 创建一个二维数组,用来放置表格的数据
let tableData = [];
for (let i = 0; i < rowNum; i++) {
let tempArr = new Array(colNum).fill(null);
tableData.push(tempArr);
}
// 索引差值
let gap = 0;
// 被合并的单元格——填充此字符串
let emptyData = `{: class="fn__none"}`;
// 逐行解析表格,得到二维数组
for (let [rowIndex, tr] of trs.entries()) {
let tds = tr.querySelectorAll("td");
gap = 0;
row: for (let colIndex = 0; colIndex < tds.length; colIndex++) {
let td = tds[colIndex];
let rowspan = td.getAttribute("rowspan");
let colspan = td.getAttribute("colspan");
let content = td.innerText;
while (tableData[rowIndex][colIndex + gap] == emptyData) {
gap++;
}
if (!rowspan && !colspan) {
tableData[rowIndex][colIndex + gap] = content;
} else {
rowspan = parseInt(rowspan);
colspan = parseInt(colspan);
let a = new Array(colspan).fill(emptyData);
for (let i = 0; i < rowspan; i++) {
tableData[rowIndex + i].splice(colIndex + gap, colspan, ...a);
}
tableData[rowIndex][colIndex + gap] =
content + `{: colspan="${colspan}" rowspan="${rowspan}"}`;
gap = gap + colspan - 1;
}
}
}
// 将数组中的数据组合成表格模板
let templateStr = "";
for (let [index, row] of tableData.entries()) {
templateStr += "|";
for (let item of row) {
templateStr += item + "|";
}
templateStr += "\n";
if (index === 0) {
templateStr = templateStr + "|" + ":-------: |".repeat(colNum) + "\n";
}
}
// 将表格模板对应字符串写入到剪切板
patseIntoClipboard(templateStr);
}
// 顶栏添加一个按钮
const barMode = document.getElementById("barMode");
barMode.insertAdjacentHTML(
"beforebegin",
'<div id="convertTable" class="toolbar__item b3-tooltips b3-tooltips__se" aria-label="表格转换" ></div>'
);
const convertBtn = document.getElementById("convertTable");
convertBtn.style.width = "auto";
convertBtn.innerHTML = `<svg t="1679417318794" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2816" width="32" height="32"><path d="M885.3 957.3H140.7c-42.2 0-76.5-34.3-76.5-76.5V136.3c0-42.2 34.3-76.5 76.5-76.5h744.6c42.2 0 76.5 34.3 76.5 76.5v744.6c-0.1 42.1-34.3 76.4-76.5 76.4z m-744.6-851c-16.5 0-29.9 13.4-29.9 29.9v744.6c0 16.5 13.4 29.9 29.9 29.9h744.6c16.5 0 29.9-13.4 29.9-29.9V136.3c0-16.5-13.4-29.9-29.9-29.9H140.7z" fill="#7D7D7D" p-id="2817"></path><path d="M938.5 315.8h-851V91.1c0-4.4 3.6-8 8-8h835c4.4 0 8 3.6 8 8v224.7z" fill="#CBCBCB" p-id="2818"></path><path d="M961.7 339H64.3V136.3c0-42.2 34.3-76.5 76.5-76.5h744.6c42.2 0 76.5 34.3 76.5 76.5V339z m-850.9-46.5h804.4V136.3c0-16.5-13.4-29.9-29.9-29.9H140.7c-16.5 0-29.9 13.4-29.9 29.9v156.2zM938.5 644.8h-851c-12.9 0-23.3-10.4-23.3-23.3 0-12.8 10.4-23.3 23.3-23.3h851c12.9 0 23.3 10.4 23.3 23.3-0.1 12.9-10.5 23.3-23.3 23.3z" fill="#7D7D7D" p-id="2819"></path><path d="M363.4 957.3c-12.9 0-23.3-10.4-23.3-23.3V315.8c0-12.8 10.4-23.3 23.3-23.3s23.3 10.4 23.3 23.3V934c0 12.9-10.4 23.3-23.3 23.3zM662.6 957.3c-12.9 0-23.3-10.4-23.3-23.3V315.8c0-12.8 10.4-23.3 23.3-23.3s23.3 10.4 23.3 23.3V934c0 12.9-10.5 23.3-23.3 23.3z" fill="#7D7D7D" p-id="2820"></path></svg>`;
convertBtn.addEventListener(
"click",
(e) => {
convertTable();
e.stopPropagation();
e.preventDefault();
},
true
);
})();
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于