Domanda

Quali sistemi di controllo versione hai usato con MS Excel (2003/2007)? Cosa consiglieresti e perché? Quali limiti hai riscontrato con il tuo sistema di controllo della versione più votato?

Per metterlo in prospettiva, ecco un paio di casi d'uso:

  1. controllo versione per moduli VBA
  2. più di una persona sta lavorando su un foglio di calcolo Excel e potrebbero apportare modifiche allo stesso foglio di lavoro, che desiderano unire e integrare. Questo foglio di lavoro può contenere formule, dati, grafici ecc.
  3. gli utenti non sono troppo tecnici e meno sistemi di controllo della versione usano meglio
  4. Il vincolo di spazio è una considerazione. Idealmente, vengono salvate solo le modifiche incrementali anziché l'intero foglio di calcolo Excel.
È stato utile?

Soluzione

Ho appena impostato un foglio di calcolo che utilizza Bazaar, con il check-in / out manuale tramite TortiseBZR. Dato che l'argomento mi ha aiutato con la parte di salvataggio, volevo pubblicare la mia soluzione qui.

La soluzione per me è stata quella di creare un foglio di calcolo che esporta tutti i moduli al momento del salvataggio, rimuovendo e reimportando i moduli all'apertura. Sì, questo potrebbe essere potenzialmente pericoloso per la conversione dei fogli di calcolo esistenti.

Questo mi consente di modificare le macro nei moduli tramite Emacs (sì, emacs) o nativamente in Excel e di eseguire il commit del mio repository BZR dopo importanti modifiche. Poiché tutti i moduli sono file di testo, i comandi standard di tipo diff in BZR funzionano per le mie fonti tranne il file Excel stesso.

Ho impostato una directory per il mio repository BZR, X: \ Data \ MySheet. Nel repository ci sono MySheet.xls e un file .vba per ciascuno dei miei moduli (es: Module1Macros). Nel mio foglio di calcolo ho aggiunto un modulo che è esente dal ciclo di esportazione / importazione chiamato "VersionControl". Ogni modulo da esportare e reimportare deve terminare con "Macro".

Contenuti di " VersionControl " Modulo:

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

Successivamente, dobbiamo configurare hook di eventi per open / save per eseguire queste macro. Nel visualizzatore di codice, fai clic con il pulsante destro del mouse su " ThisWorkbook " e seleziona " Visualizza codice " ;. Potrebbe essere necessario aprire la casella di selezione nella parte superiore della finestra del codice per passare da " (Generale) " visualizza " Cartella di lavoro " view.

Contenuti di " Cartella di lavoro " Vista:

Private Sub Workbook_Open()

ImportCodeModules

End Sub

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

SaveCodeModules

End Sub

Mi accontenterò di questo flusso di lavoro nelle prossime settimane e pubblicherò in caso di problemi.

Grazie per aver condiviso il codice VBComponent!

Altri suggerimenti

TortoiseSVN è un client Windows sorprendentemente buono per il sistema di controllo della versione di Subversion. Una caratteristica che ho appena scoperto è che quando si fa clic per ottenere una diff tra le versioni di un file Excel, si apriranno entrambe le versioni in Excel e si evidenziano (in rosso) le celle che sono state modificate. Questo viene fatto attraverso la magia di uno script vbs, descritto qui .

Potresti trovarlo utile anche se NON usi TortoiseSVN.

Dipende se stai parlando di dati o del codice contenuto in un foglio di calcolo. Anche se ho una forte antipatia per Visual Sourcesafe di Microsoft e normalmente non lo consiglierei, si integra facilmente con Access ed Excel e fornisce il controllo del codice sorgente dei moduli.

