177

您在 MS Excel (2003/2007) 中使用了哪些版本控制系统?你会推荐什么,为什么?您发现您的顶级版本控制系统有哪些限制?

从这个角度来看,这里有几个用例:

  1. VBA 模块的版本控制
  2. 不止一个人在处理 Excel 电子表格,他们可能正在对同一个工作表进行更改,他们希望将其合并和集成。此工作表可能包含公式、数据、图表等
  3. 用户不太懂技术,使用的版本控制系统越少越好
  4. 空间限制是一个考虑因素。理想情况下,只保存增量更改而不是整个 Excel 电子表格。
4

22 回答 22

66

我刚刚设置了一个使用 Bazaar 的电子表格,通过 TortiseBZR 手动签入/签出。鉴于该主题帮助我完成了保存部分,我想在这里发布我的解决方案。

我的解决方案是创建一个电子表格,在保存时导出所有模块,并在打开时删除并重新导入模块。是的,这可能对转换现有电子表格有潜在危险。

这允许我通过Emacs(是的,emacs)或在 Excel 中本地编辑模块中的宏,并在重大更改后提交我的 BZR 存储库。因为所有模块都是文本文件,所以 BZR 中的标准 diff 样式命令适用于我的源代码,但 Excel 文件本身除外。

我已经为我的 BZR 存储库设置了一个目录 X:\Data\MySheet。在 repo 中有我的每个模块的 MySheet.xls 和一个 .vba 文件(即:Module1Macros)。在我的电子表格中,我添加了一个免于导出/导入周期的模块,称为“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”并选择“查看代码”。您可能必须下拉代码窗口顶部的选择框才能从“(常规)”视图更改为“工作簿”视图。

“工作簿”视图的内容:

Private Sub Workbook_Open()

ImportCodeModules

End Sub

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

SaveCodeModules

End Sub

我将在接下来的几周内适应这个工作流程,如果我有任何问题,我会发布。

感谢分享 VBComponent 代码!

于 2010-01-05T02:28:20.737 回答
44

TortoiseSVN是一个非常出色的用于 Subversion 版本控制系统的 Windows 客户端。我刚刚发现它具有的一个功能是,当您单击以获取 Excel 文件版本之间的差异时,它将在 Excel 中打开这两个版本并突出显示(以红色显示)已更改的单元格。这是通过此处描述的 vbs 脚本的魔力完成的。

即使不使用 TortoiseSVN,您也会发现这很有用。

于 2010-01-07T15:52:46.910 回答
11

让我总结一下您希望进行版本控制的内容以及原因:

  1. 什么:

    • 代码 (VBA)
    • 电子表格(公式)
    • 电子表格(值)
    • 图表
    • ...
  2. 为什么:

    • 审核日志
    • 合作
    • 版本比较(“差异”)
    • 合并

正如其他人在此处发布的那样,在现有版本控制系统之上有几个解决方案,例如:

  • 吉特
  • 水银
  • 颠覆
  • 市场

