npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

excel-sync

v0.1.3

Published

Node.js/TypeScript orchestrator for Excel VBA sync via PowerShell bridge

Readme

Excel Sync (Node.js + TypeScript + PowerShell)

Ce projet fournit un point de départ pour synchroniser du VBA Excel avec le file system en gardant les opérations COM Excel côté PowerShell.

Principe

  • Node.js/TypeScript gère l'orchestration:
    • synchronisation initiale Excel <-> vba/ avec detection des ecarts
    • choix interactif de la source de verite en cas de differences
    • watcher bidirectionnel (file system -> Excel et Excel -> file system)
    • polling Excel toutes les 2 secondes
    • resolution de conflits LWW (last write wins), egalite -> file system
    • anti-boucle avec suppression temporaire des evenements rebonds
    • logique métier/comparaison (à enrichir ici)
  • PowerShell gère uniquement Excel COM:
    • connexion à l'instance Excel active
    • lecture des modules VBA (inspect)
    • écriture de code dans un module (import)
    • renvoi de codes d'erreur techniques (sans message métier)
  • Node.js/TypeScript gère l'affichage des erreurs utilisateur

Structure

  • scripts/excel-bridge.ps1: bridge PowerShell (JSON in/out)
  • src/infra/: exécution PowerShell + client bridge
  • src/app/sync/: logique sync par domaine (scan, apply events, sync initiale, utilitaires)
  • src/app/watcher/: helpers runtime du watcher
  • src/app/syncService.ts: facade de re-export pour l'app
  • src/index.ts: point d'entrée

Prérequis

  • Windows + Excel Desktop ouvert avec un classeur actif
  • Option Excel activée:
    • "Accès approuvé au modèle d'objet du projet VBA"
  • Node.js 20+
  • PowerShell (powershell.exe ou pwsh)

Installation

pnpm install

Lancer

Mode dev (sans build):

pnpm run dev

Mode build + exécution:

pnpm run build
pnpm start

Option CLI

Par defaut, le watch est unidirectionnel (file system -> Excel).

Pour activer aussi Excel -> file system (polling Excel), utilisez l'opt-in:

pnpm run dev -- --excel-to-fs

Ou avec le binaire compile:

pnpm start -- --excel-to-fs

Help:

pnpm start -- --help

Utilisation via pnpm dlx

Apres publication NPM:

pnpm dlx excel-sync --help
pnpm dlx excel-sync --excel-to-fs

Vérification TypeScript

pnpm run check

Notes

  • Variable optionnelle: EXCEL_SYNC_PWSH pour forcer le binaire PowerShell.
  • Le watcher traite added/updated/deleted/typeChanged en file system -> Excel, et en Excel -> file system si --excel-to-fs est active.
  • Le watcher est verrouille sur le classeur actif au demarrage (path+name). Si le classeur change, la synchronisation s'arrete automatiquement pour eviter toute ecriture sur un mauvais fichier.
  • Point d'extension recommandé: src/app/syncService.ts pour la future logique de comparaison Excel vs file system.
  • Les fichiers exportes sont ecrits en UTF-8 avec BOM pour une detection fiable dans les editeurs.
  • A l'import, le code est lu en UTF-8 puis valide/converti vers Windows-1252 avant injection dans Excel VBA.
  • Le flux Excel -> file system est desactive par defaut et s'active via --excel-to-fs.

Architecture et Flux de Synchronisation

Cette section explique visuellement comment fonctionne la synchronisation entre Excel et le système de fichiers.

Vue d'ensemble du système

┌─────────────────────────────────────────────────────────────────┐
│                         EXCEL SYNC                              │
│                    (Node.js + TypeScript)                       │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  ┌──────────────┐    ┌──────────────┐    ┌──────────────┐      │
│  │   Watcher    │    │   Initial    │    │   Bridge     │      │
│  │   (chokidar) │    │    Sync      │    │ PowerShell   │      │
│  └──────┬───────┘    └──────┬───────┘    └──────┬───────┘      │
│         │                   │                    │              │
│         │ Événements FS     │ Comparaison      │ Commandes     │
│         │ (add/change/del)  │ (MD5 + date)     │ COM Excel     │
│         ▼                   ▼                    ▼              │
│  ┌──────────────────────────────────────────────────────┐      │
│  │           Gestionnaire de conflits (LWW)             │      │
│  │        (Last Write Wins - égalité → File System)     │      │
│  └──────────────────────────────────────────────────────┘      │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘
                                    │
                                    │ PowerShell Remoting
                                    ▼
