web-dev-qa-db-fra.com

Meilleure façon de contrôler les versions pour MS Excel

Quels systèmes de contrôle de version avez-vous utilisés avec MS Excel (2003/2007)? Que recommanderiez-vous et pourquoi? Quelles limitations avez-vous trouvées avec votre système de contrôle de version le mieux coté?

Pour mettre cela en perspective, voici quelques cas d'utilisation:

  1. contrôle de version pour les modules VBA 
  2. plusieurs personnes travaillent sur une feuille de calcul Excel et peuvent éventuellement modifier la même feuille de calcul, qu’elles souhaitent fusionner et intégrer. Cette feuille de calcul peut contenir des formules, des données, des graphiques, etc.
  3. les utilisateurs ne sont pas trop techniques et le moins de systèmes de contrôle de version utilisés le mieux
  4. La contrainte d'espace est une considération. Idéalement, seules les modifications incrémentielles sont enregistrées plutôt que la totalité de la feuille de calcul Excel. 
156
TheObserver

Je viens de mettre en place une feuille de calcul utilisant Bazaar, avec archivage/départ manuel via TortiseBZR. Étant donné que le sujet m'a aidé avec la partie de sauvegarde, je voulais poster ma solution ici.

La solution pour moi était de créer un tableur qui exporte tous les modules lors de la sauvegarde, puis supprime et réimporte les modules en cours. Oui, cela pourrait être potentiellement dangereux pour la conversion de feuilles de calcul existantes.

Cela me permet d’éditer les macros dans les modules via Emacs (oui, emacs) ou nativement dans Excel et de valider mon référentiel BZR après des modifications majeures. Comme tous les modules sont des fichiers texte, les commandes standard de style diff de BZR fonctionnent pour mes sources, à l'exception du fichier Excel lui-même.

J'ai configuré un répertoire pour mon référentiel BZR, X:\Data\MySheet. MySheet.xls et un fichier .vba pour chacun de mes modules (c'est-à-dire: Module1Macros) figurent dans le référentiel. Dans ma feuille de calcul, j'ai ajouté un module exempt du cycle d'exportation/importation appelé "VersionControl". Chaque module à exporter et à réimporter doit se terminer par "Macros".

Contenu du module "VersionControl":

Sub SaveCodeModules()

'This code Exports all VBA modules
Dim i%, sName$

With ThisWorkbook.VBProject
    For i% = 1 To .VBComponents.Count
        If .VBComponents(i%).CodeModule.CountOfLines > 0 Then
            sName$ = .VBComponents(i%).CodeModule.Name
            .VBComponents(i%).Export "X:\Tools\MyExcelMacros\" & sName$ & ".vba"
        End If
    Next i
End With

End Sub

Sub ImportCodeModules()

With ThisWorkbook.VBProject
    For i% = 1 To .VBComponents.Count

        ModuleName = .VBComponents(i%).CodeModule.Name

        If ModuleName <> "VersionControl" Then
            If Right(ModuleName, 6) = "Macros" Then
                .VBComponents.Remove .VBComponents(ModuleName)
                .VBComponents.Import "X:\Data\MySheet\" & ModuleName & ".vba"
           End If
        End If
    Next i
End With

End Sub

Ensuite, nous devons configurer les crochets d’événement pour open/save afin d’exécuter ces macros. Dans la visionneuse de code, cliquez avec le bouton droit de la souris sur "ThisWorkbook" et sélectionnez "Afficher le code". Vous devrez peut-être dérouler la zone de sélection en haut de la fenêtre de code pour passer de la vue "(Général)" à la vue "Classeur".

Contenu de la vue "Cahier":

Private Sub Workbook_Open()

ImportCodeModules

End Sub

Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)

SaveCodeModules

End Sub

Je vais m'installer dans ce flux de travail au cours des prochaines semaines, et je posterai si j'ai des problèmes.

Merci de partager le code VBComponent!

63
Demosthenex