如果您唯一关心的是工作簿中的 VBA 代码,那么上面建议的方法 Demosthenex 或 VbaGit ( https://github.com/brucemcpherson/VbaGit ) 工作得很好,并且实施起来相对简单。优点是您可以依赖经过充分验证的版本控制系统并根据您的需要选择一个(查看https://help.github.com/articles/what-are-the-differences-between-svn-and -git/用于 Git 和 Subversion 之间的简要比较)。

如果您不仅担心代码,还担心工作表中的数据(“硬编码”值和公式结果),您可以使用类似的策略:将工作表的内容序列化为某种文本格式(通过 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 的电子表格比较 ( 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 for Excel 工作流程,请查看https://www.xltrail.com/blog/git-workflow-for-excel

于 2016-04-04T12:06:17.003 回答
9

这取决于您是在谈论数据还是电子表格中包含的代码。虽然我非常不喜欢 Microsoft 的 Visual Sourcesafe 并且通常不会推荐它,但它确实可以轻松地与 Access 和 Excel 集成,并提供模块的源代码控制。

[事实上与 Access 的集成,包括查询、报告和模块作为可以版本化的单独对象]

MSDN 链接在这里

于 2008-09-25T05:44:58.343 回答
7

我不知道有什么工具可以很好地做到这一点,但我已经看到了各种本土解决方案。它们的共同点是最小化版本控制下的二进制数据并最大化文本数据以利用传统 scc 系统的强大功能。去做这个:

  • 像对待任何其他应用程序一样对待工作簿。分离逻辑、配置和数据。
  • 将代码与工作簿分开。
  • 以编程方式构建 UI。
  • 编写构建脚本来重建工作簿。
于 2008-09-25T09:19:09.170 回答
6

处理@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

然后在工作簿模块中:

Private Sub Workbook_Open()

    ImportCodeModules

End Sub

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

    SaveCodeModules

End Sub
于 2014-03-07T17:25:10.490 回答
6

将@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)(意思是Sheet1Sheet2ThisWorkbook)可以导出为.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\"
于 2015-05-08T15:37:54.107 回答
5

我使用git,今天我将它 (git-xlsx-textconv)移植到 Python,因为我的项目基于 Python 代码,并且它与 Excel 文件交互。这至少适用于.xlsx文件,但我认为它也适用于.xls这是github链接。我写了两个版本,一个是每行单独一行,另一个是每个单元格单独一行(写后者是因为git diff默认不喜欢换行,至少在 Windows 上是这样)。

这是我的.gitconfig文件(这允许不同的脚本驻留在我的项目的仓库中):

[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

我的.gitattributes文件:

*.xlsx diff=xlsx
于 2015-05-16T08:02:48.253 回答
3

您可以做的一件事是在您的工作簿中包含以下代码段:

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 的命令行界面和 VBA 中的“shell”命令。这样就可以了。我什至想自己做这个:)

于 2008-09-25T08:16:05.437 回答
3

我想推荐一个很棒的开源工具Rubberduck,它内置了 VBA 代码的版本控制。试试吧!

于 2016-08-09T19:08:15.373 回答
2

如果您正在寻找一个有普通办公室非技术用户的办公室环境,那么 Sharepoint 是一个可行的选择。您可以设置启用版本控制以及签入和签出的文档文件夹。让普通办公室用户更轻松。

于 2008-09-25T05:55:35.260 回答
2

回应 mattlant 的回复 - 只有在文档库中打开版本控制功能时,sharepoint 才能作为版本控制正常工作。另外请注意,任何通过相对路径调用其他文件的代码都不起作用。最后,当文件保存在 sharepoint 中时,任何指向外部文件的链接都会中断。

于 2008-09-29T04:16:55.860 回答
1

使用任何标准版本控制工具,如 SVN 或 CVS。限制将取决于目标是什么。除了存储库大小略有增加外,我没有遇到任何问题

于 2008-09-25T05:44:40.560 回答
1

我也一直在研究这个。似乎最新的 Team Foundation Server 2010 可能具有 Excel 加载项。

这是一个线索:

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

于 2010-10-27T22:35:11.150 回答
1

在搜索了年龄并尝试了许多不同的工具之后,我在这里找到了我对 vba 版本控制问题的答案:https ://stackoverflow.com/a/25984759/2780179

这是一个简单的 excel 插件,代码可以在这里找到

导入后没有重复的模块。只要您保存工作簿,它就会自动导出您的代码,而无需修改任何现有工作簿。它带有一个 vba 代码格式化程序。

于 2014-10-12T00:50:53.963 回答
1

实际上,只有少数解决方案可以跟踪和比较宏代码的变化——其中大部分已经在这里命名。我一直在浏览网页,发现了这个值得一提的新工具:

VBA 宏的 XLTools 版本控制

  • Excel 工作表和 VBA 模块的版本控制
  • 在提交版本之前预览和比较更改
  • 非常适合多个用户在同一个文件上的协作工作(跟踪谁更改了什么/何时/评论)
  • 逐行比较版本并突出显示代码中的更改
  • 适合不精通技术或不精通 Excel 的用户
  • 版本历史存储在您自己 PC 上的 Git 存储库中 - 任何版本都可以轻松恢复

VBA 代码版本并排,更改可视化

于 2016-04-12T17:00:40.507 回答
0

还有一个名为Beyond Compare的程序,它有一个相当不错的 Excel 文件比较。我找到了一个中文截图,简要说明了这一点:

Beyond Compare - 比较两个excel文件(中文)
原图来源

他们的页面上有 30 天的试用期

于 2012-01-04T14:46:11.080 回答
0

您可能已经尝试在 zip 容器(.xlsx 和 .xslm)中使用 Microsoft 的 Excel XML 进行版本控制,发现 vba 存储在 vbaProject.bin 中(这对版本控制没有用处)。

解决方案很简单。

  1. 使用 LibreOffice Calc 打开 excel 文件
  2. 在 LibreOffice 中
    1. 文件
    2. 另存为
    3. 另存为类型:ODF 电子表格 (.ods)
  3. 关闭 LibreOffice Calc
  4. 将新文件的文件扩展名从 .ods 重命名为 .zip
  5. 在 GIT 维护的区域中为电子表格创建一个文件夹
  6. 将 zip 解压到它的 GIT 文件夹中
  7. 致力于 GIT

当您对电子表格的下一个版本重复此操作时,您必须确保使文件夹的文件与 zip 容器中的文件完全匹配(并且不要留下任何已删除的文件)。

于 2012-07-06T06:48:22.107 回答
0

我找到了一个非常简单的解决方案来满足我的需求。我在所有宏的底部添加了一行,*.txt每次运行时都会导出一个包含整个宏代码的文件。编码:

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

(在Tom's Tutorials上找到,其中还涵盖了一些设置,您可能需要让它工作。)

因为我总是在处理代码时运行宏,所以我保证 git 会接受这些更改。唯一烦人的部分是,如果我需要签出早期版本,我必须手动将其复制/粘贴*.txt到电子表格中。

于 2019-02-18T21:08:24.547 回答
-1

这取决于您想要什么级别的集成,我使用了 Subversion/TortoiseSVN,这对于简单的使用来说似乎很好。我还添加了关键字,但似乎存在文件损坏的风险。Subversion中有一个选项可以使关键字替换固定长度,据我所知,如果固定长度是偶数但不是奇数,它将起作用。在任何情况下,您都没有获得任何有用的差异功能,我认为有些商业产品会做“差异”。我确实找到了一些基于将内容转换为纯文本并进行比较的差异,但它不是很好。

于 2008-09-25T05:45:05.473 回答
-1

它应该适用于大多数 VCS(取决于您可能选择 SVN、CVS、Darcs、TFS 等的其他标准),但它实际上是完整的文件(因为它是二进制格式),这意味着“发生了什么变化”的问题是没那么容易回答。

如果人们完成它们,您仍然可以依赖日志消息,但您也可以尝试 Office 2007 中基于 XML 的新格式以获得更多可见性(尽管仍然很难清除大量 XML,加上 AFAIK XML 文件压缩在磁盘上,因此您需要一个预提交挂钩来解压缩它以使文本差异正常工作)。

于 2008-09-25T05:52:30.883 回答
-1

我使用 VBA 编写了一个版本控制的电子表格。它更适用于工程报告,其中您有多个人在处理物料清单或计划,然后在某个时间点您想要创建一个快照修订,显示上一个修订的添加、删除和更新。

注意:这是一个启用宏的工作簿,您需要登录才能从我的站点下载(您可以使用 OpenID)

所有代码都已解锁。

Rev 受控电子表格

于 2012-01-05T06:36:21.760 回答