┌─────────────────────────────────────────────────────────────────┐
│                        EXCEL (COM API)                          │
│  ┌────────────┐  ┌────────────┐  ┌────────────────────────┐    │
│  │ Classeur   │──│  Modules   │──│  Code VBA              │    │
│  │  Actif     │  │   VBA      │  │  (Standard/Class)      │    │
│  └────────────┘  └────────────┘  └────────────────────────┘    │
└─────────────────────────────────────────────────────────────────┘
                                    │
                                    │ Export/Import
                                    ▼
┌─────────────────────────────────────────────────────────────────┐
│                    SYSTÈME DE FICHIERS                          │
│                    (dossier vba/)                               │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │  Standard.bas    MyClass.cls    Module1.bas             │   │
│  │  (modules standards)    (classes)      (modules...)     │   │
│  └─────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────┘

Synchronisation initiale (au démarrage)

Au lancement du programme, une synchronisation initiale est effectuée pour détecter les écarts entre Excel et le dossier vba/.

        ┌─────────────────┐
        │    DÉMARRAGE    │
        └────────┬────────┘
                 │
                 ▼
┌──────────────────────────────────────────────────────────────┐
│                    SYNCHRONISATION INITIALE                   │
└──────────────────────────────────────────────────────────────┘
                 │
                 ▼
┌──────────────────────────────────────────────────────────────┐
│ ÉTAPE 1: SCAN COMPLET                                        │
│                                                              │
│  ┌──────────────┐          ┌──────────────┐                  │
│  │   EXCEL      │          │  FILE SYSTEM │                  │
│  │              │          │   (vba/)     │                  │
│  │ • Module1    │          │ • Module1.bas│                  │
│  │ • Module2    │          │ • Module2.bas│                  │
│  │ • ClassA     │          │ • ClassA.cls │                  │
│  └──────────────┘          └──────────────┘                  │
└──────────────────────────────────────────────────────────────┘
                 │
                 ▼
┌──────────────────────────────────────────────────────────────┐
│ ÉTAPE 2: COMPARAISON                                         │
│                                                              │
│  Module     │ Excel Hash │ FS Hash    │ Action              │
│  ───────────┼────────────┼────────────┼───────────────────  │
│  Module1    │ ABC123     │ ABC123     │ ✅ Identique         │
│  Module2    │ DEF456     │ DEF456     │ ✅ Identique         │
│  ClassA     │ GHI789     │ ─          │ 📥 Import dans FS    │
│  Module3    │ ─          │ JKL012     │ 📤 Export vers Excel │
│  OldMod     │ MNO345     │ MNO345_old │ ⚠️  Conflit détecté  │
└──────────────────────────────────────────────────────────────┘
                 │
                 ▼
┌──────────────────────────────────────────────────────────────┐
│ ÉTAPE 3: RÉSOLUTION (si conflits)                           │
│                                                              │
│  ⚠️  Conflit détecté sur "OldMod"                            │
│                                                              │
│     ┌──────────────────────────────────────────────────┐    │
│     │ Le module "OldMod" est différent des deux côtés  │    │
│     │                                                  │    │
│     │ Excel: modifié le 28/02/2026 à 10:30             │    │
│     │ Fichier: modifié le 28/02/2026 à 11:45           │    │
│     │                                                  │    │
│     │ Que voulez-vous faire ?                          │    │
│     │                                                  │    │
│     │ [1] Garder la version Excel (→ écraser fichier)  │    │
│     │ [2] Garder la version fichier (→ écraser Excel)  │    │
│     │ [3] Ignorer (ne rien faire)                      │    │
│     └──────────────────────────────────────────────────┘    │
│                                                              │
└──────────────────────────────────────────────────────────────┘
                 │
                 ▼
┌──────────────────────────────────────────────────────────────┐
│ ÉTAPE 4: APPLICATION DES CHANGEMENTS                        │
│                                                              │
│  Excel ───────────────────────► File System                 │
│    • ClassA.cls créé                                        │
│                                                              │
│  File System ─────────────────► Excel                       │
│    • Module3 importé                                        │
│    • OldMod mis à jour (selon choix utilisateur)            │
│                                                              │
│  ✅ Synchronisation initiale terminée !                     │
└──────────────────────────────────────────────────────────────┘

Mode unidirectionnel (par défaut): File System → Excel

Par défaut, seuls les changements du système de fichiers vers Excel sont synchronisés.