[In effetti l'integrazione con Access include query, report e moduli come singoli oggetti che possono essere sottoposti a versione]

Il collegamento MSDN è qui .

Non sono a conoscenza di uno strumento che funzioni bene ma ho visto una varietà di soluzioni fatte in casa. Il filo conduttore di questi è minimizzare i dati binari sotto il controllo della versione e massimizzare i dati testuali per sfruttare la potenza dei sistemi scc convenzionali. Per fare questo:

  • Tratta la cartella di lavoro come qualsiasi altra applicazione. Logica, configurazione e dati separati.
  • Separare il codice dalla cartella di lavoro.
  • Crea l'interfaccia utente a livello di codice.
  • Scrivi uno script di build per ricostruire la cartella di lavoro.

Consentitemi di riassumere ciò che si desidera controllare la versione e perché:

  1. Cosa:

    • Codice (VBA)
    • Fogli di lavoro (formule)
    • Fogli di calcolo (valori)
    • Grafici
    • ...
  2. Perché:

    • Registro di controllo
    • Collaborazione
    • Confronto delle versioni (" diffing ")
    • Fusione

Come altri hanno pubblicato qui, ci sono un paio di soluzioni oltre ai sistemi di controllo della versione esistenti come:

  • Git
  • Mercurial
  • Subversion
  • Bazar

Se la tua unica preoccupazione è il codice VBA nelle tue cartelle di lavoro, l'approccio Demosthenex sopra propone o VbaGit ( https: //github.com/brucemcpherson/VbaGit ) funzionano molto bene e sono relativamente semplici da implementare. I vantaggi sono che puoi fare affidamento su sistemi di controllo della versione ben collaudati e sceglierne uno in base alle tue esigenze (dai un'occhiata a https://help.github.com/articles/what-are-the-differences-between-svn-and-git/ per un breve confronto tra Git e Subversion).

Se non ti preoccupi solo del codice ma anche dei dati nei tuoi fogli (valori "hardcoded" e risultati della formula), puoi utilizzare una strategia simile per questo: serializzare il contenuto dei tuoi fogli in un formato di testo (tramite Range.Value) e utilizzare un sistema di controllo versione esistente. Ecco un ottimo post sul blog a riguardo: https://wiki.ucl.ac.uk/display/~ucftpw2/2013/10/18/Using+git+for+version+ controllo + di + foglio elettronico + modelli + - + parte + 1 + di + 3

Tuttavia, il confronto dei fogli di calcolo è un problema algoritmico non banale. Ci sono alcuni strumenti in giro, come Microsoft Spreadsheet Compare ( https://support.office.com/en-us/article/Overview-of-Spreadsheet-Compare-13fafa61-62aa-451b-8674-242ce5f2c986 ), Exceldiff ( http://exceldiff.arstdesign.com/ ) e DiffEngineX ( https://www.florencesoft.com/compare-excel-workbooks-differences.html ). Ma è un'altra sfida integrare questi confronti con un sistema di controllo della versione come Git.

Infine, devi accontentarti di un flusso di lavoro adatto alle tue esigenze. Per un flusso di lavoro Git for Excel semplice e su misura, dai un'occhiata a https: // www.xltrail.com/blog/git-workflow-for-excel .

Lavorando sul lavoro di @Demosthenex, @Tmdean e @Jon Crowell inestimabili commenti! (+1)

Salvo i file del modulo in git \ dir accanto alla posizione della cartella di lavoro. Modificalo a tuo piacimento.

Questo NON terrà traccia delle modifiche al codice della cartella di lavoro. Quindi tocca a te sincronizzarli.

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

E poi nel modulo Cartella di lavoro:

Private Sub Workbook_Open()

    ImportCodeModules

End Sub

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

    SaveCodeModules

End Sub

Prendendo un ulteriore passo avanti nella risposta di @Demosthenex, se desideri tenere traccia anche del codice nei tuoi oggetti Microsoft Excel e UserForm devi diventare un po 'complicato.

Per prima cosa ho modificato la mia funzione SaveCodeModules () per tenere conto dei diversi tipi di codice che intendo esportare:

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

I form utente possono essere esportati e importati proprio come il codice VBA. L'unica differenza è che verranno creati due file quando viene esportato un modulo (otterrai un file .frm e un .frx per ogni UserForm). Uno di questi contiene il software che hai scritto e l'altro è un file binario che (ne sono abbastanza sicuro) definisce il layout del modulo.

Gli oggetti di Microsoft Excel (MEO) (che significa Sheet1 , Sheet2 , ThisWorkbook ecc.) possono essere esportati come .cls file. Tuttavia, quando si desidera ripristinare questo codice nella cartella di lavoro, se si tenta di importarlo nello stesso modo in cui si farebbe un modulo VBA, verrà visualizzato un errore se tale foglio esiste già nella cartella di lavoro.

Per ovviare a questo problema, ho deciso di non provare a importare il file .cls in Excel, ma di leggere invece il file .cls in Excel come stringa, quindi incollare questa stringa nel vuoto MEO. Ecco i miei 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

Nel caso in cui tu sia confuso dall'ingresso dir in entrambe queste funzioni, questo è solo il tuo repository di codice! Quindi, chiamereste queste funzioni come:

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

Una cosa che potresti fare è avere il seguente frammento nella tua cartella di lavoro:

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

Ho trovato questo frammento su Internet.

Successivamente, è possibile utilizzare Subversion per mantenere il controllo della versione. Ad esempio, utilizzando l'interfaccia della riga di comando di Subversion con il comando 'shell' all'interno di VBA. Lo farebbe. Sto anche pensando di farlo da solo :)

Uso git e oggi ho portato this (git-xlsx-textconv) su Python, poiché il mio progetto si basa sul codice Python e interagisce con i file Excel. Questo funziona almeno per i file .xlsx , ma penso che funzionerà anche per .xls . Ecco il link github. Ho scritto due versioni, una con ogni riga sulla propria riga e un'altra in cui ogni cella si trova sulla propria riga (quest'ultima è stata scritta perché git diff non ama avvolgere le righe lunghe per impostazione predefinita, almeno qui su Windows).

