--- title: Visualizing Data in VS Code sidebar_label: Visual Studio Code description: View Excel files directly in VS Code. Seamlessly browse spreadsheet data using SheetJS. Navigate between worksheets and pages of data with a responsive interface. pagination_prev: demos/cloud/index pagination_next: demos/bigdata/index sidebar_custom_props: summary: View Excel spreadsheets 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 "WebView API"[^1] and "Custom Editor API"[^2] to display spreadsheet data as HTML tables. :::tip pass "SheetJS Spreadsheet Viewer" is a sample extension based on this demo. It is available on [Open VSX](https://open-vsx.org/extension/asadbek/sheetjs-demo) and [VSCode Marketplace](https://marketplace.visualstudio.com/items?itemName=asadbek.sheetjs-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 | |:-------------------|:-------------|:-----------| | VSCodium 1.109 | `darwin-arm` | 2026-03-05 | | VS Code 1.110.0 | `win11-arm` | 2026-03-05 | | Antigravity 1.19.6 | `linux-arm` | 2026-03-05 | ::: ## 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 SheetJS NodeJS module must be installed as a development dependency. If the module is installed as a normal dependency, the `vsce`[^3] command-line tool will fail to package or publish the exxtension. {`\ 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`[^4] is configured to support specific file types, giving us complete control over how each file is presented to the user. Additionally, `custom document`[^5] 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 :::caution pass To avoid conflicts with existing extensions, it is strongly recommended to test with a different VSCode fork. For example, VSCode and Antigravity users should install and use VSCodium for extension development. ::: 1) Download the [`pres.xlsx`](https://docs.sheetjs.com/pres.xlsx) sample file. 2) 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 (use the default `sheetjs-demo`) - `What's the description of your extension?`: Press Enter (leave blank) - `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) 3) Install the SheetJS library and start the dev server: {`\ cd sheetjs-demo pnpm install -D https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz pnpm run watch `} 4) Launch a new editor window using the desired VSCode fork and open the newly created `sheetjs-demo` folder. 4) Save the following codeblock to `src/extension.ts`: ```ts title="src/extension.ts (replace contents)" import * as vscode from 'vscode'; import * as XLSX from 'xlsx'; class ExcelDocument implements vscode.CustomDocument { constructor(public readonly uri: vscode.Uri) { } dispose() { } } class ExcelEditorProvider implements vscode.CustomReadonlyEditorProvider { // 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 data: Uint8Array = await vscode.workspace.fs.readFile(document.uri); const options: XLSX.ParsingOptions = { type: 'array', cellStyles: true, cellDates: true, }; const wb: XLSX.WorkBook = XLSX.read(new Uint8Array(data), options); const htmlTable = XLSX.utils.sheet_to_html(wb.Sheets[wb.SheetNames[0]]); webviewPanel.webview.html = `${htmlTable}`; } } export function activate(context: vscode.ExtensionContext) { const provider = vscode.window.registerCustomEditorProvider( 'excelViewer.spreadsheet', new ExcelEditorProvider(), { webviewOptions: { retainContextWhenHidden: true } } // keep webview state when hidden ); context.subscriptions.push(provider); } export function deactivate() {} ``` 5) Add the highlighted lines to the `contributes` section of `package.json`: ```json title="package.json (add highlighted lines)" "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) In the editor, open the Command Palette (Help > "Show All Commands" from the menu), type `Debug: Start` and select `Debug: Start Debugging`. This will compile and run the extension in a new Extension Development Host window. 7) Drag and drop the `pres.xlsx` test file into the new window. If drag and drop is not available, click "Open..." in the Welcome screen and select the file. A new `pres.xlsx` tab will show the contents of the file. :::info pass When this demo was last tested, the default project assumed VSCode version 1.109.0 or later. Antigravity 1.19.6 is aligned to VSCode 1.107.0. The default extension will not run in Antigravity. This can be fixed by changing the `vscode` field in `package.json`. When this demo was last tested, it was safe to set a minimum version of `^1.100.0`: ```json title="package.json (change highlighted line)" "engines": { // highlight-next-line "vscode": "^1.100.0" } ``` ::: [^1]: See [`Webview API`](https://code.visualstudio.com/api/extension-guides/webview) in the VSCode documentation for more details. [^2]: See [`Custom Editor API`](https://code.visualstudio.com/api/extension-guides/custom-editors) in the VSCode documentation for more details. [^3]: See [`vsce`](https://code.visualstudio.com/api/working-with-extensions/publishing-extension#vsce) in the VSCode documentation for more details. [^4]: See [`Custom Editor`](https://code.visualstudio.com/api/extension-guides/custom-editors#custom-editor) in the VSCode documentation for more details. [^5]: See [`CustomDocument`](https://code.visualstudio.com/api/extension-guides/custom-editors#customdocument) in the VSCode documentation for more details.