Лучший способ сделать контроль версий для MS Excel - PullRequest
160 голосов
/ 25 сентября 2008

Какие системы контроля версий вы использовали с MS Excel (2003/2007)? Что бы вы порекомендовали и почему? Какие ограничения вы обнаружили в вашей системе контроля версий с самым высоким рейтингом?

Чтобы представить это в перспективе, вот несколько вариантов использования:

  1. контроль версий для модулей VBA
  2. над таблицей Excel работают несколько человек, и они могут вносить изменения в одну и ту же таблицу, которую они хотят объединить и интегрировать. Эта рабочая таблица может содержать формулы, данные, диаграммы и т. Д.
  3. пользователи не слишком техничны, и чем меньше систем контроля версий, тем лучше
  4. Пространство ограничено. В идеале сохраняются только инкрементные изменения, а не вся электронная таблица Excel.

Ответы [ 25 ]

63 голосов
/ 05 января 2010

Я только что установил электронную таблицу, которая использует Bazaar, с ручной регистрацией / выходом через TortiseBZR. Учитывая, что тема помогла мне с сохранением, я хотел опубликовать свое решение здесь.

Решением для меня было создание электронной таблицы, которая экспортирует все модули при сохранении, а также удаляет и повторно импортирует модули при открытии. Да, это может быть потенциально опасно для преобразования существующих электронных таблиц.

Это позволяет мне редактировать макросы в модулях через Emacs (да, emacs) или непосредственно в Excel, а также фиксировать мой BZR-репозиторий после серьезных изменений. Поскольку все модули являются текстовыми файлами, стандартные команды diff-style в BZR работают для моих источников, кроме самого файла Excel.

Я установил каталог для моего хранилища BZR, X: \ Data \ MySheet. В репозитории находятся MySheet.xls и один файл .vba для каждого из моих модулей (то есть: Module1Macros). В свою электронную таблицу я добавил один модуль, который освобожден от цикла экспорта / импорта, который называется «VersionControl». Каждый экспортируемый и реимпортируемый модуль должен заканчиваться на «Макросы».

Содержимое модуля "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

Далее, мы должны установить перехватчики событий для открытия / сохранения, чтобы запустить эти макросы. В средстве просмотра кода щелкните правой кнопкой мыши «ThisWorkbook» и выберите «View Code». Возможно, вам придется снять поле выбора в верхней части окна кода, чтобы перейти из представления «(Общие) в представление« Рабочая книга ».

Содержимое представления «Рабочая тетрадь»:

Private Sub Workbook_Open()

ImportCodeModules

End Sub

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

SaveCodeModules

End Sub

В течение следующих нескольких недель я приму участие в этом рабочем процессе и опубликую его, если возникнут какие-либо проблемы.

Спасибо, что поделились кодом VBComponent!

41 голосов
/ 07 января 2010

TortoiseSVN - удивительно хороший Windows-клиент для системы контроля версий Subversion. Одна функция, которую я только что обнаружил, заключается в том, что когда вы нажимаете, чтобы получить разницу между версиями файла Excel, он открывает обе версии в Excel и выделяет (красным) ячейки, которые были изменены. Это делается с помощью сценария VBS, описанного здесь .

Вы можете найти это полезным, даже если НЕ используете TortoiseSVN.

9 голосов
/ 25 сентября 2008

Это зависит от того, говорите ли вы о данных или коде, содержащемся в электронной таблице. Хотя я сильно не люблю Visual Sourcesafe от Microsoft и обычно не рекомендую его, он легко интегрируется как с Access, так и с Excel и обеспечивает контроль над источниками модулей.

[Фактически интеграция с Access включает запросы, отчеты и модули в виде отдельных объектов, которые могут быть версионированы]

Ссылка MSDN здесь .

7 голосов
/ 04 апреля 2016

Позвольте мне резюмировать, что вы хотели бы для контроля версий и почему:

  1. Что:

    • Код (VBA)
    • Таблицы (формулы)
    • Таблицы (значения)
    • Графики
    • ...
  2. Почему:

    • Журнал аудита
    • Сотрудничество
    • Сравнение версий ("diffing")
    • Слияние

Как уже сообщали другие, есть несколько решений поверх существующих систем контроля версий, таких как:

  • Гит
  • Mercurial
  • 1042 * Subversion *
  • базар

