对MS Excel进行版本控制的最佳方法
您使用MS Excel(2003/2007)的版本控制系统? 你会推荐什么?为什么? 您使用最受好评的版本控制系统有什么限制吗?
为了说明这一点,下面是几个用例:
- VBA模块的版本控制
- 不止一个人正在使用Excel电子表格,他们可能正在对他们想要合并和整合的工作表进行更改。 这个工作表可能有公式,数据,图表等
- 用户不是太技术,使用的版本控制系统越less越好
- 空间约束是一个考虑因素。 理想情况下,只保存增量更改,而不是整个Excel电子表格。
我刚刚设置了一个使用Bazaar的电子表格,通过TortiseBZR手动签入/退出。 鉴于这个主题帮助我保存部分,我想在这里发布我的解决scheme。
我的解决scheme是创build一个电子表格,导出保存的所有模块,并删除并重新导入打开的模块。 是的,这对于转换现有的电子表格可能是潜在的危险。
这使我可以通过Emacs (是,emacs)在Excel中本地编辑模块中的macros,并在重大更改后提交我的BZR存储库。 因为所有的模块都是文本文件,所以BZR中的标准diff-style命令除了Excel文件本身之外,还可以用于我的源代码。
我为我的BZR存储库X:\ Data \ MySheet设置了一个目录。 在回购是我的每个模块(即:Module1Macros)MySheet.xls和一个.vba文件。 在我的电子表格中,我添加了一个免除名为“VersionControl”的导出/导入循环的模块。 每个要导出和重新导入的模块必须以“macros”结尾。
“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
接下来,我们必须设置事件钩子来打开/保存运行这些macros。 在代码查看器中,右键单击“ThisWorkbook”并select“查看代码”。 您可能需要拉下代码窗口顶部的select框,将其从“(常规)”视图更改为“工作簿”视图。
“工作簿”视图的内容:
Private Sub Workbook_Open() ImportCodeModules End Sub Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean) SaveCodeModules End Sub
我将在接下来的几周内安排到这个工作stream程中,如果我有任何问题,我会发布。
感谢分享VBComponent代码!
TortoiseSVN是Subversion版本控制系统中令人惊叹的Windows客户端。 我刚刚发现的一个特性是,当您单击以获取Excel文件版本之间的差异时,它将在Excel中打开这两个版本,并突出显示(以红色显示)已更改的单元格。 这是通过这里描述的vbs脚本的魔力来完成的。
即使不使用TortoiseSVN,您也可能会觉得这很有用。
这取决于您是在讨论数据,还是在电子表格中包含的代码。 虽然我非常不喜欢微软的Visual Sourcesafe,通常不会推荐它,但它很容易与Access和Excel集成,并提供模块的源代码控制。
[事实上,与Access的集成,包括查询,报告和模块作为可以版本化的单个对象]
MSDN链接在这里 。
我不知道有一个这样做的工具,但我已经看到了各种本土解决scheme。 这些的共同点是在版本控制下最小化二进制数据,并最大化文本数据以利用传统的scc系统的function。 去做这个:
- 像任何其他应用程序一样对待工作簿。 分开逻辑,configuration和数据。
- 与工作簿分开的代码。
- 以编程方式构build用户界面。
- 编写一个构build脚本来重build工作簿。
让我总结一下你想要的版本控制,为什么:
-
什么:
- 代码(VBA)
- 电子表格(公式)
- 电子表格(值)
- 图表
- …
-
为什么:
- 合作
- 版本比较(“差异”)
- 合并
- 使用方便
正如其他人在这里发布的,现有的版本控制系统上有几个解决scheme,例如:
- 混帐
- 水银
- 颠覆
- 市场
如果你唯一担心的是你的工作簿中的VBA代码,那么上面提到的方法Demosthenex或VbaGit( https://github.com/brucemcpherson/VbaGit )工作得非常好,而且实现起来相对简单。 优点是你可以依靠经过良好validation的版本控制系统,并根据你的需要select一个(看看https://help.github.com/articles/what-are-the-differences-between-svn-and -git /用于Git和Subversion之间的简单比较)。
棘手的一点是将其整合到用户的工作stream程和工具(Excel和VBE)中:例如,我经常点击“保存”,不会丢失任何工作; 如果这是一个重大的变化,我做“另存为”。 除非VBA在幕后出口有一些魔力,否则我很难改变我的工作stream程(我很懒惰)。
如果您不仅担心代码,而且还担心表单中的数据(“硬编码”值和公式结果),则可以使用类似的策略:将表单内容序列化为某种文本格式(通过Range.Value)并使用现有的版本控制系统。 这里有一个很好的博客文章: https : //wiki.ucl.ac.uk/display/~ucftpw2/2013/10/18/Using+git+for+version+control+of+spreadsheet+models+-+part + 1 + + 3
这种方法的缺点是差异和合并不会很好。 想象一下,你在两个版本之间添加一个空列。 由于Git,Subversion,Bazaar等将电子表格(二维)视为文本(一维),因此diff会产生与表格中行数一样多的变化量:从一维的angular度来看,每个variables都有一个变化,每一行(一列插入)。
想要比较公式时,情况会变得更加复杂:想象一下,单元格B1中的表单看起来像这样:
= A1 + 1
接下来,在第1行中添加一个空行,将B1中的公式转换为C1,然后调整将公式转换为:
= B1 + 1
如果您只是将其作为文本序列化,则会得到如下所示的差异:
+ - =A1+1 + =B1+1
对于它应该显示的内容来说,这是很多噪音:
+ = =B1+1
我们对单元格引用的改变不感兴趣,除非它暗示了一个实际修改的公式。
比较电子表格是一个不平凡的问题,取决于所选的algorithm,计算成本很高。 有几个很好的工具,比如微软的电子表格比较( 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 )。
缺点是,这些比较工具只解决了难题(差异)的一部分。 Sharepoint尽pipe有点沉重,但却提供了一个更全面的解决scheme,允许用户在某种程度上与他们的工作簿进行协作,版本跟踪和合并更改。 但是,它确实需要改变工作stream程,但通常是企业界的首选解决scheme。
最后(我真的不打算在这里做任何垃圾邮件),这个问题还有另一个解决scheme,我在过去的两年半里一直在努力:我试图解决这个问题
- 工作stream程整合
- 原生的二维Diffing
- 合作
在单一的解决scheme。 这是一个服务器/客户端应用程序(认为SVN / Turtoise或Git / GitHub)。 核心差异algorithm是“行/列alignment”algorithm的扩展( http://web.engr.oregonstate.edu/~scaffidc/papers/eu_20121001_ssdiff.pdf )。
我最近添加了公共项目(并且公共账户是免费的),以便于在社区中共享工作簿,公式/代码片段。 下面是一个这样的项目的例子(它把你带到表diff): https : //app.pathio.com/bjoernstiel/Column-Compare/sheets/Sheet1/versions/47b46863898aa0748a17c70345769ba1baba2795
致力于@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
让@Demosthenex的答案更进一步,如果你想跟踪你的Microsoft Excel对象和用户表单中的代码,你必须要有点棘手。
首先我改变了我的SaveCodeModules()
函数来说明我打算导出的不同types的代码:
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代码一样导出和导入。 唯一的区别是在导出表单时会创build两个文件(您将为每个UserForm获取.frm
和.frx
文件)。 其中一个保存你写的软件,另一个是一个二进制文件(我敢肯定)定义了表单的布局。
Microsoft Excel对象(MEOs)(即Sheet1
, Sheet2
, ThisWorkbook
等)可以导出为.cls
文件。 然而,当你想把这段代码放回到你的工作簿中时,如果你尝试像使用VBA模块一样导入它,如果工作簿中已经存在这个工作表,你将会得到一个错误。
为了解决这个问题,我决定不要尝试将.cls文件导入到Excel中,而是将.cls
文件作为string读入excel,然后将该string粘贴到空的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
input感到困惑,那只是你的代码库! 所以,你会像这样调用这些函数:
SaveCodeModules "C:\...\YourDirectory\Project\source\" ImportCodeModules "C:\...\YourDirectory\Project\source\"
你可以做的一件事是在你的工作簿中有下面的代码片段:
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
我在互联网上find了这个片段。
之后,您可以使用Subversion来维护版本控制。 例如,在VBA中使用Subversion的命令行界面和'shell'命令。 那会做。 我甚至想自己做这个:)
我使用git ,今天我将这个(git-xlsx-textconv)移植到Python,因为我的项目是基于Python代码的,并且与Excel文件交互。 这至less适用于.xlsx文件,但我认为它也适用于.xls 。 这里是 github链接。 我写了两个版本,每行一行在自己的行上,另一个版本在每行都在自己的行上(后者是因为git diff不喜欢在默认情况下包装长行,至less在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
使用任何标准的版本控制工具,如SVN或CVS。 局限性取决于目标是什么。 除了版本库的规模略有增加之外,我没有遇到任何问题
如果您正在寻找办公室设置与常规办公室非技术用户比Sharepoint是一个可行的select。 您可以设置启用版本控制的文档文件夹以及签入和签出。 对于普通的办公室用户来说,这是一个令人心动
为了响应mattlant的回复 – 只有在文档库中打开版本控制function的情况下,sharepoint才能很好地作为版本控制。 另外请注意,任何通过相对path调用其他文件的代码都不能工作。 最后,当文件保存在sharepoint时,任何指向外部文件的链接都会中断。
你应该尝试DiffEngineX。 它可以以编程方式调用,也可以通过命令行参数进行调用。 它不仅可以比较Excel电子表格单元,还可以embedded工作簿中的Visual Basicmacros。 还比较了Excel定义的名称和注释,很多免费软件工具都漏掉了。 它可以从中下载
http://www.florencesoft.com/excel-differences-download.html
我确定您的版本控制系统有一个选项或框,所以您可以自动调用DiffEngineX与您的原始和修改的Excel工作簿。
我也一直在看这个。 它认为最新的Team Foundation Server 2010可能有一个Excel加载项。
这是一个线索:
http://team-foundation-server.blogspot.com/2009/07/tf84037-there-was-problem-initializing.html
search年龄后,尝试了很多不同的工具,我发现我的答案在这里vba版本控制问题: https : //stackoverflow.com/a/25984759/2780179
这是一个简单的Excel插件,可以在这里find代码
导入后没有重复的模块。 只要保存您的工作簿,它就会自动导出您的代码, 而不修改任何现有的工作簿 。 它与一个vba代码格式化程序。
实际上,只有less数解决scheme能够跟踪和比较macros代码中的变化 – 其中大部分已经在这里命名了。 我一直在浏览网页,碰到这个值得一提的新工具:
用于VBAmacros的XLTools版本控制
- Excel工作表和VBA模块的版本控制
- 在提交版本之前预览和区别变化
- 非常适合同一文件上几个用户的协作工作(跟踪谁改变什么/何时/评论)
- 比较版本并逐行突出显示代码中的更改
- 适合那些不懂技术的用户,或者对于那些精通Excel的人
- 版本历史logging存储在您自己的PC上的Git-repository中 – 任何版本都可以轻松恢复
VBA代码版本并排,变化是可视化的
您可能已经尝试使用Microsoft的Excel XML压缩包(.xlsx和.xslm)进行版本控制,并发现vba存储在vbaProject.bin中(这对版本控制没用)。
解决scheme很简单。
- 用LibreOffice Calc打开excel文件
- 在LibreOffice Calc
- 文件
- 另存为
- 另存为types:ODF电子表格(.ods)
- closuresLibreOffice Calc
- 将新文件的文件扩展名从.ods重新命名为.zip
- 在GIT维护区域中为电子表格创build一个文件夹
- 解压缩到它的GIT文件夹
- 承诺GIT
当您使用电子表格的下一个版本重复此操作时,您必须确保将文件夹的文件与zip容器中的文件完全匹配(并且不要留下任何已删除的文件)。
还有一个名为Beyond Compare的程序,它有一个相当不错的Excel文件比较。 我用中文发现了一个截图,简要说明了这一点:
原始图像源
他们的网页上有30天的试用期
我公司在自动化Microsoft Office解决scheme方面做了大量工作,所以我写了一个.DLL文件,每次保存模板时都会导出解决scheme的源文件。 它创build一个名为Source的文件夹作为保存模板的文件夹的子文件夹,在Source下创build一个与VBA Project同名的文件夹。 在项目文件夹中,它将导出模块,类和用户表单的所有源代码。 select这种安排是为了便于pipe理大量模板集合的源代码。 如果您有本地configuration文件或全局configuration文件可用,该DLL能够解锁已locking的项目以获得对VBA项目的访问权限。 通过使用这个工具,开发人员可以将模板用于他们的内容,并使用他们最喜欢的修订控制工具来pipe理他们的工作。 我们主要在我们的环境中使用Git,我们保留完整的模板二进制文件以及版本控制下的VBA资源。
我想推荐一个名为Rubberduck的开源工具,它内置了VBA代码的版本控制。试试吧!
这取决于你想要什么级别的集成,我已经使用Subversion / TortoiseSVN这似乎罚款简单的用法。 我也添加了关键字,但似乎有文件损坏的风险。 在Subversion中有一个选项可以使关键字replace为固定长度,并且据我所知,如果固定长度是偶数但不是奇数,它将起作用。 在任何情况下,你都没有得到任何有用的差异function,我认为有商业产品,将做'差异'。 我确实发现了一些基于将内容转换为纯文本并进行比较的差异,但这并不是很好。
它应该与大多数VCS一起工作(取决于你可能selectSVN,CVS,Darcs,TFS等的其他标准),但它实际上是完整的文件(因为它是二进制格式),这意味着“什么改变”的问题是不容易回答。
如果用户完成日志信息,您仍然可以依赖日志消息,但是您也可以尝试使用Office 2007中基于XML的新格式来获得更多的可见性(尽pipe仍然很难清除大量XML,再加上AFAIK XML文件被压缩在磁盘上,所以你需要一个预先提交的钩子来解压缩文本差异才能正常工作)。
我使用VBA编写了一个修订版控制的电子表格。 它更适用于工程报告,其中有多个人员正在处理物料清单或计划,然后在某个时间点创build快照版本,以显示上一版本的增加,删除和更新。
注意:这是一个启用macros的工作簿,您需要login才能从我的网站下载(您可以使用OpenID)
所有的代码是解锁的。
修改受控电子表格