Skip to main content

在 VS Code 中可视化数据

SheetJS 是一个用于从电子表格读取和写入数据的 JavaScript 库。

¥SheetJS is a JavaScript library for reading and writing data from spreadsheets.

Visual Studio Code 是一个流行的代码编辑器,支持 JavaScript 扩展,可用于自定义和增强功能。

¥Visual Studio Code is a popular code editor that supports JavaScript extensions for customizing and enhancing functionality.

"完整示例" 使用 VS Code 扩展中的 SheetJS 直接在编辑器中查看 Excel 文件。该扩展程序利用 VS Code 的 "自定义编辑器 API"[^2] 和 "WebView API"[^1] 将电子表格数据显示为 HTML 表格。

¥The "Complete Example" uses SheetJS in a VS Code extension to view Excel files directly within the editor. The extension leverages the VS Code "Custom Editor API"[^2] and "WebView API"[^1] to display spreadsheet data as HTML tables.

"SheetJS 电子表格查看器" 是基于此演示的示例扩展。

¥"SheetJS Spreadsheet Viewer" is a sample extension based on this demo.

源代码 可在 SheetJS Git 服务器上使用。欢迎反馈和贡献!

¥The source code is available on the SheetJS Git server. Feedback and contributions are welcome!

Expected output

测试部署

该演示已在以下部署中得到验证:

¥This demo was verified in the following deployments:

平台架构日期
VS Code 1.100.0darwin-arm2025-05-15TODO
VSCodium 1.100.0darwin-arm2025-05-15TODO
光标win11-arm2025-05-15TODO
Windsurfwin11-arm2025-05-15TODO
无效win11-arm2025-05-15TODO

集成详情

¥Integration Details

SheetJS NodeJS 模块 可以从扩展中的任何组件或脚本中导入。

¥The SheetJS NodeJS Module can be imported from any component or script in the extension.

该模块必须作为开发依赖安装。如果模块作为常规依赖安装,vsce[^5](Visual Studio Code 扩展管理器)将无法正确打包或发布你的扩展程序。

¥The module must be installed as a development dependency. If the module is installed as a normal dependency, vsce[^5] (Visual Studio Code Extension Manager) will fail to package or publish your extension correctly.

yarn remove xlsx
yarn add -D https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz

扩展架构

¥Extension Architecture

VS Code 电子表格查看器扩展包含三个主要组件:

¥The VS Code Spreadsheet viewer extension has three main components:

  • 扩展入口点:使用 VS Code 注册扩展

    ¥Extension Entry Point: Registers the extension with VS Code

  • 自定义编辑器提供程序:处理 Excel 文件并将其转换为 Web 内容

    ¥Custom Editor Provider: Handles Excel files and converts them to web content

  • WebView 内容:将 Excel 数据显示为 HTML 表格

    ¥WebView Content: Displays Excel data as HTML tables

该扩展程序使用 VS Code 的 Custom Editor API[^2] 注册为 Excel 文件的处理程序。打开文件时,SheetJS 会解析文件并在 WebView 组件中显示数据。

¥The extension uses VS Code's Custom Editor API[^2] to register as a handler for Excel files. When a file is opened, SheetJS parses it and displays the data in a WebView component.

扩展入口点

¥Extension Entry Point

主入口点注册了自定义编辑器提供程序:

¥The main entry point registers the custom editor provider:

src/extension.ts
import * as vscode from 'vscode';
import { ExcelEditorProvider } from './excelEditorProvider';

