架构问题 - VBA Excel宏还是VS Tools For Office?

4
我有一个客户的需求,我们需要从不同来源的PDF文件中“解析”出数据。我们提供的第一阶段解决方案是使用Able2Extract应用程序手动提取PDF文件中所需的列,并生成一个Excel文件。但这个Excel文件仍然很“脏”,因为它包含了大量的头部信息和我们不需要的额外字段等。因此,我们开发了一个应用程序来对这个“脏”Excel文件进行清理,只保留他们需要的3或4列,并将其整齐地排列在一起。
我们正在探索的第一个解决方案是使用VBA / Excel完成第二步。他们将输出的“脏”数据粘贴到Excel中,然后运行我们的清理宏。Excel非常适合这种工作-移动和清洗已经存在于Excel电子表格中的数据。我们使用一个特定的“源”文件进行了概念验证,效果很好。但问题是:这个脚本只适用于一个特定的文件类型和一个特定的来源。我们将有10个不同的来源,每个可能有3-10个不同的文件类型。这意味着最终我们可能会得到一个巨大的Excel宏,其中包含120个非常具体的“清理脚本”。因此,我担心长期的可维护性问题。我们还可能遇到以前从未见过的文件,这些文件可能会“破坏”我们的清理脚本,并需要快速重新部署/更改清理脚本...我从未使用过Visual Studio Tools for Office,并且对VBA Excel宏的经验很少-但是它似乎在这种情况下可能是一个好的选择。
您是否有类似经历的建议?巨大的VBA宏像这里可能会难以维护吗?VSTFO是一个好的选择,可以提供易于移动/清洗数据的功能,并具有可扩展性和健壮性吗?老实说,我的第一反应是使用纯.NET解决方案,从数据库中获取动态编译的脚本,使用我们的Syncfusion Excel API进行清理/清洗...但也许这有些过头了。

2
dferraro,Excel VBA 的一个“不好”的用途是尝试将其用作服务或服务器应用程序——我曾经尝试过。Excel 有很多不同的方式可以抛出对话框,在用户单击某些内容之前使应用程序无能为力(即使您已经禁止了对话框,这种情况仍可能发生,但没有对话框可供单击!),这使得尝试捕捉所有可能中断流程的对话框变成了一种打地鼠的练习。Excel 认为自己是一个桌面应用程序,不会轻易退出。 - Joel Goodwin
嗯...我明白了...所以如果我们想要完全自动化端到端,我们不能重复使用那些存在于VBA宏中的“清洗脚本”吗?那么VSTFO呢?我们能否在Windows服务中重复使用代码?或者VSTFO代码是否有类似的问题..?我猜不会,我们应该能够在服务中使用它,但是... - dferraro
1
将Excel(任何与Excel对象模型相关的引用)涉及到服务器进程中是存在问题的。通常它会表现为一个挂起的进程,没有错误消息,但你也可能会得到孤立的对话框等待用户输入 - 我曾经看到过一种情况,Excel Solver的对话框无法被抑制。随着Excel的最新版本的推出,这种情况可能已经得到改善(我没有使用比Excel 2003更晚的版本)。你仍然可以这样做,但要准备花费一些时间进行维护。 - Joel Goodwin
9个回答

3
VBA比VSTO容易处理得多。好吧,VBA可能不是一个很好的编程语言,但至少它提供了对Excel对象模型的底层访问。而基于VBA的解决方案通常比基于VSTO的解决方案更加稳定。
我建议使用VBA,如果您担心可维护性,请考虑将“清洗脚本”存储在单独的文件中。您可以选择:
(a) 每个清洗脚本一个Excel文件,每个文件都有一个相同名称的宏;您的插件可以加载(并执行代码)适用于任何给定输入文件的正确的Excel文件。
(b) 每个清洗脚本一个文本文件,每个文件都包含上述宏的文本;您的插件可以在运行时将其作为新模块导入 - 要么导入到自身,要么导入到临时工作簿中。这种方法效率较低,但与版本控制系统更兼容,因为您可以在两个Excel工作簿的模块之间进行差异比较,但在文本文件的版本之间进行差异比较更容易。
在这两种情况下,您可以将清洗脚本存储在共享文件夹中,以便在需要修改脚本时进行集中更新。

3

我喜欢用C#编程,但我讨厌VSTO。

我遇到的两个主要问题:

  • 你不能直接访问代码,因为它都被编译成DLL文件并附加到工作簿上,无法进行即时调试(对于小型RAD项目非常有用)。通过Visual Studio进行调试不能替代使用Excel VBA时随时调试的能力。

  • 你是在.NET环境下使用封装好的Excel VBA接口,而不是使用感觉本地的东西。你需要使用可怕的函数调用,比如 sheet.get_Range("A1:B1", System.Type.Missing);,其中Missing处于可选参数的位置。

很多人使用VSTO,但是经过多年在Excel VBA平台上的经验,我发现目前没有太多迁移的理由。但是如果你需要在C#/.NET中做一些很酷的事情,而在VBA中做不到(例如反射),那么请考虑迁移到VSTO。

