Chrome 和 Chromium
SheetJS 独立脚本 可以集成到 Chromium 扩展中。
¥The SheetJS Standalone scripts can be integrated in a Chromium extension.
该演示包括使用内容脚本和后台脚本从弹出窗口导出书签和抓取表格的示例。
¥This demo includes examples for exporting bookmarks from a popup and scraping tables with a content script and a background script.
演示 包括 Manifest V2 和 Manifest V3 的未打包扩展。
¥The demo includes unpacked extensions for Manifest V2 and Manifest V3.
该演示最后一次测试是在 2024 年 3 月 30 日,针对 Chrome 122。
¥This demo was last tested on 2024 March 30 against Chrome 122.
该演示展示了 Manifest V2 和 Manifest V3 扩展。
¥This demo showcases Manifest V2 and Manifest V3 extensions.
Chrome Web Store 不接受新的 V2 扩展,但可以在开发者模式下使用 "加载解包" 扩展选项进行旁加载。
¥Chrome Web Store will not accept new V2 extensions, but these can be sideloaded using the "Load unpacked" extension option in Developer mode.
新的 Chrome 和 Chromium 扩展应该使用 Manifest V3!
¥New Chrome and Chromium Extensions should use Manifest V3!
加载 SheetJS 脚本
¥Loading SheetJS Scripts
SheetJS 库应该打包在扩展中。出于路径目的,强烈建议将 xlsx.full.min.js
放置在根文件夹中。
¥SheetJS libraries should be bundled in the extension. For path purposes, it is
strongly recommended to place xlsx.full.min.js
in the root folder.
弹出页面
¥Popup Pages
在 Manifest V2 和 Manifest V3 扩展中,弹出页面可以使用普通的 <script>
标签加载独立脚本:
¥In Manifest V2 and Manifest V3 extensions, popup pages can load the standalone
script using a normal <script>
tag:
<script type="text/javascript" src="xlsx.full.min.js"></script>
内容脚本
¥Content Scripts
在 Manifest V2 和 Manifest V3 扩展中,可以通过 content_scripts
字段加载独立脚本:
¥In Manifest V2 and Manifest V3 extensions, the standalone script can be loaded
through the content_scripts
field:
/* in manifest.json v2 or v3 */
"content_scripts": [{
"matches": ["<all_urls>"],
"js": ["xlsx.full.min.js", "content.js"],
"run_at": "document_end"
}],
XLSX
全局将对其他内容脚本可见。
¥The XLSX
global will be visible to other content scripts.
后台脚本
¥Background Scripts
在 Manifest V2 扩展中,如果将独立脚本添加为后台脚本,其他后台脚本将能够访问 XLSX
全局!
¥In Manifest V2 extensions, if the standalone script is added as a background
script, other background scripts will be able to access the XLSX
global!
/* in manifest.json v2 only! */
"background": {
"scripts": ["xlsx.full.min.js", "table.js"],
"persistent": false
},
在 Manifest V3 扩展中,后台服务工作者可以通过 importScripts
加载独立脚本:
¥In Manifest V3 extensions, background service workers can load the standalone
script through importScripts
:
/* assuming background script is in the same folder as xlsx.full.min.js */
importScripts("./xlsx.full.min.js");
// now XLSX will be available
相关操作
¥Relevant Operations
官方文档涵盖了包括所需权限在内的详细信息。
¥The official documentation covers details including required permissions.
生成下载
¥Generating Downloads
清单 V2
¥Manifest V2
writeFile
函数适用于 Chrome 或 Chromium 扩展程序:
¥The writeFile
function works in a Chrome or Chromium extension:
XLSX.writeFile(wb, "export.xlsx");
在底层,它使用 chrome.downloads
API。"downloads"
权限应设置在 manifest.json
中。
¥Under the hood, it uses the chrome.downloads
API. "downloads"
permission
should be set in manifest.json
.
清单 V3
¥Manifest V3
在后台 Service Worker 中,URL.createObjectURL
不可用。相反,XLSX.write
可以为合成 URL 生成 Base64 字符串:
¥In a background service worker, URL.createObjectURL
is unavailable. Instead,
XLSX.write
can generate a Base64 string for a synthetic URL:
/* generate Base64 string */
const b64 = XLSX.write(wb, {bookType: "xlsx", type: "base64"});
chrome.downloads.download({
/* make a base64 url manually */
url: `data:application/octet-stream;base64,${b64}`,
filename: `SheetJSTables.xlsx`
});
内容脚本表抓取
¥Content Script Table Scraping
table_to_book
和 table_to_sheet
可以帮助从 DOM 表构建工作簿:
¥table_to_book
and table_to_sheet
can help build workbooks from DOM tables:
var tables = document.getElementsByTagName("table");
var wb = XLSX.utils.book_new();
for(var i = 0; i < tables.length; ++i) {
var ws = XLSX.utils.table_to_sheet(tables[i]);
XLSX.utils.book_append_sheet(wb, ws, "Table" + i);
}
演示
¥Demo
演示扩展包含多个功能来演示示例用法。生产扩展应包括正确的错误处理。
¥The demo extension includes multiple features to demonstrate sample usage. Production extensions should include proper error handling.
- Prepared Extension
- Extension from Scratch
-
下载所需清单版本的 zip:
¥Download the zip for the desired Manifest version:
-
在浏览器中打开
chrome://extensions/
并启用开发者模式¥Open
chrome://extensions/
in the browser and enable Developer mode -
将下载的 zip 文件拖放到窗口中。
¥Drag and drop the downloaded zip file into the window.
-
使用
create-chrome-ext
[^1] 创建一个新扩展:¥Create a new extension using
create-chrome-ext
[^1]:
npm create chrome-ext@latest sheetjs-crx -- --template vanilla-ts
cd sheetjs-crx
npm install
-
编辑
package.json
中高亮的行:¥Edit the highlighted lines in
package.json
:
{
"name": "sheetjs-crx",
"displayName": "SheetJS Demo",
"version": "0.0.0",
"author": "**",
"description": "Sample Extension using SheetJS to interact with Chrome",
-
编辑
manifest.ts
并添加到permissions
数组:¥Edit
manifest.ts
and add to thepermissions
array:
permissions: ['sidePanel', 'storage',
"activeTab",
"bookmarks",
"contextMenus",
"downloads",
"tabs"
],
-
安装 SheetJS 依赖并启动开发服务器:
¥Install the SheetJS dependency and start the dev server:
curl -o ./public/img/logo-48.png https://xlsx.nodejs.cn/logo.png
npm i --save https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz
npm run dev
构建步骤将创建一个 build
子文件夹。
¥The build step will create a build
subfolder.
-
将
src/popup/index.ts
替换为以下代码块:¥Replace
src/popup/index.ts
with the following codeblock:
import { version, utils, writeFileXLSX } from 'xlsx';
import './index.css'
/* recursively walk the bookmark tree */
const recurse_bookmarks = (data, tree, path) => {
if(tree.url) data.push({Name: tree.title, Location: tree.url, Path:path});
var T = path ? (path + "::" + tree.title) : tree.title;
(tree.children||[]).forEach(function(C) { recurse_bookmarks(data, C, T); });
};
const export_bookmarks = () => {
chrome.bookmarks.getTree(function(res) {
var data = [];
res.forEach(function(t) { recurse_bookmarks(data, t, ""); });
/* create worksheet */
var ws = utils.json_to_sheet(data, { header: ['Name', 'Location', 'Path'] });
/* create workbook and export */
var wb = utils.book_new();
utils.book_append_sheet(wb, ws, 'Bookmarks');
writeFileXLSX(wb, "bookmarks.xlsx");
});
};
document.addEventListener('DOMContentLoaded', () => {
const root = document.getElementById('app')!
const xprt = document.createElement("button"); // sjsdownload
xprt.type = "button"; xprt.innerHTML = "Export Bookmarks";
root.appendChild(xprt);
xprt.addEventListener("click", export_bookmarks);
const vers = document.createElement("a");
vers.innerHTML = "SheetJS " + version;
root.appendChild(vers);
vers.addEventListener("click", () => { chrome.tabs.create({url: "https://sheetjs.com/"}); });
});
-
将
src/background/index.ts
替换为以下代码块:¥Replace
src/background/index.ts
with the following codeblock:
chrome.runtime.onInstalled.addListener(function() {
chrome.contextMenus.create({
type: "normal",
id: "sjsexport",
title: "Export Table to XLSX",
contexts: ["page", "selection"]
});
chrome.contextMenus.create({
type: "normal",
id: "sj5export",
title: "Export All Tables in Page",
contexts: ["page", "selection"]
});
chrome.contextMenus.onClicked.addListener(function(info/*, tab*/) {
var mode = "";
switch(info.menuItemId) {
case 'sjsexport': mode = "JS"; break;
case 'sj5export': mode = "J5"; break;
default: return;
}
chrome.tabs.query({active: true, currentWindow: true}, function(tabs){
chrome.tabs.sendMessage(tabs[0].id, {Sheet:mode}, sjsexport_cb);
});
});
chrome.contextMenus.create({
id: "sjsabout",
title: "About",
contexts: ["browser_action"]
});
chrome.contextMenus.onClicked.addListener(function(info/*, tab*/) {
if(info.menuItemId !== "sjsabout") return;
chrome.tabs.create({url: "https://sheetjs.com/"});
});
});
function sjsexport_cb(wb) {
if(!wb || !wb.SheetNames || !wb.Sheets) { return alert("Error in exporting table"); }
const b64 = XLSX.write(wb, {bookType: "xlsx", type: "base64"});
chrome.downloads.download({
url: `data:application/octet-stream;base64,${b64}`,
filename: `SheetJSTables.xlsx`
})
}
-
将
src/contentScript/index.ts
替换为以下代码块:¥Replace
src/contentScript/index.ts
with the following codeblock:
import { utils } from 'xlsx';
var coords = [0,0];
document.addEventListener('mousedown', function(mouse) {
if(mouse && mouse.button == 2) coords = [mouse.clientX, mouse.clientY];
});
chrome.runtime.onMessage.addListener(function(msg, sender, cb) {
if(!msg || !msg['Sheet']) return;
if(msg.Sheet == "JS") {
var elt = document.elementFromPoint(coords[0], coords[1]);
while(elt != null) {
if(elt.tagName.toLowerCase() == "table") return cb(utils.table_to_book(elt));
elt = elt.parentElement;
}
} else if(msg.Sheet == "J5") {
var tables = document.getElementsByTagName("table");
var wb = utils.book_new();
for(var i = 0; i < tables.length; ++i) {
var ws = utils.table_to_sheet(tables[i]);
utils.book_append_sheet(wb, ws, "Table" + i);
}
return cb(wb);
}
cb(coords);
});
-
在浏览器中打开
chrome://extensions/
并启用开发者模式¥Open
chrome://extensions/
in the browser and enable Developer mode -
单击 "加载解包" 并选择项目中的
build
文件夹。¥Click "Load unpacked" and select the
build
folder within the project.
书签导出器
¥Bookmark Exporter
Testing (click to hide)
-
在浏览器中打开 https://sheetjs.com 并创建书签。
¥Open https://sheetjs.com in the browser and create a bookmark.
-
单击扩展图标(地址栏右侧的拼图图标)并选择 "SheetJS 演示"。
¥Click the Extensions icon (puzzle icon to the right of the address bar) and select "SheetJS Demo".
-
如果未显示小弹出窗口,请单击 SheetJS 图标
¥If a small popup is not displayed, click on the SheetJS icon
-
单击 "导出书签",然后单击 "保存"。打开下载的文件!
¥Click "Export Bookmarks" and click "Save". Open the downloaded file!
chrome.bookmarks
API 支持书签树遍历。扩展弹出窗口中的 "导出书签" 按钮递归地遍历书签树,将书签 URL 推送到数据数组中,然后导出到简单的电子表格中。
¥chrome.bookmarks
API enables bookmark tree traversal. The "Export Bookmarks"
button in the extension pop-up recursively walks the bookmark tree, pushes the
bookmark URLs into a data array, and exports into a simple spreadsheet.
/* walk the bookmark tree */
function recurse_bookmarks(data, tree) {
if(tree.url) data.push({Name: tree.title, Location: tree.url});
(tree.children||[]).forEach(function(child) { recurse_bookmarks(data, child); });
}
/* get bookmark data */
chrome.bookmarks.getTree(function(res) {
/* load into an array */
var data = [];
res.forEach(function(t) { recurse_bookmarks(data, t); });
/* create worksheet */
var ws = XLSX.utils.json_to_sheet(data, { header: ['Name', 'Location'] });
/* create workbook and export */
var wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, ws, 'Bookmarks');
XLSX.writeFile(wb, "bookmarks.xlsx");
});
表导出器
¥Table Exporter
Testing (click to hide)
-
在浏览器中打开 https://sheetjs.com/demo/table。
¥Open https://sheetjs.com/demo/table in the browser.
-
右键单击页面中的任意位置并选择 "SheetJS 演示" > "导出页面中的所有表格"
¥Right-click anywhere in the page and select "SheetJS Demo" > "Export All Tables in Page"
-
保存并打开下载的文件!
¥Save and open the downloaded file!
后台脚本配置上下文菜单,其中包含导出数据的选项。流程图显示了用户选择导出时的数据流。他们的结局不同
¥The background script configures a context menu with the option to export data. The flow diagrams show the data flow when the user chooses to export. They differ in the denouement
清单 V2
¥Manifest V2
对于 Manifest V2 扩展,XLSX.writeFile
就可以工作:
¥For Manifest V2 extensions, XLSX.writeFile
just works:
清单 V3
¥Manifest V3
对于 Manifest V3 扩展,由于 URL.createObjectURL
在后台服务工作线程中不可用,因此创建了一个合成 URL:
¥For Manifest V3 extensions, since URL.createObjectURL
is not available in
background service workers, a synthetic URL is created:
[^1]: 有关详细信息,请参阅 create-chrome-ext
包。
¥See the create-chrome-ext
package for more details.