TortoiseSVN est un client Windows étonnamment bon pour le système de contrôle de version Subversion. Une caractéristique que je viens de découvrir, c'est que lorsque vous cliquez pour obtenir un diff entre les versions d'un fichier Excel, les deux versions sont ouvertes dans Excel et mettent en surbrillance (en rouge) les cellules modifiées. Cela se fait par la magie d'un script vbs, décrit ici .

Vous pouvez trouver cela utile même si vous n'utilisez PAS TortoiseSVN.

39
mcherm

Cela dépend si vous parlez de données ou du code contenu dans une feuille de calcul. Bien que je n'aime pas vraiment Visual Sourcesafe de Microsoft et que je ne le recommande pas normalement, il s'intègre facilement à Access et à Excel et permet le contrôle de source des modules.

[En fait, l'intégration avec Access inclut les requêtes, les rapports et les modules sous forme d'objets individuels pouvant être versionnés]

Le lien MSDN est ici .

8
Mitch Wheat

Permettez-moi de résumer ce que vous souhaitez contrôler par version et pourquoi:

  1. Quoi:

    • Code (VBA)
    • Feuilles de calcul (formules)
    • Feuilles de calcul (valeurs)
    • Graphiques
    • ...
  2. Pourquoi: 

    • Journal d'audit
    • Collaboration
    • Comparaison de version ("diffing")
    • Fusion

Comme d'autres l'ont signalé ici, plusieurs solutions s'ajoutent aux systèmes de contrôle de version existants, tels que:

  • Git
  • Mercuriel
  • Subversion
  • Bazar

Si votre seul souci est le code VBA de vos classeurs, l'approche proposée par Demosthenex ou VbaGit ( https://github.com/brucemcpherson/VbaGit ) fonctionne très bien et est relativement simple à mettre en œuvre. Les avantages sont que vous pouvez compter sur des systèmes de contrôle de version éprouvés et en choisir un en fonction de vos besoins (consultez https://help.github.com/articles/what-are-the-differences-between-svn -and-git/ pour une brève comparaison entre Git et Subversion).

Si vous vous inquiétez non seulement du code mais aussi des données de vos feuilles (valeurs "codées en dur" et résultats de formules), vous pouvez utiliser une stratégie similaire pour cela: Sérialiser le contenu de vos feuilles dans un format de texte (via Range.Value) et utilisez un système de contrôle de version existant. Voici un très bon article de blog à ce sujet: https://wiki.ucl.ac.uk/display/~ucftpw2/2013/10/18/Using+git+for+version+control+of+spreadsheet+models+- + partie + 1 + de + 3