Если вас беспокоит только код VBA в ваших книгах, то предложенный выше подход Demosthenex или VbaGit (https://github.com/brucemcpherson/VbaGit) работают очень хорошо и относительно просты в реализации. Преимущества в том, что вы можете положиться на них. проверенные системы контроля версий и выбрали одну из них в соответствии с вашими потребностями (кратко сравните Git и Subversion с https://help.github.com/articles/what-are-the-differences-between-svn-and-git/).

Если вы беспокоитесь не только о коде, но и о данных на ваших листах («жестко закодированные» значения и результаты формул), вы можете использовать аналогичную стратегию для этого: сериализовать содержимое ваших листов в некоторый текстовый формат (через Range .Value) и использовать существующую систему контроля версий. Вот очень хороший пост в блоге об этом: https://wiki.ucl.ac.uk/display/~ucftpw2/2013/10/18/Using+git+for+version+control+of+spreadsheet+models+-+part+1+of+3

Однако сравнение электронных таблиц является нетривиальной алгоритмической проблемой. Существует несколько инструментов, таких как Microsoft Spreadsheet Compare (https://support.office.com/en-us/article/Overview-of-Spreadsheet-Compare-13fafa61-62aa-451b-8674-242ce5f2c986), Exceldiff (http://exceldiff.arstdesign.com/)) и DiffEngineX (https://www.florencesoft.com/compare-excel-workbooks-differences.html).). Но это еще одна проблема - объединить это сравнение с такой системой контроля версий, как Git.

Наконец, вы должны выбрать рабочий процесс, который соответствует вашим потребностям. Для простого, адаптированного рабочего процесса Git для Excel, посмотрите https://www.xltrail.com/blog/git-workflow-for-excel.

7 голосов
/ 25 сентября 2008

Мне не известен инструмент, который делает это хорошо, но я видел множество отечественных решений. Общим для них является минимизация двоичных данных при управлении версиями и максимизация текстовых данных для использования возможностей традиционных систем scc. Для этого:

  • Рассматривайте книгу как любое другое приложение. Отдельная логика, конфиг и данные.
  • Отдельный код из рабочей тетради.
  • Построить пользовательский интерфейс программно.
  • Напишите сценарий сборки, чтобы восстановить книгу.
6 голосов
/ 08 мая 2015

Если вы ответите @Demosthenex еще дальше, если вы хотите также отслеживать код в ваших объектах и ​​пользовательских формах Microsoft Excel, вам нужно немного усложнить.

Сначала я изменил свою функцию SaveCodeModules(), чтобы учесть различные типы кода, который я планирую экспортировать:

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

Пользовательские формы можно экспортировать и импортировать так же, как и код VBA. Единственное отличие состоит в том, что при экспорте формы будут созданы два файла (вы получите файл .frm и .frx для каждой пользовательской формы). Один из них содержит программное обеспечение, которое вы написали, а другой - двоичный файл, который (я почти уверен) определяет макет формы.

Объекты Microsoft Excel (MEO) (что означает Sheet1, Sheet2, ThisWorkbook и т. Д.) Можно экспортировать в виде файла .cls. Однако если вы захотите вернуть этот код в рабочую книгу, если вы попытаетесь импортировать его так же, как в модуле VBA, вы получите сообщение об ошибке, если этот лист уже существует в рабочей книге.

Чтобы обойти эту проблему, я решил не пытаться импортировать файл .cls в Excel, а вместо этого прочитать файл .cls в excel в виде строки, а затем вставить эту строку в пустой MEO. Вот мои 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

В случае, если вас смущает ввод dir для обеих этих функций, это всего лишь ваше хранилище кода! Итак, вы бы назвали эти функции как:

SaveCodeModules "C:\...\YourDirectory\Project\source\"
ImportCodeModules "C:\...\YourDirectory\Project\source\"
6 голосов
/ 07 марта 2014

Работая над работой @Demosthenex, @Tmdean и @Jon Crowell бесценные комментарии! (+1 их)

Я сохраняю файлы модуля в папке git \ dir рядом с папкой. Измените это по своему вкусу.

Это НЕ будет отслеживать изменения в коде книги. Так что вам решать синхронизировать их.

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

А затем в модуле Workbook:

Private Sub Workbook_Open()

    ImportCodeModules

End Sub

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

    SaveCodeModules

End Sub
3 голосов
/ 25 сентября 2008

Единственное, что вы можете сделать, это включить в свою рабочую книгу следующий фрагмент:

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

Я нашел этот фрагмент в Интернете.

После этого вы можете использовать Subversion для поддержки контроля версий. Например, используя интерфейс командной строки Subversion с командой 'shell' в VBA. Это сделало бы это. Я даже думаю сделать это сам:)

3 голосов
/ 16 мая 2015

Я использую git , и сегодня я портировал this (git-xlsx-textconv) на Python, поскольку мой проект основан на коде Python и взаимодействует с файлами Excel. Это работает как минимум для .xlsx файлов, но я думаю, что это будет работать и для .xls . Вот ссылка на github. Я написал две версии, одна с каждой строкой на отдельной строке, а другая - с каждой ячейкой на отдельной строке (последняя была написана, потому что git diff по умолчанию не любит переносить длинные строки в хотя бы здесь, на Windows).

Это мой .gitconfig файл (это позволяет сценарию dif находиться в репозитории моего проекта):

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

если вы хотите, чтобы скрипт был доступен для множества различных репозиториев, используйте что-то вроде этого:

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

my .gitattributes file:

*.xlsx diff=xlsx
2 голосов
/ 25 сентября 2008

Если вы ищете офисную среду с обычными офисными не техническими пользователями, то Sharepoint является жизнеспособной альтернативой. Вы можете настроить папки документов с включенным контролем версий, а также проверками и проверками. Делает это freindlier для постоянных офисных пользователей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...