进行MS Excel版本控制的最佳方法[关闭]


176

您在MS Excel(2003/2007)中使用了哪些版本控制系统?您会推荐什么,为什么?您对最高评价的版本控制系统有什么限制?

为了正确理解这一点,这里有一些用例:

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

17
Google Apps / Docs不具有MS Excel的全部功能,您需要做MSM等更高级的工作。
TheObserver 2010年

26
@Richie Cotton。如果这是一个切实可行的选择(例如,使用matlab / python),那么所有金融公司现在都将已转换。要求分析金融模型但不是程序员的人成为程序员,总的来说充满了危险,并且实在不切实际。
匿名类型

1
stackoverflow.com/q/608872/107537在此处看到类似的问题。但是它不能解决工作表本身。仅VBA代码。
维杰2013年

7
那些将Excel建模归咎于信贷紧缩的人最有可能是欺诈者故意将垃圾作为AAA出售。您不需要电子表格即可告诉您一项投资是废话。作为一名财务专家,我可以告诉您完全依赖任何模型都是确保输掉钱的肯定方法。此外,任何模型都只能与建立模型的人一样好。如果您聘请Morts从事爱因斯坦的工作,那将是一段糟糕的时光。
Eric J

如果您只想对VBA宏进行版本控制,请在这里查看我的答案:stackoverflow.com/a/38297505/2146688
2016年

Answers:


65

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

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

这使我可以通过Emacs(是,emacs)或在Excel中本地编辑模块中的宏,并在进行重大更改后提交我的BZR存储库。因为所有模块都是文本文件,所以BZR中的标准diff样式命令适用于我的源文件,但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”,然后选择“查看代码”。您可能需要下拉代码窗口顶部的选择框,才能从“(常规)”视图更改为“工作簿”视图。

“工作簿”视图的内容:

Private Sub Workbook_Open()

ImportCodeModules

End Sub

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

SaveCodeModules

End Sub

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

感谢您分享VBComponent代码!


5
重新导入时,还可以检查模块类型。ThisWorkbook.VBProject.VBComponents.Item(i).Type对于标准模块为1,对于类模块为2,对于用户窗体为3,对于文档模块(工作簿或工作表)为100。
乔恩·克罗威尔

4
导入代码中存在错误。由于您已删除并导入模块,因此它会更改模块的顺序,因此每次都会丢失一些模块。您需要更改For循环才能向后遍历数组。例如对于i = .VBComponents.Count到1步骤-1
Tmdean 2012年

2
在Excel 2013中,必须在信任中心中启用“对VBA项目对象模型的信任访问”,否则,如果尝试运行此代码,则会收到非常无用的错误1004。
罗宾·格林

9
上面的脚本远非完美。importCodeModules()子有问题,并产生重复的模块。此外,您将需要编辑每个工作簿以添加open和before_save事件。这是无法接受的。在网上搜索了很长很长一段时间后,我终于找到的东西,实际工作,(这是指在这里)。它具有代码导入,导出,代码格式化等功能。导出会在保存时自动进行,无需编辑任何现有工作簿。
CodeKid 2014年

5
这是一个很好的发现!我建议使用它而不是上面的脚本。我写了一次,用了一段时间,就满足了我的需求。对于每天使用Excel和VBA的人来说,专用于该导出的程序或项目会更合适。感谢分享!
Demosthenex 2014年

42

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

即使不使用TortoiseSVN,您也可能会发现它很有用。


3
非常高兴知道TortoiseSVN可以将其作为内置功能进行比较^^
Nam G VU 2012年

2
这与Word文件是否相同?
Nam G VU 2012年

3
我刚刚测试过-这也可用于Word文件。酷^^
Nam G VU 2012年

它似乎不适用于VB代码。有什么解决办法吗?
manpreet singh's

10

让我总结一下您想要进行版本控制的原因以及原因:

  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/使用+ git + for + version + control + of +电子表格+模型+-+部分+ 1 + 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 for Excel工作流,请访问https://www.xltrail.com/blog/git-workflow-for-excel


2020更新:对于您的xltrail.com/git-xl建议,赞成一个开源git扩展,它在两次提交之间产生vba源差异,尽管有限,但使我免于容易出错的进出口
chingNotCHing

9

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

[实际上,与Access的集成包括查询,报告和模块,它们是可以版本化的单个对象]

MSDN链接在这里


4
保存得更好的秘密之一-我不知道VSS可以做到这一点。+1
ConcernedOfTunbridgeWells

我也不知道。但是无论如何,VSS是一堆s..t,我会远离它。
GUI Junkie

我很兴奋,花了一个小时来进行网上搜索,但是似乎MS不再支持Excel2003。如果您使用的是Access VBA,可能会很幸运,但是我没有看。
收获