Cependant, la comparaison de feuilles de calcul est un problème algorithmique non trivial. Il existe quelques outils, tels que Spreadsheet Compare ( https://support.office.com/en-us/article/Overview-of-Spreadsheet-Compare-13fafa61-62aa-451b-8674-242ce5f2c986 ), Exceldiff ( http://exceldiff.arstdesign.com/ ) et DiffEngineX ( https://www.florencesoft.com/compare-Excel-workbooks-differences.html ). C’est un autre défi d’intégrer ces comparaisons à un système de contrôle de version comme Git.

Enfin, vous devez choisir un flux de travail qui répond à vos besoins. Pour un flux de production Git for Excel simple et personnalisé, consultez https://www.xltrail.com/blog/git-workflow-for-Excel .

7
Bjoern Stiel

Je ne suis pas au courant d'un outil qui fait cela bien mais j'ai vu une variété de solutions maison. Leur dénominateur commun est de minimiser les données binaires sous contrôle de version et de maximiser les données textuelles afin de tirer parti de la puissance des systèmes scc conventionnels. Pour faire ça:

  • Traitez le classeur comme n'importe quelle autre application. Logique, configuration et données séparées.
  • Séparez le code du classeur.
  • Construisez l'interface utilisateur par programme. 
  • Ecrivez un script de construction pour reconstruire le classeur.
7
Hobbo

Travailler sur @Demosthenex, @Tmdean et @Jon Crowell, de précieux commentaires! (+1 eux)

J'enregistre les fichiers de module dans git\dir à côté de l'emplacement du classeur. Changer cela à votre goût.

Ceci ne suivra PAS les modifications apportées au code du classeur. C'est donc à vous de les synchroniser.

Sub SaveCodeModules()

'This code Exports all VBA modules
Dim i As Integer, name As String

With ThisWorkbook.VBProject
    For i = .VBComponents.count To 1 Step -1
        If .VBComponents(i).Type <> vbext_ct_Document Then
            If .VBComponents(i).CodeModule.CountOfLines > 0 Then
                name = .VBComponents(i).CodeModule.name
                .VBComponents(i).Export Application.ThisWorkbook.Path & _
                                            "\git\" & name & ".vba"
            End If
        End If
    Next i
End With

End Sub

Sub ImportCodeModules()
Dim i As Integer
Dim ModuleName As String

With ThisWorkbook.VBProject
    For i = .VBComponents.count To 1 Step -1

        ModuleName = .VBComponents(i).CodeModule.name

        If ModuleName <> "VersionControl" Then
            If .VBComponents(i).Type <> vbext_ct_Document Then
                .VBComponents.Remove .VBComponents(ModuleName)
                .VBComponents.Import Application.ThisWorkbook.Path & _
                                         "\git\" & ModuleName & ".vba"
            End If
        End If
    Next i
End With

End Sub

Et ensuite dans le module Classeur:

Private Sub Workbook_Open()

    ImportCodeModules

End Sub

Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)

    SaveCodeModules

End Sub
6
przemo_li

Pour aller plus loin dans la réponse de @Demosthenex, si vous souhaitez également garder une trace du code dans vos objets Microsoft Excel et UserForm, vous devez être un peu délicat.

D'abord, j'ai modifié ma fonction SaveCodeModules() pour prendre en compte les différents types de code que je compte exporter:

Sub SaveCodeModules(dir As String)

'This code Exports all VBA modules
Dim moduleName As String
Dim vbaType As Integer

With ThisWorkbook.VBProject
    For i = 1 To .VBComponents.count
        If .VBComponents(i).CodeModule.CountOfLines > 0 Then
            moduleName = .VBComponents(i).CodeModule.Name
            vbaType = .VBComponents(i).Type

            If vbaType = 1 Then
                .VBComponents(i).Export dir & moduleName & ".vba"
            ElseIf vbaType = 3 Then
                .VBComponents(i).Export dir & moduleName & ".frm"
            ElseIf vbaType = 100 Then
                .VBComponents(i).Export dir & moduleName & ".cls"
            End If

        End If
    Next i
End With

End Sub

Les UserForms peuvent être exportés et importés comme le code VBA. La seule différence est que deux fichiers seront créés lors de l'exportation d'un formulaire (vous obtiendrez un fichier .frm et un fichier .frx pour chaque formulaire UserForm). L’un d’eux contient le logiciel que vous avez écrit et l’autre est un fichier binaire qui (je suis à peu près sûr) définit la présentation du formulaire.

Les objets Microsoft Excel (MEO) (signifiant Sheet1, Sheet2, ThisWorkbook etc.) peuvent être exportés sous la forme d'un fichier .cls. Toutefois, lorsque vous souhaitez récupérer ce code dans votre classeur, si vous tentez de l'importer de la même manière qu'un module VBA, vous obtiendrez une erreur si cette feuille existe déjà dans le classeur. 

Pour résoudre ce problème, j'ai décidé de ne pas essayer d'importer le fichier .cls dans Excel, mais plutôt de lire le fichier .cls dans Excel sous forme de chaîne, puis de coller cette chaîne dans le MEO vide. Voici mes ImportCodeModules:

Sub ImportCodeModules(dir As String)

Dim modList(0 To 0) As String
Dim vbaType As Integer