SYSTÈME DE FICHIERS (vba/)                    EXCEL
     │                                            │
     │   1. Création d'un fichier .bas/.cls      │
     │      └── NouveauModule.bas                │
     │────────────────────────────────────────────►│
     │                                            │
     │      2. Import automatique dans Excel     │
     │         → Module créé avec le code        │
     │                                            ▼
     │                                    ┌───────────────┐
     │                                    │ NouveauModule │
     │                                    │   (dans VBA)  │
     │                                    └───────────────┘
     │
     │   3. Modification du fichier
     │      └── Contenu changé
     │────────────────────────────────────────────►
     │
     │      4. Excel mis à jour automatiquement
     │         → Code remplacé
     │                                           ▼
     │                                    ┌───────────────┐
     │                                    │ Code mis à    │
     │                                    │ jour dans     │
     │                                    │ le module     │
     │                                    └───────────────┘
     │
     │   5. Suppression du fichier
     │      └── Fichier supprimé
     │────────────────────────────────────────────►
     │
     │      6. Module supprimé dans Excel
     │                                           ▼
     │                                    ┌───────────────┐
     │                                    │   Module      │
     │                                    │  supprimé ❌  │
     │                                    └───────────────┘
     │
     ▼
 ⚠️ IMPORTANT: Les modifications faites DIRECTEMENT dans Excel
    ne sont PAS synchronisées vers le système de fichiers
    en mode unidirectionnel !

Mode bidirectionnel: File System ↔ Excel (--excel-to-fs)

Avec le flag --excel-to-fs, la synchronisation fonctionne dans les deux sens.

                         ┌─────────────────────────────┐
                         │      SYNCHRONISATION        │
                         │      BIDIRECTIONNELLE       │
                         │      (--excel-to-fs)        │
                         └─────────────────────────────┘
                                          │
           ┌──────────────────────────────┼──────────────────────────────┐
           │                              │                              │
           ▼                              ▼                              ▼
┌─────────────────────┐      ┌─────────────────────┐      ┌─────────────────────┐
│  FILE SYSTEM → EXCEL│      │   GESTIONNAIRE DE   │      │  EXCEL → FILE SYSTEM│
│   (événements FS)   │      │     CONFLITS LWW    │      │   (polling 2s)      │
└─────────────────────┘      │  (Last Write Wins)  │      └─────────────────────┘
           │                  └─────────────────────┘               │
           │                            │                           │
           ▼                            ▼                           ▼
    ┌──────────────┐            ┌──────────────┐            ┌──────────────┐
    │ add → import │            │              │            │ export vers  │
    │ change→update│◄──────────►│  Résolution  │◄──────────►│ fichier .bas │
    │ unlink→delete│            │   conflits   │            │ ou .cls      │
    └──────────────┘            └──────────────┘            └──────────────┘

Flux détaillé du mode bidirectionnel

EXCEL (VBA Editor)                    SYSTÈME DE FICHIERS (vba/)
        │                                         │
        │  1. Vous modifiez du code               │
        │     dans Excel                          │
        │                                         │
        ▼                                         │
┌───────────────┐                                 │
│ Code changé   │                                 │
│ dans Module1  │                                 │
└───────┬───────┘                                 │
        │                                         │
        │  2. Polling Excel toutes les 2s         │
        │     détecte le changement               │
        │                                         │
        └────────────────────────────────────────►│
                                                  │
                                                  │ 3. Comparaison des timestamps
                                                  │    Excel: 11:30:15
                                                  │    Fichier: 11:30:00
                                                  │
                                                  │ 4. Excel est PLUS RÉCENT
                                                  │    → Export vers fichier
                                                  │
                                                  ▼
                                         ┌────────────────┐
                                         │ Module1.bas    │
                                         │ mis à jour     │
                                         │ (code Excel)   │
                                         └────────────────┘

────────────────────────────────────────────────────────────────────────────

EXCEL (VBA Editor)                    SYSTÈME DE FICHIERS (vscode/)
        │                                         │
        │                                         │  1. Vous modifiez le fichier
        │                                         │     dans VS Code
        │                                         │
        │                                         ▼
        │                                ┌────────────────┐
        │                                │ Module1.bas    │
        │                                │ modifié        │
        │                                └───────┬────────┘
        │                                        │
        │  2. Événement fichier détecté          │
        │◄───────────────────────────────────────┘
        │
        │ 3. Comparaison des timestamps
        │    Fichier: 11:35:20
        │    Excel: 11:30:15
        │
        │ 4. Fichier est PLUS RÉCENT
        │    → Import dans Excel
        ▼
