--- title: Visualizing Data in VS 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 JavaScript extensions for customizing and enhancing functionality. The ["Complete Example"](#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. :::tip pass ["SheetJS Spreadsheet Viewer"](https://marketplace.visualstudio.com/items?itemName=asadbek.sheetjs-demo) is a sample extension based on this demo. [The source code](https://git.sheetjs.com/asadbek064/sheetjs-vscode-extension) is available on the SheetJS Git server. Feedback and contributions are welcome! ::: ![Expected output](pathname:///vscode/extension-viewing-xls-file.png) :::note Tested Deployments This demo was verified in the following deployments: | Platform | Architecture | Date | |:-----------------|:-------------|:-----------| | VS Code 1.100.0 | `darwin-arm` | 2025-05-15 | TODO | VSCodium 1.100.0 | `darwin-arm` | 2025-05-15 | TODO | Cursor | `win11-arm` | 2025-05-15 | TODO | Windsurf | `win11-arm` | 2025-05-15 | TODO | Void | `win11-arm` | 2025-05-15 | TODO ::: ## Integration Details The [SheetJS NodeJS Module](/docs/getting-started/installation/nodejs) can be imported from any component or script in the extension. :::caution pass 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. {`\ npm rm --save xlsx npm i --save-dev https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} {`\ pnpm rm xlsx pnpm install -D https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} {`\ yarn remove xlsx yarn add -D https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`} ::: ## 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. ### Extension Entry Point The main entry point registers the custom editor provider: ```ts 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() {}`} ``` 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. {`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 { // ... 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 The extension reads Excel files using the VS Code filesystem API and passes the data to SheetJS for parsing: {`export class ExcelEditorProvider implements vscode.CustomReadonlyEditorProvider { // ... private async loadWorkbook(document: ExcelDocument, webviewPanel: vscode.WebviewPanel): Promise { 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 { return new ExcelDocument(uri); } // This is called whenever the user opens a new editor async resolveCustomEditor(document: ExcelDocument, webviewPanel: vscode.WebviewPanel): Promise { const wb: XLSX.WorkBook = await this.loadWorkbook(document, webviewPanel); const htmlTable = XLSX.utils.sheet_to_html(wb.Sheets[wb.SheetNames[0]]); webviewPanel.webview.html = \`\${htmlTable}\`; } }`} ### 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 Enter - `What's the name of your extension?`: Type `sheetjs-demo` and press Enter - `What's the identifier of your extension?`: Press Enter - `What's the description of your extension?`: Press Enter - `Initialize a git repository?`: Type `n` and press Enter - `Which bundler to use?`: Select `webpack` and press Enter - `Which package manager to use?`: Select `pnpm` and press Enter ![Expected output](pathname:///vscode/yeo-code.png) - `Do you want to open the new folder with Visual Studio Code?`: Press Enter 2) [Install the dependencies](#integration-details) and start the dev server: {`\ cd sheetjs-demo pnpm install -D https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz pnpm run watch `} 3) Save the following code snippet to `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 { 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 { 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 { return new ExcelDocument(uri); } // This is called whenever the user opens a new editor async resolveCustomEditor(document: ExcelDocument, webviewPanel: vscode.WebviewPanel): Promise { const wb: XLSX.WorkBook = await this.loadWorkbook(document, webviewPanel); const htmlTable = XLSX.utils.sheet_to_html(wb.Sheets[wb.SheetNames[0]]); webviewPanel.webview.html = \`\${htmlTable}\`; } }`} 4) Register the custom editor provider in `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() {}`} 5) Register the custom editor in the `contributes` section of `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" } ] }, `} 6. 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. 7. Select the new VSCode Window and open a `.xlsx` or `.xls` file. --- [^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.