' delete all forms, modules, and code in MEOs
With ThisWorkbook.VBProject
    For Each comp In .VBComponents

        moduleName = comp.CodeModule.Name

        vbaType = .VBComponents(moduleName).Type

        If moduleName <> "DevTools" Then
            If vbaType = 1 Or _
                vbaType = 3 Then

                .VBComponents.Remove .VBComponents(moduleName)

            ElseIf vbaType = 100 Then

                ' we can't simply delete these objects, so instead we empty them
                .VBComponents(moduleName).CodeModule.DeleteLines 1, .VBComponents(moduleName).CodeModule.CountOfLines

            End If
        End If
    Next comp
End With

' make a list of files in the target directory
Set FSO = CreateObject("Scripting.FileSystemObject")
Set dirContents = FSO.getfolder(dir) ' figure out what is in the directory we're importing

' import modules, forms, and MEO code back into workbook
With ThisWorkbook.VBProject
    For Each moduleName In dirContents.Files

        ' I don't want to import the module this script is in
        If moduleName.Name <> "DevTools.vba" Then

            ' if the current code is a module or form
            If Right(moduleName.Name, 4) = ".vba" Or _
                Right(moduleName.Name, 4) = ".frm" Then

                ' just import it normally
                .VBComponents.Import dir & moduleName.Name

            ' if the current code is a Microsoft Excel object
            ElseIf Right(moduleName.Name, 4) = ".cls" Then
                Dim count As Integer
                Dim fullmoduleString As String
                Open moduleName.Path For Input As #1

                count = 0              ' count which line we're on
                fullmoduleString = ""  ' build the string we want to put into the MEO
                Do Until EOF(1)        ' loop through all the lines in the file

                    Line Input #1, moduleString  ' the current line is moduleString
                    If count > 8 Then            ' skip the junk at the top of the file

                        ' append the current line `to the string we'll insert into the MEO
                        fullmoduleString = fullmoduleString & moduleString & vbNewLine

                    End If
                    count = count + 1
                Loop

                ' insert the lines into the MEO
                .VBComponents(Replace(moduleName.Name, ".cls", "")).CodeModule.InsertLines .VBComponents(Replace(moduleName.Name, ".cls", "")).CodeModule.CountOfLines + 1, fullmoduleString

                Close #1

            End If
        End If

    Next moduleName
End With

End Sub

Si l'entrée dir vous confond avec ces deux fonctions, il s'agit simplement de votre référentiel de code! Donc, vous appelez ces fonctions comme:

SaveCodeModules "C:\...\YourDirectory\Project\source\"
ImportCodeModules "C:\...\YourDirectory\Project\source\"
6
dslosky

J'utilise git, et aujourd'hui j'ai porté this (git-xlsx-textconv) vers Python, car mon projet est basé sur du code Python et qu'il interagit avec les fichiers Excel. Cela fonctionne pour au moins .xlsx fichiers, mais je pense que cela fonctionnera également pour .xls. Voici le lien github. J'ai écrit deux versions, une avec chaque ligne sur sa propre ligne, et une autre où chaque cellule est sur sa propre ligne (la dernière a été écrite parce que git diff n'aime pas encapsuler de longues lignes par défaut, du moins ici sous Windows).

Voici mon fichier .gitconfig (cela permet au script différent de résider dans le référentiel de mon projet):

[diff "xlsx"]
    binary = true
    textconv = python `git rev-parse --show-toplevel`/src/util/git-xlsx-textconv.py

si vous voulez que le script soit disponible pour de nombreux dépôts différents, utilisez ce qui suit:

[diff "xlsx"]
    binary = true
    textconv = python C:/Python27/Scripts/git-xlsx-textconv.py

mon fichier .gitattributes:

*.xlsx diff=xlsx
3
nmz787

Une chose que vous pouvez faire est d’avoir l’extrait suivant dans votre classeur:

Sub SaveCodeModules()

