您在 MS Excel (2003/2007) 中使用了哪些版本控制系统?你会推荐什么,为什么?您发现您的顶级版本控制系统有哪些限制?
从这个角度来看,这里有几个用例:
- VBA 模块的版本控制
- 不止一个人在处理 Excel 电子表格,他们可能正在对同一个工作表进行更改,他们希望将其合并和集成。此工作表可能包含公式、数据、图表等
- 用户不太懂技术,使用的版本控制系统越少越好
- 空间限制是一个考虑因素。理想情况下,只保存增量更改而不是整个 Excel 电子表格。
您在 MS Excel (2003/2007) 中使用了哪些版本控制系统?你会推荐什么,为什么?您发现您的顶级版本控制系统有哪些限制?
从这个角度来看,这里有几个用例:
我刚刚设置了一个使用 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 代码!
TortoiseSVN是一个非常出色的用于 Subversion 版本控制系统的 Windows 客户端。我刚刚发现它具有的一个功能是,当您单击以获取 Excel 文件版本之间的差异时,它将在 Excel 中打开这两个版本并突出显示(以红色显示)已更改的单元格。这是通过此处描述的 vbs 脚本的魔力完成的。
即使不使用 TortoiseSVN,您也会发现这很有用。
让我总结一下您希望进行版本控制的内容以及原因:
什么:
为什么:
正如其他人在此处发布的那样,在现有版本控制系统之上有几个解决方案,例如:
如果您唯一关心的是工作簿中的 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。
这取决于您是在谈论数据还是电子表格中包含的代码。虽然我非常不喜欢 Microsoft 的 Visual Sourcesafe 并且通常不会推荐它,但它确实可以轻松地与 Access 和 Excel 集成,并提供模块的源代码控制。
[事实上与 Access 的集成,包括查询、报告和模块作为可以版本化的单独对象]
MSDN 链接在这里。
我不知道有什么工具可以很好地做到这一点,但我已经看到了各种本土解决方案。它们的共同点是最小化版本控制下的二进制数据并最大化文本数据以利用传统 scc 系统的强大功能。去做这个:
处理@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()
函数来解释我计划导出的不同类型的代码:
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\"
我使用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
您可以做的一件事是在您的工作簿中包含以下代码段:
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”命令。这样就可以了。我什至想自己做这个:)
我想推荐一个很棒的开源工具Rubberduck,它内置了 VBA 代码的版本控制。试试吧!
如果您正在寻找一个有普通办公室非技术用户的办公室环境,那么 Sharepoint 是一个可行的选择。您可以设置启用版本控制以及签入和签出的文档文件夹。让普通办公室用户更轻松。
回应 mattlant 的回复 - 只有在文档库中打开版本控制功能时,sharepoint 才能作为版本控制正常工作。另外请注意,任何通过相对路径调用其他文件的代码都不起作用。最后,当文件保存在 sharepoint 中时,任何指向外部文件的链接都会中断。
使用任何标准版本控制工具,如 SVN 或 CVS。限制将取决于目标是什么。除了存储库大小略有增加外,我没有遇到任何问题
我也一直在研究这个。似乎最新的 Team Foundation Server 2010 可能具有 Excel 加载项。
这是一个线索:
http://team-foundation-server.blogspot.com/2009/07/tf84037-there-was-problem-initializing.html
在搜索了年龄并尝试了许多不同的工具之后,我在这里找到了我对 vba 版本控制问题的答案:https ://stackoverflow.com/a/25984759/2780179
这是一个简单的 excel 插件,代码可以在这里找到
导入后没有重复的模块。只要您保存工作簿,它就会自动导出您的代码,而无需修改任何现有工作簿。它带有一个 vba 代码格式化程序。
实际上,只有少数解决方案可以跟踪和比较宏代码的变化——其中大部分已经在这里命名。我一直在浏览网页,发现了这个值得一提的新工具:
您可能已经尝试在 zip 容器(.xlsx 和 .xslm)中使用 Microsoft 的 Excel XML 进行版本控制,发现 vba 存储在 vbaProject.bin 中(这对版本控制没有用处)。
解决方案很简单。
当您对电子表格的下一个版本重复此操作时,您必须确保使文件夹的文件与 zip 容器中的文件完全匹配(并且不要留下任何已删除的文件)。
我找到了一个非常简单的解决方案来满足我的需求。我在所有宏的底部添加了一行,*.txt
每次运行时都会导出一个包含整个宏代码的文件。编码:
ActiveWorkbook.VBProject.VBComponents("moduleName").Export"C:\Path\To\Spreadsheet\moduleName.txt"
(在Tom's Tutorials上找到,其中还涵盖了一些设置,您可能需要让它工作。)
因为我总是在处理代码时运行宏,所以我保证 git 会接受这些更改。唯一烦人的部分是,如果我需要签出早期版本,我必须手动将其复制/粘贴*.txt
到电子表格中。
这取决于您想要什么级别的集成,我使用了 Subversion/TortoiseSVN,这对于简单的使用来说似乎很好。我还添加了关键字,但似乎存在文件损坏的风险。Subversion中有一个选项可以使关键字替换固定长度,据我所知,如果固定长度是偶数但不是奇数,它将起作用。在任何情况下,您都没有获得任何有用的差异功能,我认为有些商业产品会做“差异”。我确实找到了一些基于将内容转换为纯文本并进行比较的差异,但它不是很好。
它应该适用于大多数 VCS(取决于您可能选择 SVN、CVS、Darcs、TFS 等的其他标准),但它实际上是完整的文件(因为它是二进制格式),这意味着“发生了什么变化”的问题是没那么容易回答。
如果人们完成它们,您仍然可以依赖日志消息,但您也可以尝试 Office 2007 中基于 XML 的新格式以获得更多可见性(尽管仍然很难清除大量 XML,加上 AFAIK XML 文件压缩在磁盘上,因此您需要一个预提交挂钩来解压缩它以使文本差异正常工作)。
我使用 VBA 编写了一个版本控制的电子表格。它更适用于工程报告,其中您有多个人在处理物料清单或计划,然后在某个时间点您想要创建一个快照修订,显示上一个修订的添加、删除和更新。
注意:这是一个启用宏的工作簿,您需要登录才能从我的站点下载(您可以使用 OpenID)
所有代码都已解锁。