1
您是否可以使用Office开发人员版加载项?:brandon.fuller.name/archives/2003/11/07/10.26.30
Mitch Wheat

7

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

  • 像对待其他任何应用程序一样对待工作簿。分离逻辑,配置和数据。
  • 将代码与工作簿分开。
  • 以编程方式构建UI。
  • 编写构建脚本以重建工作簿。

当您只需要处理二进制对象的源代码控件时,为什么要经历所有这些废话呢?SVN可以做到这一点。
Unknown Coder 2014年

16
因为您无法合并二进制对象
igelineau 2014年

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

6

如果您还想跟踪Microsoft Excel对象和UserForms中的代码,请进一步使用@Demosthenex的答案。

首先,我更改了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代码一样导出和导入UserForm。唯一的区别是,导出表单时将创建两个文件(您将为每个UserForm得到.frm一个.frx文件)。其中一个保存您编写的软件,另一个保存一个二进制文件(我很确定),该文件定义了表单的布局。

微软Excel对象(MEOS)(意为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\"

快速说明:由于二进制文件的缘故,我对使用UserForms进行真正的版本控制没有任何运气。如果您在git
仓库中

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

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维护版本控制。例如,通过在VBA中将Subversion的命令行界面与“ shell”命令配合使用。那样就可以了。我什至在想自己做这个:)


我认为这是一个很好的方法。Excel代码的源代码控制只能通过分解进行。这也将推断出一种构建方法。例如,Code Cleaner可以执行此操作(我相信是免费软件) appspro.com/Utilities/CodeCleaner.htm,但同样,您的代码也等效。
多语种

我试图将其修改为使用Microsoft®Excel®for Mac 2011 14.4.1版。调用Export方法的这一行悄无声息(不管我使用的格式正确的OS X目录如何)。
2014年


2

如果您正在与普通办公室非技术用户一起查看办公室环境,那么Sharepoint是一个可行的选择。您可以在启用版本控制以及签入和签出的情况下设置文档文件夹。使普通办公室用户更容易使用。


2

响应mattlant的答复-仅当文档库中的版本控制功能处于打开状态时,sharepoint才能很好地用作版本控制。此外,请注意,通过相对路径调用其他文件的任何代码均无效。最后,将文件保存在sharepoint中时,指向外部文件的任何链接都将断开。


1

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



1

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

这是一个简单的excel插件,可在此处找到其代码

导入后没有重复的模块。保存工作簿后,它将自动导出代码,而无需修改任何现有工作簿。它与vba代码格式化程序一起提供。


1

实际上,只有少数解决方案可以跟踪和比较宏代码中的更改-大多数解决方案已在此处命名。我一直在浏览网络,发现了这个值得一提的新工具:

用于VBA宏的XLTools版本控制

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

VBA代码版本并排显示更改


0

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

解决方案很简单。

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

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


3
但是,这种方法充满风险。如果随后使用Excel中未在Libre中实现或未“映射”到Libre并正确返回的功能,则此方法将无效。我敢肯定,这对于简单的电子表格是有效的,但是必须格外小心。PW
Phil Whittington

0

还有一个名为Beyond Compare的程序,它具有相当不错的Excel文件比较功能。我找到了一个中文截图,简短地显示了这一点:

超越比较-比较两个Excel文件(中文)
原始图片来源

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


0

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

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

(可在Tom's Tutorials上找到,该指南还介绍了可能需要进行一些设置才能使其正常工作。)

由于每当我处理代码时,我都会一直运行宏,因此可以保证git将接受更改。唯一令人烦恼的部分是,如果我需要签出早期版本,则必须手动从中复制/粘贴*.txt到电子表格中。


-1

这取决于您想要的集成级别,我使用了Subversion / TortoiseSVN,对于简单的用法来说似乎不错。我还添加了关键字,但是似乎存在文件损坏的风险。Subversion中有一个选项可以将关键字替换设置为固定长度,据我了解,如果固定长度为偶数而不是奇数,它将可以正常工作。无论如何,您都不会获得任何有用的diff功能,我认为有些商业产品会执行“ diff”。我确实发现了一些将差异转换为纯文本并进行比较的东西,但这不是很好。


-1

它应该可以与大多数VCS一起使用(取决于其他条件,您可以选择SVN,CVS,Darcs,TFS等),但是实际上它是完整的文件(因为它是二进制格式),这意味着“更改了什么”问题不太容易回答。

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


-1

我使用VBA编写了受版本控制的电子表格。它更适合于工程报告,在工程报告中,您需要多个人来处理材料明细表或明细表,然后在某个时间点要创建快照修订,以显示上一修订的添加,删除和更新。

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

所有代码均已解锁。

转速控制的电子表格

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.