'This code Exports all VBA modules
Dim i%, sName$

    With ThisWorkbook.VBProject
        For i% = 1 To .VBComponents.Count
            If .VBComponents(i%).CodeModule.CountOfLines > 0 Then
                sName$ = .VBComponents(i%).CodeModule.Name
                .VBComponents(i%).Export "C:\Code\" & sName$ & ".vba"
            End If
        Next i
    End With
End Sub

J'ai trouvé cet extrait sur Internet.

Ensuite, vous pouvez utiliser Subversion pour maintenir le contrôle de version. Par exemple, en utilisant l'interface de ligne de commande de Subversion avec la commande 'Shell' dans VBA. Cela le ferait. Je pense même à le faire moi-même :)

3
GUI Junkie

Si vous envisagez de créer un environnement de bureau avec des utilisateurs non techniques habituels, Sharepoint constitue une alternative viable. Vous pouvez configurer des dossiers de documents avec le contrôle de version activé, ainsi que des vérifications et des extractions. Rend le freindlier pour les utilisateurs de bureau réguliers.

2
mattlant

en réponse à la réponse de mattlant - sharepoint fonctionnera bien comme contrôle de version uniquement si la fonctionnalité de contrôle de version est activée dans la bibliothèque de documents . De plus, sachez que tout code appelant d'autres fichiers par des chemins relatifs ne fonctionnera pas. et enfin, tous les liens vers des fichiers externes se briseront lorsqu'un fichier est enregistré dans SharePoint.

1
SpyJournal

Utilisez l’un des outils de contrôle de version standard tels que SVN ou CVS. Les limitations dépendent de l'objectif. Mis à part une petite augmentation de la taille du référentiel, je n'ai rencontré aucun problème.

1
Dheer

En réalité, il n’existe que très peu de solutions pour suivre et comparer les modifications du code macro, la plupart d’entre elles étant déjà nommées ici. J'ai navigué sur le Web et suis tombé sur ce nouvel outil qui mérite d'être mentionné: 

XLTools Version Control pour les macros VBA

  • contrôle de version pour les feuilles Excel et les modules VBA
  • prévisualiser et modifier les modifications avant de valider une version
  • idéal pour le travail collaboratif de plusieurs utilisateurs sur le même fichier (savoir qui a changé quoi/quand/commenter)
  • comparer les versions et mettre en évidence les modifications dans le code ligne par ligne
  • convient aux utilisateurs qui ne sont pas férus de technologie, ou d'Excel d'ailleurs
  • l'historique des versions est stocké dans le référentiel Git sur votre propre PC - toute version peut être facilement récupérée 

Les versions du code VBA côte à côte, les modifications sont visualisées

1
eriklind

Après avoir recherché des âges et essayé de nombreux outils, j'ai trouvé ici ma réponse au problème du contrôle de version vba: https://stackoverflow.com/a/25984759/2780179

C'est un simple complément Excel pour lequel le code peut être trouvé ici

Il n'y a pas de modules en double après l'importation. Il exporte votre code automatiquement, dès que vous enregistrez votre classeur, sans modifier aucun classeur existant . Il est fourni avec un formateur de code vba.

1
CodeKid

Je voudrais recommander un excellent outil open-source appelé Rubberduck qui intègre le contrôle de version du code VBA. Essayez-le!

1
Yuxiang Wang

J'ai aussi étudié cela. Il semble que le dernier Team Foundation Server 2010 ait un complément Excel.

Voici un indice:

http://team-foundation-server.blogspot.com/2009/07/tf84037-there-was-problem-initializing.html

1
Jim Slavens

Vous devriez essayer DiffEngineX. Il peut être appelé par programme et également à partir de la ligne de commande en utilisant des arguments de ligne de commande. Il compare non seulement les cellules de feuille de calcul Excel, mais également les macros Visual Basic incorporées dans les classeurs. Compare également les noms définis par Excel et les commentaires, ce que de nombreux outils gratuits ignorent. Il peut être téléchargé à partir de

http://www.florencesoft.com/Excel-differences-download.html