export function activate(context: vscode.ExtensionContext) {
// SheetJS Spreadsheet Viewer extension activating...
const provider = ExcelEditorProvider.register(context);
context.subscriptions.push(provider);
}
export function deactivate() {}`}

custom editor[^3] 配置为支持特定文件类型,使我们能够完全控制每个文件向用户的呈现方式。此外,custom document[^4] 使我们能够维护并保存每个已打开文件的状态。

¥The custom editor[^3] is configured to support specific file types, giving us complete control over how each file is presented to the user. Additionally, custom document[^4] enables us to maintain and persist the state of each individual file that's opened.

src/excelEditorProvider.ts
import * as vscode from 'vscode';
import * as XLSX from 'xlsx';
import { ExcelDocument } from './excelDocument';

// A simple class to store document state (one per opened file)
class ExcelDocument implements vscode.CustomDocument {
constructor(public readonly uri: vscode.Uri) {}
dispose() {}
}

export class ExcelEditorProvider implements vscode.CustomReadonlyEditorProvider<ExcelDocument> {
// ...
public static register(context: vscode.ExtensionContext): vscode.Disposable {
return vscode.window.registerCustomEditorProvider(
'excelViewer.spreadsheet',
new ExcelEditorProvider(),
{ webviewOptions: { retainContextWhenHidden: true } } // keep webview state when hidden
);
}
// ...
}

读取文件

¥Reading Files

该扩展程序使用 VS Code 文件系统 API 读取 Excel 文件,并将数据传递给 SheetJS 进行解析:

¥The extension reads Excel files using the VS Code filesystem API and passes the data to SheetJS for parsing:

src/excelEditorProvider.ts
export class ExcelEditorProvider implements vscode.CustomReadonlyEditorProvider<ExcelDocument> {
// ...
private async loadWorkbook(document: ExcelDocument, webviewPanel: vscode.WebviewPanel): Promise<XLSX.WorkBook> {
const data: Uint8Array = await vscode.workspace.fs.readFile(document.uri);

const options: XLSX.ParsingOptions = {
type: 'array',
cellStyles: true,
cellDates: true,
};

return XLSX.read(new Uint8Array(data), options); // returns a XLSX.WorkBook
}

// This is called when the first time an editor for a given resource is opened
async openCustomDocument(uri: vscode.Uri): Promise<ExcelDocument> {
return new ExcelDocument(uri);
}

// This is called whenever the user opens a new editor
async resolveCustomEditor(document: ExcelDocument, webviewPanel: vscode.WebviewPanel): Promise<void> {
const wb: XLSX.WorkBook = await this.loadWorkbook(document, webviewPanel);
const htmlTable = XLSX.utils.sheet_to_html(wb.Sheets[wb.SheetNames[0]]);
webviewPanel.webview.html = `<!DOCTYPE html><html><body>${htmlTable}</body></html>`;
}
}

使用流程

¥Usage Flow

完整示例

¥Complete Example

  1. 创建一个新的 VS Code 扩展

    ¥Create a new VS Code extension

npx --package yo --package generator-code -- yo code

出现提示时,输入以下选项:

¥When prompted, enter the following options:

  • What type of extension do you want to create?:选择 New Extension (TypeScript) 并按 Enter

    ¥What type of extension do you want to create?: Select New Extension (TypeScript) and press Enter

  • What's the name of your extension?:输入 sheetjs-demo 并按 Enter

    ¥What's the name of your extension?: Type sheetjs-demo and press Enter

  • What's the identifier of your extension?:按下 Enter

    ¥What's the identifier of your extension?: Press Enter

  • What's the description of your extension?:按下 Enter

    ¥What's the description of your extension?: Press Enter

  • Initialize a git repository?:输入 n 并按 Enter

    ¥Initialize a git repository?: Type n and press Enter

  • Which bundler to use?:选择 webpack 并按 Enter

    ¥Which bundler to use?: Select webpack and press Enter

  • Which package manager to use?:选择 pnpm 并按 Enter

    ¥Which package manager to use?: Select pnpm and press Enter

Expected output

  • Do you want to open the new folder with Visual Studio Code?:按下 Enter

    ¥Do you want to open the new folder with Visual Studio Code?: Press Enter

  1. 安装依赖 并启动开发服务器:

    ¥Install the dependencies and start the dev server:

cd sheetjs-demo
pnpm install -D https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz
pnpm run watch
  1. 将以下代码片段保存到 src/excelEditorProvider.ts

    ¥Save the following code snippet to src/excelEditorProvider.ts:

src/excelEditorProvider.ts
import * as vscode from 'vscode';
import * as XLSX from 'xlsx';

class ExcelDocument implements vscode.CustomDocument {
constructor(public readonly uri: vscode.Uri) { }
dispose() { }
}

export class ExcelEditorProvider implements vscode.CustomReadonlyEditorProvider<ExcelDocument> {
public static register(context: vscode.ExtensionContext): vscode.Disposable {
return vscode.window.registerCustomEditorProvider(
'excelViewer.spreadsheet',
new ExcelEditorProvider(),
{ webviewOptions: { retainContextWhenHidden: true } } // keep webview state when hidden
);
}

private async loadWorkbook(document: ExcelDocument, webviewPanel: vscode.WebviewPanel): Promise<XLSX.WorkBook> {
const data: Uint8Array = await vscode.workspace.fs.readFile(document.uri);

const options: XLSX.ParsingOptions = {
type: 'array',
cellStyles: true,
cellDates: true,
};

return XLSX.read(new Uint8Array(data), options); // returns a XLSX.WorkBook
}

// This is called when the first time an editor for a given resource is opened
async openCustomDocument(uri: vscode.Uri): Promise<ExcelDocument> {
return new ExcelDocument(uri);
}

// This is called whenever the user opens a new editor
async resolveCustomEditor(document: ExcelDocument, webviewPanel: vscode.WebviewPanel): Promise<void> {
const wb: XLSX.WorkBook = await this.loadWorkbook(document, webviewPanel);
const htmlTable = XLSX.utils.sheet_to_html(wb.Sheets[wb.SheetNames[0]]);
webviewPanel.webview.html = `<!DOCTYPE html><html><body>${htmlTable}</body></html>`;
}
}
  1. src/extension.ts 中注册自定义编辑器提供程序:

    ¥Register the custom editor provider in src/extension.ts:

src/extension.ts (replace contents)
import * as vscode from 'vscode';
import { ExcelEditorProvider } from './excelEditorProvider';

export function activate(context: vscode.ExtensionContext) {
// SheetJS Spreadsheet Viewer extension activating...
const provider = ExcelEditorProvider.register(context);
context.subscriptions.push(provider);
}
export function deactivate() {}
  1. package.jsoncontributes 部分注册自定义编辑器:

    ¥Register the custom editor in the contributes section of package.json:

package.json (add highlighted lines)
  "main": "./dist/extension.js",
"contributes": {
"customEditors": [
{
"viewType": "excelViewer.spreadsheet",
"displayName": "SheetJS Demo",
"selector": [
{ "filenamePattern": "*.xlsx" },
{ "filenamePattern": "*.xls" }
]
}
],
"commands": [
{
"command": "sheetjs-demo.helloWorld",
"title": "Hello World"
}
]
},
  1. 在编辑器中,打开 src/extension.ts 并按下 F5 或运行命令 Debug:从命令面板 (⇧⌘P) 开始调试。这将在新的扩展开发主机窗口中编译并运行扩展。

    ¥Inside the editor, open src/extension.ts and press F5 or run the command Debug: Start Debugging from the Command Palette (⇧⌘P). This will compile and run the extension in a new Extension Development Host window.

  2. 选择新的 VSCode 窗口并打开 .xlsx.xls 文件。

    ¥Select the new VSCode Window and open a .xlsx or .xls file.


[^1]: 详细信息请参见 Webview API

¥See Webview API for more details.

[^2]: 更多详情,请参阅 Custom Editor API 文档。

¥See Custom Editor API documentation for more details.

[^3]: 详细信息请参见 Custom Editor

¥See Custom Editor for more details.

[^4]: 详细信息请参见 CustomDocument

¥See CustomDocument for more details.

[^5]: 详细信息请参见 Visual Studio Code Extension Manager

¥See Visual Studio Code Extension Manager for more details.