Questo è il mio file .gitconfig (ciò consente al diverso script di risiedere nel repository del mio progetto):

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

se vuoi che lo script sia disponibile per molti repository diversi, usa qualcosa del genere:

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

il mio .gitattributes file:

*.xlsx diff=xlsx

Se stai guardando un ufficio con utenti abituali non tecnici rispetto a Sharepoint è una valida alternativa. È possibile impostare cartelle di documenti con il controllo versione abilitato e check-in e check-out. Lo rende amichevole per gli utenti normali di ufficio.

Vorrei raccomandare un ottimo strumento open source chiamato Rubberduck che ha il controllo della versione del codice VBA integrato. Provalo!

Utilizza uno degli strumenti di controllo della versione standard come SVN o CVS. Le limitazioni dipenderebbero dall'obiettivo. A parte un piccolo aumento delle dimensioni del repository, non ho riscontrato alcun problema

in risposta alla risposta di Mattlant - sharepoint funzionerà bene come controllo della versione solo se la funzione di controllo della versione è attivata nella raccolta documenti. inoltre, tenere presente che qualsiasi codice che chiama altri file tramite percorsi relativi non funzionerà. e infine eventuali collegamenti a file esterni verranno interrotti quando un file viene salvato in sharepoint.

Dovresti provare DiffEngineX. Può essere chiamato a livello di codice e anche dalla riga di comando prendendo argomenti della riga di comando. Non solo confronta le celle dei fogli di calcolo di Excel, ma anche le macro di Visual Basic incorporate nelle cartelle di lavoro. Confronta anche nomi e commenti definiti da Excel, che mancano molti strumenti freeware. Può essere scaricato da

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

Sono sicuro che il tuo sistema di controllo della versione ha un'opzione o una casella in modo da poter chiamare automaticamente DiffEngineX con le tue cartelle di lavoro Excel originali e modificate.

Ho esaminato anche questo. Sembra che l'ultimo Team Foundation Server 2010 possa avere un componente aggiuntivo di Excel.

Ecco un indizio:

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

Dopo aver cercato per anni e provato molti strumenti diversi, ho trovato la mia risposta al problema di controllo della versione vba qui: https: //stackoverflow.com/a/25984759/2780179

È un semplice componente aggiuntivo Excel per il quale è possibile trovare il codice qui

Non ci sono moduli duplicati dopo l'importazione. Esporta automaticamente il codice, non appena si salva la cartella di lavoro, senza modificare alcuna cartella di lavoro esistente . Viene fornito con un formattatore di codice vba.

In realtà ci sono solo poche soluzioni per tracciare e confrontare i cambiamenti nel codice macro: la maggior parte di quelli sono stati già nominati qui. Ho visitato il Web e ho trovato questo nuovo strumento degno di nota:

Controllo versione XLTools per macro VBA

  • controllo versione per fogli Excel e moduli VBA
  • visualizza l'anteprima e le modifiche alla differenza prima di eseguire il commit di una versione
  • ottimo per il lavoro collaborativo di più utenti sullo stesso file (traccia chi ha cambiato cosa / quando / commenti)
  • confronta le versioni ed evidenzia le modifiche nel codice riga per riga
  • adatto a utenti che non sono esperti di tecnologia o esperti di Excel in tale materia
  • la cronologia delle versioni è memorizzata nel repository Git sul tuo PC - qualsiasi versione può essere facilmente recuperata

Versioni di codice VBA fianco a fianco, le modifiche vengono visualizzate

Potresti aver provato a utilizzare l'XML di Microsoft Excel nel contenitore zip (.xlsx e .xslm) per il controllo della versione e hai scoperto che la vba era memorizzata in vbaProject.bin (che è inutile per il controllo della versione).

La soluzione è semplice.

  1. Apri il file Excel con LibreOffice Calc
  2. In LibreOffice Calc
    1. File
    2. Salva come
    3. Salva come tipo: foglio di calcolo ODF (.ods)
  3. Chiudi LibreOffice Calc
  4. rinomina l'estensione del nuovo file da .ods a .zip
  5. crea una cartella per il foglio di calcolo in un'area gestita da GIT
  6. estrae lo zip nella sua cartella GIT
  7. si impegna in GIT

