---
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!
:::

:::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

- `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.