┌────────────────┐
│ Module1        │
│ mis à jour     │
│ (code fichier) │
└────────────────┘

Gestion des conflits (Last Write Wins)

Quand une modification est détectée des deux côtés simultanément, le système utilise l'algorithme LWW (Last Write Wins).

                    CONFLIT DÉTECTÉ
                          │
                          ▼
            ┌─────────────────────────────┐
            │   Comparaison timestamps    │
            │   (dernière modification)   │
            └──────────────┬──────────────┘
                           │
            ┌──────────────┼──────────────┐
            │                             │
            ▼                             ▼
   ┌─────────────────┐           ┌─────────────────┐
   │ Excel PLUS RÉCENT│           │ Fichier PLUS    │
   │  (date_excel >   │           │ RÉCENT          │
   │   date_fichier)  │           │  (date_fichier > │
   └────────┬────────┘           │   date_excel)   │
            │                     └────────┬────────┘
            │                             │
            ▼                             ▼
   ┌─────────────────┐           ┌─────────────────┐
   │  Excel gagne    │           │  Fichier gagne  │
   │  → Export vers  │           │  → Import dans  │
   │     fichier     │           │     Excel       │
   └─────────────────┘           └─────────────────┘
            │                             │
            └──────────────┬──────────────┘
                           │
                           ▼
            ┌─────────────────────────────┐
            │   ÉGALITÉ (dates identiques) │
            │                             │
            │   → File System gagne       │
            │   (valeur par défaut)       │
            └─────────────────────────────┘

Tableau récapitulatif des actions

| Événement | Source | Direction | Action dans l'autre système | | -------------------------------- | ----------- | ------------ | ------------------------------------------------- | | Création fichier (.bas/.cls) | File System | FS → Excel | Import dans Excel (nouveau module VBA) | | Modification fichier | File System | FS → Excel | Mise à jour du code dans le module Excel existant | | Suppression fichier | File System | FS → Excel | Suppression du module VBA dans Excel | | Création module dans VBA | Excel | Excel → FS* | Export vers nouveau fichier .bas/.cls | | Modification code dans VBA | Excel | Excel → FS* | Mise à jour du fichier existant | | Suppression module dans VBA | Excel | Excel → FS* | Suppression du fichier |

Note: Le flux Excel → File System (marqué *) nécessite le flag --excel-to-fs

Anti-boucle et protection

Pour éviter les boucles infinies de synchronisation, le système utilise un mécanisme de suppression temporaire des événements rebonds.

Sans protection (BOUCLE INFINIE):
─────────────────────────────────

1. Vous modifiez Module1.bas dans VS Code
   │
   ▼
2. Fichier changé → Import dans Excel
   │
   ▼
3. Excel modifié → Export vers fichier
   │
   ▼
4. Fichier changé → Import dans Excel
   │
   ▼
5. Excel modifié → Export vers fichier
   │
   ▼
   ... ET ÇA CONTINUE À L'INFINI !


Avec protection (ANTI-BOUCLE):
──────────────────────────────

1. Vous modifiez Module1.bas dans VS Code
   │
   ▼
2. Fichier changé → Import dans Excel
   │
   ├──► 🚫 Marque "ignoreNextExcelChange"
   │
   ▼
3. Excel modifié → VÉRIFICATION
   │
   ├──► ✅ "ignoreNextExcelChange" est actif
   │     → Ne pas propager vers fichier
   │     → 🗑️ Supprime le flag
   │
   ▼
4. ✅ Pas de boucle ! Modification terminée.

Sécurité: Verrouillage sur le classeur actif

Le système est verrouillé sur le classeur actif au démarrage pour éviter les erreurs.

Démarrage
   │
   ▼
┌────────────────────────────────────┐
│ Capturer ID du classeur actif      │
│ (nom + chemin complet)             │
└──────────────┬─────────────────────┘
               │
               ▼
┌────────────────────────────────────┐
│ Watcher démarré                    │
└──────────────┬─────────────────────┘
               │
               ▼
       Événement détecté
               │
               ▼
      ┌────────────────┐
      │ Classeur actif │
      │ est-il le même │
      │ qu'au démarrage│
      └───────┬────────┘
              │
     ┌────────┴────────┐
     │                 │
     ▼                 ▼