Quando lo ripeti con la prossima versione del foglio di calcolo, devi assicurarti che i file della cartella corrispondano esattamente a quelli nel contenitore zip (e non lasciare indietro alcun file eliminato).

Esiste anche un programma chiamato Beyond Compare che ha un bel confronto di file Excel. Ho trovato uno screenshot in cinese che mostra brevemente questo:

Beyond Compare - confronto tra due file Excel (cinese)
Fonte immagine originale

C'è una prova di 30 giorni sulla loro pagina

La mia azienda lavora molto nell'automazione delle soluzioni di Microsoft Office, quindi ho scritto un .DLL che esporterà l'origine di una soluzione ogni volta che viene salvato un modello. Crea una cartella denominata Source come figlio della cartella in cui viene salvato il modello e sotto Source crea una cartella con lo stesso nome del progetto VBA. Nella cartella del progetto esporta tutto il codice sorgente per moduli, classi e moduli utente. Questa disposizione è stata scelta per semplificare la gestione della fonte per grandi raccolte di modelli. La DLL è in grado di sbloccare progetti bloccati per ottenere l'accesso al progetto VBA se si dispone di un file di configurazione locale o di un file di configurazione globale. Con questo strumento in uso, gli sviluppatori possono lavorare su modelli per i loro contenuti e usare il loro strumento di controllo delle revisioni preferito per gestire il loro lavoro. Utilizziamo Git principalmente nel nostro ambiente e manteniamo sotto controllo i file binari del modello completo e le risorse VBA.

Ecco un progetto GitHub che risolve solo i punti 1. e 4. della domanda del PO: https: // github.com/ColmBhandal/VbaMisc . È una soluzione VC solo per i moduli VBA. Può essere facilmente adattato a qualsiasi progetto replicando la struttura del progetto vista su GitHub & amp; aggiungendo tutti i moduli da mettere sotto VC a una WhiteList definita nel modulo ExportImport. Quel modulo controlla export & amp; importazione di una whitelist di moduli VBA, incluso potenzialmente se stesso. Consultare il repository GitHub per istruzioni su come utilizzare.

Ho trovato una soluzione molto semplice a questa domanda che soddisfa le mie esigenze. Aggiungo una riga in fondo a tutte le mie macro che esporta un file * .txt con l'intero codice macro ogni volta che viene eseguito. Il codice:

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

(Trovato su Tom's Tutorials , che copre anche alcune impostazioni di cui potresti aver bisogno per farlo funzionare.)

Dato che eseguirò sempre la macro ogni volta che sto lavorando sul codice, sono sicuro che git prenderà le modifiche. L'unica parte fastidiosa è che se devo verificare una versione precedente, devo copiare / incollare manualmente dal * .txt nel foglio di calcolo.

Dipende dal livello di integrazione desiderato, ho usato Subversion / TortoiseSVN che sembra perfetto per un semplice utilizzo. Ho anche aggiunto parole chiave, ma sembra esserci il rischio di corruzione dei file. C'è un'opzione in Subversion per rendere le sostituzioni di parole chiave a lunghezza fissa e per quanto ne so funzionerà se la lunghezza fissa è pari ma non dispari. In ogni caso non ottieni alcun tipo utile di funzionalità diff, penso che ci siano prodotti commerciali che faranno 'diff'. Ho trovato qualcosa che differiva in base alla conversione di cose in testo semplice e al confronto, ma non era molto carino.

Dovrebbe funzionare con la maggior parte dei VCS (a seconda di altri criteri che potresti scegliere SVN, CVS, Darcs, TFS, ecc.), tuttavia in realtà sarà il file completo (perché è un formato binario), il che significa che " cambiato " alla domanda non è così facile rispondere.

Puoi ancora fare affidamento sui messaggi di log se le persone li completano, ma potresti anche provare i nuovi formati basati su XML da Office 2007 per ottenere un po 'più di visibilità (anche se sarebbe comunque difficile sfogliare tonnellate di XML, oltre ad AFAIK il file XML è compresso sul disco, quindi avrai bisogno di un hook pre-commit per decomprimerlo affinché il diff di testo funzioni correttamente).

Ho scritto un foglio di calcolo controllato tramite revisione usando VBA. È più orientato ai report di ingegneria in cui ci sono più persone che lavorano su una distinta base o su una pianificazione e quindi a un certo punto nel tempo si desidera creare una revisione di istantanee che mostri aggiunte, eliminazioni e aggiornamenti dalla versione precedente.

Nota: è una cartella di lavoro abilitata per le macro che è necessario accedere per scaricare dal mio sito (è possibile utilizzare OpenID)

Tutto il codice è sbloccato.

Foglio di calcolo controllato dai revisori

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top