Je suis sûr que votre système de contrôle de version dispose d'une option ou d'une boîte vous permettant d'appeler automatiquement DiffEngineX avec vos classeurs Excel originaux et modifiés.

1
Marisa Poulian

Vous avez peut-être essayé d'utiliser le format XML Excel de Microsoft dans le conteneur Zip (.xlsx et .xslm) pour le contrôle de version et vous avez trouvé que la vba était stockée dans vbaProject.bin (ce qui est inutile pour le contrôle de version).

La solution est simple.

  1. Ouvrez le fichier Excel avec LibreOffice Calc
  2. Dans LibreOffice Calc
    1. Fichier
    2. Enregistrer sous
    3. Enregistrer en tant que type: feuille de calcul ODF (.ods)
  3. Fermer LibreOffice Calc
  4. renommer l'extension de fichier du nouveau fichier de .ods à .Zip
  5. créer un dossier pour la feuille de calcul dans une zone maintenue par GIT
  6. extraire le Zip dans son dossier GIT
  7. s'engager à GIT

Lorsque vous répétez cette opération avec la prochaine version de la feuille de calcul, vous devez vous assurer que les fichiers du dossier correspondent exactement à ceux du conteneur Zip (et ne laissez aucun fichier supprimé derrière vous).

0
Dave Saunders

J'ai trouvé une solution très simple à cette question qui répond à mes besoins. J'ajoute une ligne au bas de toutes mes macros, qui exporte un fichier *.txt avec le code de macro entier à chaque exécution. Le code:

ActiveWorkbook.VBProject.VBComponents("moduleName").Export"C:\Path\To\Spreadsheet\moduleName.txt"

(Trouvé sur Les didacticiels de Tom , qui couvre également certaines configurations dont vous pourriez avoir besoin pour que cela fonctionne.)

Comme je vais toujours lancer la macro chaque fois que je travaille sur le code, je suis assuré que git enregistrera les modifications. La seule partie ennuyante est que si je dois extraire une version antérieure, je dois copier/coller manuellement à partir du *.txt dans la feuille de calcul.

0
LShaver

Il existe également un programme appelé Beyond Compare qui contient un fichier Excel plutôt sympa. J'ai trouvé une capture d'écran en chinois qui montre brièvement ceci:

Beyond Compare - comparing two Excel files (Chinese)
Source de l'image d'origine

Il y a un essai de 30 jours sur leur page

0
mana

Voici un projet GitHub qui ne résout que les points 1. et 4. de la question du PO: https://github.com/ColmBhandal/VbaMisc . C'est une solution VC pour les modules VBA uniquement. Il peut être facilement personnalisé pour tout projet en répliquant la structure de projet vue sur GitHub et en ajoutant les modules à placer sous VC à une liste blanche définie dans le module ExportImport. Ce module contrôle l’exportation et l’importation d’une liste blanche de modules VBA, s’incluant éventuellement. Voir le repo GitHub pour des instructions sur l'utilisation. 

0
Colm Bhandal

Mon entreprise travaille énormément à l'automatisation des solutions Microsoft Office. J'ai donc écrit un fichier .DLL qui exportera la source d'une solution chaque fois qu'un modèle est enregistré. Il crée un dossier nommé Source en tant qu'enfant du dossier dans lequel le modèle est enregistré, et sous Source, il crée un dossier du même nom que le projet VBA. Dans le dossier du projet, il exporte tout le code source des modules, des classes et des formulaires utilisateur. Cet arrangement a été choisi pour faciliter la gestion de la source pour de grandes collections de modèles. La DLL peut déverrouiller les projets verrouillés pour accéder au projet VBA si un fichier de configuration local ou un fichier de configuration global est disponible. Avec cet outil, les développeurs peuvent travailler sur des modèles à leur contenu et utiliser leur outil de contrôle de révision favori pour gérer leur travail. Nous utilisons Git principalement dans notre environnement et nous gardons les fichiers binaires du modèle complet ainsi que les ressources VBA sous contrôle de révision.

0
Chad Knudson