┌──────────┐    ┌──────────────┐
│   OUI    │    │     NON      │
│          │    │              │
│ Traiter  │    │ 🛑 ARRÊT     │
│ l'event  │    │ IMMÉDIAT     │
│          │    │              │
│          │    │ Protection   │
│          │    │ contre       │
│          │    │ écriture sur │
│          │    │ mauvais      │
│          │    │ fichier !    │
└──────────┘    └──────────────┘

Résumé visuel du flux complet

┌────────────────────────────────────────────────────────────────────────────┐
│                         FLUX COMPLET DU PROGRAMME                          │
└────────────────────────────────────────────────────────────────────────────┘

    ┌──────────────┐
    │   LANCEMENT  │
    └──────┬───────┘
           │
           ▼
┌──────────────────────┐
│ Synchronisation      │
│ initiale             │
│ (scan + résolution)  │
└──────────┬───────────┘
           │
           ▼
    ┌──────────────┐
    │ Choix mode   │
    └──────┬───────┘
           │
    ┌──────┴──────┐
    │             │
    ▼             ▼
┌────────┐  ┌─────────────┐
│ Mode   │  │ Mode        │
│ Uni    │  │ Bidirection │
│(défaut)│  │(--excel-to- │
│        │  │  fs)        │
└───┬────┘  └──────┬──────┘
    │              │
    │    ┌─────────┘
    │    │
    ▼    ▼
┌──────────────────────────────────────────────────────────────┐
│                    WATCHER ACTIF                             │
│                                                              │
│   ┌─────────────────┐          ┌──────────────────────────┐ │
│   │ File System     │          │ Excel (si --excel-to-fs) │ │
│   │ • add file      │          │ • Polling toutes les 2s  │ │
│   │ • change file   │          │ • Détection changements  │ │
│   │ • delete file   │          │   code VBA               │ │
│   └────────┬────────┘          └────────────┬─────────────┘ │
│            │                                │               │
│            ▼                                ▼               │
│   ┌──────────────────────────────────────────────────┐     │
│   │          COMPARAISON + RÉSOLUTION LWW            │     │
│   │     (Last Write Wins, égalité → File System)     │     │
│   └──────────────────────────────────────────────────┘     │
│                           │                                 │
│                           ▼                                 │
│   ┌──────────────────────────────────────────────────┐     │
│   │              SYNCHRONISATION CIBLE               │     │
│   │                                                  │     │
│   │   File System ───────────► Excel (import)        │     │
│   │   Excel ─────────────────► File System (export)  │     │
│   │                                                  │     │
│   └──────────────────────────────────────────────────┘     │
│                                                              │
└──────────────────────────────────────────────────────────────┘
           │
           │ Ctrl+C ou erreur
           ▼
    ┌──────────────┐
    │   ARRÊT      │
    └──────────────┘

Exemple de session typique

$ pnpm run dev -- --excel-to-fs

🚀 Démarrage Excel Sync (mode bidirectionnel)
═══════════════════════════════════════════════════════════════

📊 Étape 1/3: Connexion à Excel...
   ✅ Connecté au classeur: MonProjet.xlsm

🔍 Étape 2/3: Scan initial...
   Excel: 3 modules trouvés
   Fichiers: 3 fichiers trouvés dans vba/

🔄 Étape 3/3: Comparaison...
   ✅ Module1: identique
   ✅ Module2: identique
   ⚠️  ClassA: différence détectée

┌────────────────────────────────────────────────────────────┐
│ Conflit détecté sur "ClassA"                                │
│                                                            │
│ Excel:  modifié le 28/02/2026 10:30:15                    │
│ Fichier: modifié le 28/02/2026 10:35:42                   │
│                                                            │
│ [1] Garder Excel    [2] Garder fichier    [3] Ignorer      │
└────────────────────────────────────────────────────────────┘
➤ Choix: 2
   ✅ ClassA: synchronisé (fichier → Excel)

✨ Synchronisation initiale terminée !

👁️  Watcher démarré (surveillance active):
   • File System → Excel: ACTIVÉ
   • Excel → File System: ACTIVÉ (--excel-to-fs)

───────────────────────────────────────────────────────────────

📝 11:45:23 - [FS → Excel] Module1.bas modifié → Excel mis à jour
📝 11:47:15 - [Excel → FS] ClassA.cls modifié dans VBA → Fichier exporté
📝 11:50:01 - [FS → Excel] NouveauModule.bas créé → Import dans Excel

───────────────────────────────────────────────────────────────

👋 Arrêt demandé (Ctrl+C)
🛑 Watcher arrêté proprement