最快的方式来实时(未保存的)Excel数据和C#对象之间的接口

我想知道什么是最快的方式是从一个打开的Excel工作簿读取和写入数据到c#对象。背景是,我想开发一个从Excel使用的c#应用程序,并使用excel中保存的数据。

业务逻辑将驻留在c#应用程序中,但数据将驻留在Excel工作簿中。用户将使用Excel,并将单击按钮(或做类似的东西)在Excel工作簿启动c#应用程序。然后,c#应用程序将从excel工作簿读取数据,处理数据,然后将数据写回excel工作簿。
可能有许多数据块需要被读出并写回到excel工作簿,但是它们通常具有相对较小的尺寸,例如10行和20列。有时,可能需要处理大量的数据列表,大约50,000行和40列。

我知道这是比较容易做到说使用VSTO,但我想知道什么是最快的(但仍然健壮和优雅)的解决方案,并得到一个速度的想法。我不介意如果解决方案建议使用第三方产品或使用C。

显而易见的解决方案是使用VSTO或互操作,但我不知道什么性能与VBA,我目前正在使用读取的数据,或如果有任何其他解决方案。

这是在专家交流上发表的说,VSTO是显着慢于VBA,但这是几年前,我不知道性能是否有所改善。

http://www.experts-exchange.com/Microsoft/Development/VSTO/Q_23635459.html

谢谢。

如果C#应用程序是一个独立的应用程序,那么您将始终具有跨进程编组,这将覆盖您可以通过将语言从C#切换到C来执行的任何优化。在这种情况下,坚持你最喜欢的语言,听起来像是C#。

如果你愿意做一个加载项在Excel中运行,然而,你的操作将避免跨进程调用,运行速度快50倍。

如果在Excel中作为加载项运行,则VBA是最快的选项之一,但它仍然涉及COM,因此使用XLL加载项的C调用将是最快的。但是VBA在调用Excel对象模型方面仍然很快。然而,对于实际的计算速度,VBA作为pcode运行,而不是作为完全编译的代码,因此执行比本地代码慢约2-3x。这听起来很糟糕,但这不是因为使用典型的Excel加载项或应用程序所执行的绝大多数时间都涉及到对Excel对象模型的调用,因此VBA与完全编译的COM加载项相比,使用本地编译VB 6.0,只会慢约5-15%,这是不明显的。

VB 6.0是一种编译的COM方法,对于非Excel相关的调用,运行速度比VBA快2-3倍,但VB 6.0大约是12岁,并且不会以64位模式运行,比如说安装Office 2010,其可以安装运行32位或64位。 64位Excel的使用目前很小,但会增加使用,所以我会避免VB 6.0的原因。

C#,如果作为Excel加载项在过程中运行将像VBA一样快地执行对Excel模型的调用,并执行非Excel调用比VBA快2-3倍 – 如果运行未填充。然而,Microsoft推荐的方法是运行完全填充,例如,通过使用COM Shim Wizard.通过被填充,Excel是保护您的代码(如果它的错误),并且您的代码完全保护,免受其他第三方添加 – 否则可能会导致问题。然而,这一点的缺点是,shimmed解决方案运行在单独的AppDomain,这需要跨AppDomain封送,导致大约40x的执行速度惩罚 – 这在许多上下文非常明显。

使用Visual Studio Tools for Office(VSTO)的加载项将自动加载到垫片中,并在单独的AppDomain中执行。如果使用VSTO,没有避免这种情况。因此,调用Excel对象模型也会导致大约40x的执行速度降低。 VSTO是一个华丽的系统,使非常丰富的Excel加载项,但执行速度是它的弱点,为您的应用程序。

ExcelDna是一个免费的开源项目,允许您使用C#代码,然后将其转换为使用C代码的XLL加载项。也就是说,ExcelDna解析您的C#代码并为您创建所需的C代码。我没有自己使用它,但我熟悉的过程,这是非常令人印象深刻。 ExcelDna得到非常好的评论,从那些使用它。 [编辑:注意以下更正根据Govert的意见如下:“迈克 – 我想添加一个小的更正澄清Excel-Dna实施:所有的管理到Excel的胶水工程在运行时从您的托管程序集使用反射 – 那里是没有额外的预编译步骤或C代码生成。此外,即使Excel-Dna使用.NET,与Excel交谈时不需要任何COM互操作 – 作为.xll本机接口可以直接从.NET使用(虽然你也可以使用COM,如果你想),这使得高性能的UDF和宏可能。 – Govert]

你也可能想看看Add-in Express。它不是免费的,但它会允许你在C#代码,虽然它将你的解决方案融入一个单独的AppDomain,我相信它的执行速度是杰出的。如果我正确理解它的执行速度,那么我不知道Add-in Express如何做到这一点,但它可能正在利用一些名为FastPath AppDomain封送。不要引用我对任何这,但是,因为我不是很熟悉加载项Express。你应该检查一下,并做自己的研究。 [编辑:阅读Charles Williams的回答,看起来Add-in Express允许COM和C API访问。 Govert指出,Excel DNA也支持COM和fastrer C API访问。所以你可能想检查两者,并将其与ExcelDna比较。]

我的建议是研究Add-in Express和ExcelDna。两种方法都允许你使用C#代码,你看起来最熟悉。

另一个主要问题是你如何打电话。例如,当处理作为数组来回传递的整个范围的数据时,Excel非常快。这比单独循环单元有效得多。例如,以下代码使用Excel.Range.set_Value访问器方法将一个10 x 10的值数组分配给一次性的10 x 10个单元格范围:

void AssignArrayToRange()
{
    // Create the array.
    object[,] myArray = new object[10, 10];

    // Initialize the array.
    for (int i = 0; i < myArray.GetLength(0); i++)
    {
        for (int j = 0; j < myArray.GetLength(1); j++)
        {
            myArray[i, j] = i + j;
        }
    }

    // Create a Range of the correct size:
    int rows = myArray.GetLength(0);
    int columns = myArray.GetLength(1);
    Excel.Range range = myWorksheet.get_Range("A1", Type.Missing);
    range = range.get_Resize(rows, columns);

    // Assign the Array to the Range in one shot:
    range.set_Value(Type.Missing, myArray);
}

类似地,可以使用Excel.Range.get_Value访问器方法在一个步骤中从范围中读取值的数组。这样做,然后循环遍历数组中的值,比单独循环遍历该范围的单元格内的值快得多。

http://stackoverflow.com/questions/3840270/fastest-way-to-interface-between-live-unsaved-excel-data-and-c-sharp-objects

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:最快的方式来实时(未保存的)Excel数据和C#对象之间的接口