(感觉同事小皮 + 。。。的提醒)
使用场景:
1. 老板让你做个工具,其中需求之是:调用Office的接口(VBA),并且做一些操作。你完成后,客户觉得有点慢,Boss Say: 能更快一点吗?
2. 如果你是一个VBA的爱好者,发现以前在Office中写VBA时,运行速度还不错,但为了给没有装VBA封装成一个exe后,发现速度看起来慢了一些?
为什么会这样?
1. 两个COM对象在交互时,其中的耗时是巨大的,如果在COM内部交互,则耗时是比较小。
2. 所以,我们在外部调用时,如果要提高速度,最好的方式就是将其核心部分(即与Office交互的部分)做成com加载项。这样,进程内调用速度就会快很多。
使用数字来说话。
代码:
C#
using Microsoft.Office.Interop.Excel;
using System.Diagnostics;
using System;
namespace onion_autotest
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(string.Format("外部调用的时间是: {0} 毫秒", ExternalFill()));
Console.WriteLine(string.Format("ComAddin调用的时间是: {0} 毫秒", ComAddInFill()));
Console.Read();
}
static long ComAddInFill()
{
Application app = new Application();
app.Visible = true;
app.Workbooks.Add();
Worksheet sht = app.ActiveWorkbook.Worksheets[1] as Worksheet;
Stopwatch watch = new Stopwatch();
watch.Start();//VBA的用法: application.COMAddIns("V8Test.Helper").Object.FillTest
Object obj = app.COMAddIns.Item("V8Test.Helper").Object;
obj.GetType().InvokeMember("FillTest", System.Reflection.BindingFlags.InvokeMethod,
null, obj, null);
watch.Stop();
return watch.ElapsedMilliseconds;
}
static long ExternalFill()
{
Application app = new Application();
app.Visible = true;
app.Workbooks.Add();
Worksheet sht = app.ActiveWorkbook.Worksheets[1] as Worksheet;
Stopwatch watch = new Stopwatch();
watch.Start();
for (int r = 1; r < 100; r++)
for (int c = 1; c < 25; c++)
sht.Cells[r, c] = "onion_autotest";
watch.Stop();
return watch.ElapsedMilliseconds;
}
}
}
VB:
Public Sub FillTest()
Dim sht, r, c
Set sht = g_obj_App.ActiveWorkbook.Worksheets(1)
For r = 1 To 100
For c = 1 To 25
sht.Cells(r, c) = "onion_autotest"
Next
Next
End Sub
如图:
注意:
1.以上代码,我们没有去优化代码,只是说明问题,如在VBA或C#代码上是完全可以优化的,比较数组的填充肯定比一个一个填的快,等。仅是为了说明问题。
2.如果与COM交互比较少时,速度不会有快6倍的差距,但如果交互越多,则速度提高越明显。