你可以在VBA中编写非常好的代码;它因为是一个不会惩罚你编写糟糕代码的环境,所以受到了很多负面评价,任何人都可以涉足VBA。

这些可能只是一个经验丰富的VBA开发人员的抱怨,而不是VSTO。所以说,如果你不熟悉VBA,直接使用VSTO可能更好。我不确定微软未来会怎样处理VBA;VSTO被认为是未来。


我不认为我理解你关于调试的观点;在 VS 与 Office 中,调试工具的质量要好得多,我发现使用 VBA 编辑器非常痛苦。语法方面的观点是正确的,但有一些解决方法,如使用 VB.NET,或 VSTO 功能强大的工具。 - Mathias
1
这并不是关于质量本身的问题,而是我可以在用户桌面上出现问题时立即进行调试。放弃这一点并告诉用户我不能立即修复问题是相当困难的。 - Joel Goodwin

3
首先,无论如何您都需要使用“n”个清洗程序。事实上,Excel/VBA在维护此功能方面并不比许多其他平台差。
您可以使用Userform添加界面,或者玩自动检测游戏,输出任何它不理解的“新”文件格式。还有几种强大的错误处理方案可供选择,因此无需担心会出现问题。
一家石油公司曾支付我编写一个Excel应用程序,其中包括4个Userforms和超过5000行的VBA代码,作为辅助其会计师进行每月联合报告的工具。该应用程序被使用了4年之久,因为其界面非常熟悉且易于使用。
...很抱歉我这么啰嗦,但是有一种倾向是“看不起”VBA,因为很少有“真正的程序员”使用它...

谢谢回复。如果我选择VBA路线,长期来看会有什么现实限制?将来我可能需要完全优化这个应用程序,这本来应该是一个ASP.NET网站,它与Windows服务进行处理逻辑通信,可能使用WCF。但我不明白为什么我们不能为此创建桌面应用程序,如果有意义的话...在这种情况下,我们可能可以坚持使用VBA。在我的职业生涯中,我大部分时间都是XL宏的赏金猎人。 - dferraro
我的许多应用程序自动化了现有的业务流程,而这些流程都是在 Excel 中手动完成的...因此,我对使用它们的犹豫可能源于此 =) - dferraro
我已经在一个VBA应用程序中编写了10K行代码,但是我不能处理更多的行数。我发现使用服务会稍慢一些,因为涉及到进程间通信,但是对于较小的数据集来说,这不会是个问题。祝你的项目顺利! - caving
抱歉耽搁了,我一直不在。只要每个模块长度不超过65K字符,我从未遇到过任何严重的限制。如果一个模块超过16K字符,你可能需要进一步进行模块化...我使用WCF和进程间通信时遇到了严重的瓶颈。如果你需要Excel格式,最好的方法是使用Excel本身编写文件,并使用VBA处理它。 - caving
不要直接从VBA使用WCF,编写一个客户端的.NET或Java组件来处理序列化和异步回调。 - Anonymous Type

2

我认为你应该按照你的第一直觉操作。

尽管从数据库中提取动态编译的脚本听起来对我来说有点过度设计。我可能没有完全理解你的问题,因为我不确定从数据库中提取动态编译的脚本可以解决什么问题。

你已经拥有了Syncfusion Excel API,在第二步中,为什么不只是编写一个纯粹的.NET应用程序,使用Syncfusion加载和操作Excel文件并重新保存它们。当你遇到需要支持的新文件类型时,更新应用程序并重新分发即可。

这个解决方案可能要花费一些时间来开发,但是:

  1. 将完全在.NET中实现(我讨厌VBA)。
  2. 不会使用Excel作为服务器应用程序(另一个帖子已经指出Excel不是为此而构建的,并且MS基于其他帖子提到的原因建议不要这样做)。
  3. 根据我的经验,比VSTO(interop)和可能也比VBA快一个数量级。

2

我在Excel中编写了许多VBA函数,其中一些变得非常庞大和复杂。我认为维护它们并不比处理其他大型项目更难,除非人们不太了解VBA。 VBA为您提供了许多完成任务的方法,其中大多数并不是最优的。例如,如果您不非常小心,您将会有很多代码看起来像

