added demo for sheetjs in vscode extension

This commit is contained in:
Asad Karimov 2025-05-15 01:41:40 -04:00
parent 1f87dda979
commit 9af5473755
5 changed files with 328 additions and 2 deletions

3
.gitignore vendored

@ -4,4 +4,5 @@ package-lock.json
pnpm-lock.yaml
/docs
node_modules
.idea
.idea
.vscode

@ -91,7 +91,7 @@ in the ["API Reference"](/docs/api/) section of the documentation.
<!-- The SheetJS Standalone script must be loaded before the UI5 bootstrap -->
<script src="https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js"></script>
<!-- UI5 bootstrap script -->
<script
id="sap-ui-bootstrap"

@ -0,0 +1,325 @@
---
title: Excel Viewer in Visual Studio Code
sidebar_label: Visual Studio Code
description: View Excel files directly in VS Code. Seamlessly browse spreadsheet data without leaving your editor using SheetJS. Navigate between worksheets and pages of data with a responsive
pagination_prev: demos/cloud/index
pagination_next: demos/bigdata/index
sidebar_custom_props:
summary: View Excel files directly within Visual Studio Code
---
import current from '/version.js';
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import CodeBlock from '@theme/CodeBlock';
[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing
data from spreadsheets.
[Visual Studio Code](https://code.visualstudio.com) is a popular code editor that supports extensions for customizing
and enhancing functionality.
This demo uses SheetJS in a VS Code extension to view Excel files directly within the editor. The extension leverages
VS Code's `Custom Editor API`[^2] and `WebView API`[^1] to display XLSX data as HTML tables.
The demo includes the full source code for the extension and installation instructions.
:::note Tested Deployments
This demo was verified in the following deployments:
| Platform | OS Version | Architecture | Date |
|:----------------|:------------------------|:------------------|:-----------|
| VS Code 1.100.0 | macOS 15.3.1 | Darwin (arm64) | 2025-05-15 |
:::
## Integration Details
The [SheetJS NodeJS Module](/docs/getting-started/installation/nodejs) can be imported from any component or script in the extension.
:::note
> Install the package as a developer dependency.
> Otherwise, `vsce`[^5] (Visual Studio Code Extension Manager) will **fail to package or publish** your extension correctly.
<Tabs groupId="pm">
<TabItem value="npm" label="npm">
<CodeBlock language="bash">{`\
npm rm --save xlsx
npm i --save-dev https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
</CodeBlock>
</TabItem>
<TabItem value="pnpm" label="pnpm">
<CodeBlock language="bash">{`\
pnpm rm xlsx
pnpm install -D https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
</CodeBlock>
</TabItem>
<TabItem value="yarn" label="Yarn" default>
<CodeBlock language="bash">{`\
yarn remove xlsx
yarn add -D https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
</CodeBlock>
</TabItem>
</Tabs>
:::
## Extension Architecture
The VS Code Spreadsheet viewer extension has three main components:
- **Extension Entry Point:** Registers the extension with VS Code
- **Custom Editor Provider:** Handles Excel files and converts them to web content
- **WebView Content:** Displays Excel data as HTML tables
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.
## Building the Extension
### Extension Entry Point
The main entry point registers the custom editor provider:
<CodeBlock language="typescript" value="typescript" title="src/extension.ts">
{`import * as vscode from 'vscode';
// highlight-start
import { ExcelEditorProvider } from './excelEditorProvider';
// highlight-end
export function activate(context: vscode.ExtensionContext) {
// SheetJS Spreadsheet Viewer extension activating...
// highlight-start
const provider = ExcelEditorProvider.register(context);
context.subscriptions.push(provider);
// highlight-end
}
export function deactivate() {}`}
</CodeBlock>
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.
<CodeBlock language="typescript" value="typescript" title="src/excelEditorProvider.ts">
{`import * as vscode from 'vscode';
// highlight-start
import * as XLSX from 'xlsx';
import { ExcelDocument } from './excelDocument';
// highlight-end
// 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(context),
{ webviewOptions: { retainContextWhenHidden: true } } // keep webview state when hidden
);
}
// ...
}`}
</CodeBlock>
### Reading Files
The extension reads Excel files using the VS Code filesystem API and passes
the data to SheetJS for parsing:
<CodeBlock language="typescript" value="typescript" title="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>\`;
}
}`}
</CodeBlock>
### Usage Flow
```mermaid
sequenceDiagram
actor User
participant VSCode as VS Code
participant Provider as ExcelEditorProvider
participant SheetJS
participant WebView
User->>VSCode: Open .xlsx file
VSCode->>Provider: openCustomDocument(uri)
Provider-->>VSCode: return ExcelDocument
VSCode->>Provider: resolveCustomEditor(document, webviewPanel)
Provider->>VSCode: workspace.fs.readFile(document.uri)
VSCode-->>Provider: return file data
Provider->>SheetJS: XLSX.read(data, options)
SheetJS-->>Provider: return workbook
Provider->>SheetJS: XLSX.utils.sheet_to_html(sheet)
SheetJS-->>Provider: return HTML
Provider->>WebView: set webview.html
WebView-->>User: Display Excel data
```
## Complete Example
1. Create a new VS Code extension
```bash
npx --package yo --package generator-code -- yo code
```
When prompted, enter the following options:
- `What type of extension do you want to create?`: Select `New Extension (TypeScript)` and press <kbd>Enter</kbd>
- `What's the name of your extension?`: Type `sheetjs-demo` and press <kbd>Enter</kbd>
- `What's the identifier of your extension?`: Press <kbd>Enter</kbd>
- `What's the description of your extension?`: Press <kbd>Enter</kbd>
- `Initialize a git repository?`: Type `n` and press <kbd>Enter</kbd>
- `Which bundler to use?`: Select `webpack` and press <kbd>Enter</kbd>
- `Which package manager to use?`: Select `pnpm` and press <kbd>Enter</kbd>
![Expected output](pathname:///vscode/yeo-code.png)
- `Do you want to open the new folder with Visual Studio Code?`: Press <kbd>Enter</kbd>
2. [Install the dependencies](#integration-details) and start:
<CodeBlock language="bash">{`\
pnpm install -D https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz
pnpm run watch
`}
</CodeBlock>
3. Create a new provider `excelEditorProivder.ts` and paste the following:
<CodeBlock language="typescript" value="typescript" title="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(context),
{ 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>\`;
}
}`}
</CodeBlock>
4. Register the custom editor provider with the main entry point `extension.ts`
<CodeBlock language="typescript" value="typescript" title="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() {}`}
</CodeBlock>
5. Registering the custom editor in your `package.json` file.
<CodeBlock language="json" value="json" title="./package.json">{`\
"main": "./dist/extension.js",
"contributes": {
// highlight-start
"customEditors": [
{
"viewType": "excelViewer.spreadsheet",
"displayName": "SheetJS Demo",
"selector": [
{ "filenamePattern": "*.xlsx" },
{ "filenamePattern": "*.xls" }
]
}
],
// highlight-end
"commands": [
{
"command": "sheetjs-demo.helloWorld",
"title": "Hello World"
}
]
},
`}
</CodeBlock>
6. Inside the editor, open `src/extension.ts` and press <kbd>F5</kbd> or run the command **Debug: Start Debugging**
from the Command Pallet (<kbd>⇧⌘P</kbd>). This will compile and run the extension in a new Extension Development Host window.
7. Select the new VSCode Window and open a `.xlsx` or `.xls` file.
![Expected output](pathname:///vscode/extension-viewing-xls-file.png)
---
### Learn More
You can check out [the complete SheetJS VS Code extension demo repository](https://git.sheetjs.com/asadbek064/sheetjs-vscode-extension) - your feedback and contributions are welcome!
[^1]: See [`Webview API`](https://code.visualstudio.com/api/extension-guides/webview) for more details.
[^2]: See [`Custom Editor API`](https://code.visualstudio.com/api/extension-guides/custom-editors) documentation for more details.
[^3]: See [`Custom Editor`](https://code.visualstudio.com/api/extension-guides/custom-editors#custom-editor) for more details.
[^4]: See [`CustomDocument`](https://code.visualstudio.com/api/extension-guides/custom-editors#customdocument) for more details.
[^5]: See [`Visual Studio Code Extension Manager`](https://code.visualstudio.com/api/working-with-extensions/publishing-extension) for more details.

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB