diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000..34a59d0
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,17 @@
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "Run Extension",
+ "type": "extensionHost",
+ "request": "launch",
+ "args": [
+ "--extensionDevelopmentPath=${workspaceFolder}"
+ ],
+ "outFiles": [
+ "${workspaceFolder}/dist/**/*.js"
+ ],
+ "preLaunchTask": "${defaultBuildTask}"
+ }
+ ]
+}
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
new file mode 100644
index 0000000..34edf97
--- /dev/null
+++ b/.vscode/tasks.json
@@ -0,0 +1,18 @@
+{
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "type": "npm",
+ "script": "watch",
+ "problemMatcher": "$tsc-watch",
+ "isBackground": true,
+ "presentation": {
+ "reveal": "never"
+ },
+ "group": {
+ "kind": "build",
+ "isDefault": true
+ }
+ }
+ ]
+}
diff --git a/.vscodeignore b/.vscodeignore
index d255964..5dd7b05 100644
--- a/.vscodeignore
+++ b/.vscodeignore
@@ -12,3 +12,4 @@ vsc-extension-quickstart.md
**/*.map
**/*.ts
**/.vscode-test.*
+*.vsix
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 336c6c0..17444d5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,8 +2,17 @@
All notable changes to the "sheetjs-demo" extension will be documented in this file.
-Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file.
+## [0.1.0]
-## [Unreleased]
+- Added commands to disable/enable viewer for specific file extensions
+- Added right-click context menu options for spreadsheet files
+- Automatic file reloading when files are edited externally
+- Command palette integration for quick toggling
-- Initial release
\ No newline at end of file
+## [0.0.9]
+
+- View spreadsheets directly in VSCode
+- Support for 30+ file formats (XLSX, XLS, CSV, ODS, and more)
+- Multi-level caching for workbooks and sheets
+- On-demand sheet loading
+- Pagination for large files
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
index 5723c45..ffaa914 100644
--- a/LICENSE
+++ b/LICENSE
@@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
- Copyright (C) 2014-present SheetJS LLC
+ Copyright (C) 2025-present Asadbek Karimov
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/README.md b/README.md
index 9cda12f..852df6e 100644
--- a/README.md
+++ b/README.md
@@ -17,19 +17,12 @@ Powered by [SheetJS](http://sheetjs.com/) a powerful VSCode extension that lets
## Key Features
-The extension uses sophisticated optimization techniques to ensure smooth performance:
-- **Multi-level Caching**
- - Workbook cache prevents redundant parsing of the same files
- - Sheet HTML cache eliminates regeneration of previously viewed sheets
-- **Smart Loading Strategy**
- - First sheet loads immediately for instant feedback
- - Additional sheets load on-demand when selected
- - Preserved webview context maintains your state even when hidden
-- **Responsive Interface**
- - Immediate loading spinner provides visual feedback
- - Sheet-switching indicators keep you informed
- - Persistent state across view changes
+- Caches workbooks and sheets to avoid re-parsing files
+- Loads sheets on-demand when switching between them
+- Automatically reloads when files are edited externally
+- Handles mega large files with pagination
+- Toggle viewer on/off for specific file extensions via command palette or context menu
## Supported File Formats
@@ -65,11 +58,41 @@ The extension uses sophisticated optimization techniques to ensure smooth perfor
| *.wb3 |
| *.qpw |
| *.xlr |
-| *.eth |
+| *.eth |
+
+## Usage
+
+### Disabling/Enabling the Viewer
+
+You can easily disable the SheetJS viewer for specific file extensions:
+
+
+
+
+**Command Palette** (Ctrl/Cmd+Shift+P):
+- `SheetJS: Disable Viewer for Current File Extension` - Switches to default text editor for that extension
+- `SheetJS: Enable Viewer for Current File Extension` - Re-enables the viewer
+
+**Context Menu**: Right-click any spreadsheet file in the Explorer to access the same commands.
+
+**Built-in VSCode**: Right-click any file and select "Open With..." to choose between SheetJS Viewer and other editors.
## Getting Started
Want to integrate SheetJS in your own VSCode extension? Check out our [detailed tutorial](https://docs.sheetjs.com/docs/) to learn how to implement these capabilities in your projects.
+## Development
+
+To run the extension in development mode, install dependencies with `pnpm install` and press F5 in VSCode. This opens a new Extension Development Host window where you can test the extension by opening any spreadsheet file.
+
+
+Build for production with `pnpm run package`.
+
+## Publishing
+```bash
+npx vsce login foo
+npx vsce publish
+```
+
## Learn More
For more information on using this extension and integrating SheetJS capabilities in your own projects, visit our [documentation](https://docs.sheetjs.com/docs/).
diff --git a/asset/toggle_context_menu.png b/asset/toggle_context_menu.png
new file mode 100644
index 0000000..df47e0e
Binary files /dev/null and b/asset/toggle_context_menu.png differ
diff --git a/asset/toggle_ext_via_palette.png b/asset/toggle_ext_via_palette.png
new file mode 100644
index 0000000..95dacad
Binary files /dev/null and b/asset/toggle_ext_via_palette.png differ
diff --git a/package.json b/package.json
index e05c4af..df84984 100644
--- a/package.json
+++ b/package.json
@@ -5,7 +5,7 @@
"author": "Asadbek Karimov ",
"publisher": "asadbek",
"icon": "img/logo.png",
- "version": "0.0.8",
+ "version": "0.1.0",
"license": "Apache-2.0",
"bugs": {
"url": "https://git.sheetjs.com/asadbek064/sheetjs-vscode-extension/issues"
@@ -30,6 +30,47 @@
"activationEvents": [],
"main": "./dist/extension.js",
"contributes": {
+ "commands": [
+ {
+ "command": "sheetjs.disableForExtension",
+ "title": "SheetJS: Disable Viewer for Current File Extension"
+ },
+ {
+ "command": "sheetjs.enableForExtension",
+ "title": "SheetJS: Enable Viewer for Current File Extension"
+ },
+ {
+ "command": "sheetjs.openWithViewer",
+ "title": "SheetJS: Open with Spreadsheet Viewer"
+ }
+ ],
+ "menus": {
+ "commandPalette": [
+ {
+ "command": "sheetjs.disableForExtension",
+ "when": "editorIsOpen"
+ },
+ {
+ "command": "sheetjs.enableForExtension",
+ "when": "editorIsOpen"
+ },
+ {
+ "command": "sheetjs.openWithViewer"
+ }
+ ],
+ "explorer/context": [
+ {
+ "command": "sheetjs.disableForExtension",
+ "group": "2_workspace",
+ "when": "resourceExtname =~ /\\.(xlsx|xls|csv|ods|xlsm|xlsb|numbers)$/"
+ },
+ {
+ "command": "sheetjs.enableForExtension",
+ "group": "2_workspace",
+ "when": "resourceExtname =~ /\\.(xlsx|xls|csv|ods|xlsm|xlsb|numbers)$/"
+ }
+ ]
+ },
"customEditors": [
{
"viewType": "excelViewer.spreadsheet",
diff --git a/src/excelEditorProvider.ts b/src/excelEditorProvider.ts
index e94ba04..2c81a6d 100644
--- a/src/excelEditorProvider.ts
+++ b/src/excelEditorProvider.ts
@@ -7,7 +7,9 @@ import { WorkbookCache } from './cacheManagement/workbookCache';
export class ExcelEditorProvider implements vscode.CustomReadonlyEditorProvider {
private cache: WorkbookCache;
-
+ private fileWatchers: Map = new Map();
+ private webviewPanels: Map = new Map();
+
public static register(context: vscode.ExtensionContext): vscode.Disposable {
return vscode.window.registerCustomEditorProvider(
'excelViewer.spreadsheet',
@@ -30,6 +32,45 @@ export class ExcelEditorProvider implements vscode.CustomReadonlyEditorProvider<
webviewPanel.webview.options = { enableScripts: true };
+ // store the webview panel for this document
+ const uriKey = document.uri.toString();
+ this.webviewPanels.set(uriKey, webviewPanel);
+
+ // setup file watcher for changes to this specific file
+ const watcher = vscode.workspace.createFileSystemWatcher(
+ document.uri.fsPath
+ );
+
+ watcher.onDidChange(async () => {
+ console.log(`File changed: ${document.uri.fsPath}, reloading...`);
+
+ // clear the cache for this file
+ this.cache.clearCachesForUri(document.uri.toString());
+
+ // reload the file
+ this.setLoadingView(webviewPanel);
+ await new Promise(resolve => setTimeout(resolve, 50));
+
+ try {
+ await this.processExcelFile(document, webviewPanel);
+ } catch (error) {
+ console.error('Error reloading file:', error);
+ this.setErrorView(webviewPanel, error);
+ }
+ });
+
+ this.fileWatchers.set(uriKey, watcher);
+
+ // clean up when the panel is disposed
+ webviewPanel.onDidDispose(() => {
+ this.webviewPanels.delete(uriKey);
+ const watcher = this.fileWatchers.get(uriKey);
+ if (watcher) {
+ watcher.dispose();
+ this.fileWatchers.delete(uriKey);
+ }
+ });
+
this.setLoadingView(webviewPanel);
// small timeout to ensure the loading view is rendered before heavy processing begins
diff --git a/src/extension.ts b/src/extension.ts
index de3261e..2e0deeb 100644
--- a/src/extension.ts
+++ b/src/extension.ts
@@ -3,10 +3,124 @@ import { ExcelEditorProvider } from './excelEditorProvider';
export function activate(context: vscode.ExtensionContext) {
console.log('SheetJS Spreadsheet Viewer extension activating...');
-
+
const provider = ExcelEditorProvider.register(context);
context.subscriptions.push(provider);
-
+
+ // Command to disable viewer for current file extension
+ const disableCommand = vscode.commands.registerCommand('sheetjs.disableForExtension', async (uri?: vscode.Uri) => {
+ // Try to get URI from parameter, active text editor, or prompt user
+ if (!uri) {
+ const activeTab = vscode.window.tabGroups.activeTabGroup.activeTab;
+ if (activeTab?.label) {
+ // Try to find the file by label in workspace
+ const files = await vscode.workspace.findFiles(`**/${activeTab.label}`);
+ if (files.length > 0) {
+ uri = files[0];
+ }
+ }
+ }
+
+ if (!uri) {
+ vscode.window.showWarningMessage('No file is currently open or could not determine file path');
+ return;
+ }
+
+ const ext = uri.fsPath.split('.').pop()?.toLowerCase();
+ if (!ext) {
+ vscode.window.showWarningMessage('Could not determine file extension');
+ return;
+ }
+
+ // Update workbench.editorAssociations to use default editor
+ const workbenchConfig = vscode.workspace.getConfiguration('workbench');
+ const associations = workbenchConfig.get>('editorAssociations') || {};
+
+ if (associations[`*.${ext}`] === 'default') {
+ vscode.window.showInformationMessage(`SheetJS viewer is already disabled for .${ext} files`);
+ return;
+ }
+
+ associations[`*.${ext}`] = 'default';
+ await workbenchConfig.update('editorAssociations', associations, vscode.ConfigurationTarget.Global);
+
+ // Close the current tab and reopen with default editor
+ await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
+ await vscode.commands.executeCommand('vscode.open', uri);
+
+ vscode.window.showInformationMessage(`SheetJS viewer disabled for .${ext} files`);
+ });
+
+ // Command to enable viewer for current file extension
+ const enableCommand = vscode.commands.registerCommand('sheetjs.enableForExtension', async (uri?: vscode.Uri) => {
+ // Try to get URI from parameter or active tab
+ if (!uri) {
+ uri = vscode.window.activeTextEditor?.document.uri;
+ if (!uri) {
+ const activeTab = vscode.window.tabGroups.activeTabGroup.activeTab;
+ if (activeTab?.label) {
+ const files = await vscode.workspace.findFiles(`**/${activeTab.label}`);
+ if (files.length > 0) {
+ uri = files[0];
+ }
+ }
+ }
+ }
+
+ if (!uri) {
+ vscode.window.showWarningMessage('No file is currently open or could not determine file path');
+ return;
+ }
+
+ const ext = uri.fsPath.split('.').pop()?.toLowerCase();
+ if (!ext) {
+ vscode.window.showWarningMessage('Could not determine file extension');
+ return;
+ }
+
+ // Remove from workbench.editorAssociations
+ const workbenchConfig = vscode.workspace.getConfiguration('workbench');
+ const associations = workbenchConfig.get>('editorAssociations') || {};
+
+ // If not set to 'default', it's already enabled
+ if (associations[`*.${ext}`] !== 'default') {
+ vscode.window.showInformationMessage(`SheetJS viewer is already enabled for .${ext} files`);
+ return;
+ }
+
+ // Create a new object without the extension (to avoid proxy issues)
+ const newAssociations: Record = {};
+ for (const key in associations) {
+ if (key !== `*.${ext}`) {
+ newAssociations[key] = associations[key];
+ }
+ }
+ await workbenchConfig.update('editorAssociations', newAssociations, vscode.ConfigurationTarget.Global);
+
+ // Close the current tab and reopen with SheetJS viewer
+ await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
+ await vscode.commands.executeCommand('vscode.openWith', uri, 'excelViewer.spreadsheet');
+
+ vscode.window.showInformationMessage(`SheetJS viewer enabled for .${ext} files`);
+ });
+
+ // Command to open with viewer
+ const openCommand = vscode.commands.registerCommand('sheetjs.openWithViewer', async () => {
+ const uris = await vscode.window.showOpenDialog({
+ canSelectMany: false,
+ openLabel: 'Open with SheetJS Viewer',
+ filters: {
+ 'Spreadsheets': ['xlsx', 'xls', 'csv', 'ods', 'xlsm', 'xlsb', 'numbers']
+ }
+ });
+
+ if (uris && uris[0]) {
+ await vscode.commands.executeCommand('vscode.openWith', uris[0], 'excelViewer.spreadsheet');
+ }
+ });
+
+ context.subscriptions.push(disableCommand, enableCommand, openCommand);
+
console.log('SheetJS Spreadsheet Viewer extension is now active');
vscode.window.showInformationMessage('SheetJS Spreadsheet Viewer is ready!');
}