Workbook("name").Sheets("name).Range(Cells(1,1),Cells(3,1)).Value = "Test"
Workbook("name").Sheets("name).Range(Cells(1,1),Cells(3,1)).Font.Bold = True
Workbook("name").Sheets("name).Range(Cells(1,1),Cells(3,1)).Font.Italics = True

应该是这样的:
With Workbook("name").Sheets("name).Range(Cells(1,1),Cells(3,1))
  .Value = "Test"
   With .Font
      .Bold = True
      .italics = True
   End With
End With

两种方式都能实现相同的功能,不过第二种应该会稍微更加高效(可能还有更好的例子),并且在我看来更容易维护。

话虽如此,如果你和你的团队有足够的经验编写良好的VBA代码,那么我认为这是一个好的选择。否则,为了长期可维护性,我建议考虑一种你更有经验的解决方案。


感谢lansinwd、Gary和Joel。正如我所说,我几乎没有任何VBA和VSTFO经验,但是团队的其他成员有VBA经验。看来你们解决了我对长期可维护性的担忧...但是当我们进入这个项目的第二阶段并希望完全自动化时怎么办?我可以使用Windows服务获取那些不干净的Excel输出,将其提供给我的宏,并获得“干净”的文件吗?容易吗?而且对于企业应用程序来说是否可扩展,还是一个黑客行为?例如,当应用程序完全自动化时,我能否轻松地重复使用这些“清洗脚本”? - dferraro
现在用户甚至不再使用Excel,而是通过ASP.NET Web应用程序上的按钮来完成操作,该应用程序与一个Windows服务进行通信,该服务执行工作并包含更多逻辑。 - dferraro
PDF产品能否将这些数据导出为CSV文件,而不是Excel文件?如果可以的话,我会考虑使用脚本语言(我是Perl的粉丝,但其他语言也可以)。因为这种工作正是它们非常有用的领域。完全自动化这种解决方案很容易,并且在可维护性方面与使用VBA差不多。 - Irwin M. Fletcher
转向脚本语言有什么好处呢? 团队中的每个人都是.NET开发人员,对其他语言的接触很少。如果我们想走“脚本”路线,难道我们不能只使用C#或VB.NET作为我们的脚本语言,并进行动态编译吗?这是我的第一反应... - dferraro
我同意,我只是这么说因为你提到了你认为那是过度杀伤力的。在所有的解决方案中,我相信你最好的长期战略应该是选择 .Net 路线,特别是考虑到你团队的技能组合。 - Irwin M. Fletcher

2
我不会在VBA中编写需要长期维护的任何内容,但如果是短期的话,VBA将是可以接受的。
在性能方面,VBA比.NET略快,但您会失去很多好用的功能,并且随着新版本的VSTO,像调试和完整OM访问的问题已经成为过去式。
如果所有的代码仅用于Excel OM操作,我仍然会考虑使用VBA,因为它稍微快一些,而且除了团队中提到的熟悉度混合之外,使用.NET没有明显的优势。
如果您正在使用其他库,则应使用.NET-主要原因是可以摆脱您需要添加的1/2十几个库依赖项,例如FSO、ADO、CDO等。
另一个常见的抱怨是,您必须从C#中使用get访问器,而且您必须经常使用Type.Missing。
在较新版本的.NET中,Type.Missing已经是过去时了。获取访问器问题仅出现在Interop库的早期版本中,并且我认为这是关于在C#中使用范围对象和范围属性的用法的常见误解。
我从未使用过访问器方法,一旦您为常见的Excel OM方法编写了一些包装器方法,您就不必再编写缺少参数了。显然,.NET 4.0有更好的解决此问题的方法。

AT,这些更改是多久之前进行的?我在这里使用的是针对Excel 2003的VS2005。需要升级到什么级别才能消除这些问题? - Joel Goodwin
对的,我再看了一下,似乎你需要 VS 2008 .net 3.5。 不过好消息是,你可以使用 VSTO 3.0 与 Office 2003,所以你只需要升级 Visual Studio。 另一个你需要的部分是 VSTO power tools 1.0 - 安装 Office interop 扩展库 PT_ExtLibs,你就可以获得扩展方法来解决很多以上问题。 - Anonymous Type

1

如果第二步最终需要成为一个服务,并且您愿意在前期投入更多时间(取决于您的交付时间表)并且您正在处理Open XML中的Excel(虽然旧的二进制格式也可以),请查看Open XML SDK,并查看Microsoft的推荐的Office文档服务器端自动化

如果您需要快速交付,VBA将帮助您实现目标。如果您想要一些易于打包和分发的东西,则需要更多的努力才能使用VSTO。如果您需要一个服务,请选择其他选项。


1

关于更广泛的问题,需要考虑以下几点:

  1. VBA IDE与Excel一起提供。如果您想让更广泛的人员编辑代码,则使用VSTO不太容易。
  2. 目前更多的人知道如何编写VBA而不是VSTO。
  3. 目前有更多的在线支持可用于VBA。
  4. VBA并不是为Office产品设计的除自动化语言外的其他东西。对于这一点来说,它非常适用,并且不会很快消失。微软意识到这是Office比OpenOffice更好的一点——财务部的肯不会坐下来用Eclipse开始输入Public Static Void Main。
  5. 一旦您想要像应用程序代码一样使用VBA,就会有相当大的限制。仅包含类库就很麻烦。如果这将被广泛分发,我会选择VSTO。

正如上面的帖子所述:5000行代码就是5000行代码,差不多就这样。

我不是VSTO的铁杆粉丝。 VBA适用于其预期的用途。没有必要重写它。如果您需要硬编码,请使用C#。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接