Если приложение C # является автономным приложением, то вы всегда будете задействованы в межпроцессном маршалинге, который сократит любые оптимизации, которые вы можете выполнить, переключая языки, скажем, с C # на C ++. В этой ситуации придерживайтесь своего наиболее предпочтительного языка, который звучит как C #.
Однако, если вы хотите создать надстройку, которая запускает в Excel, ваши операции позволят избежать межпроцессных вызовов и будут выполняться примерно в 50 раз быстрее.
Если вы запускаете в Excel как надстройку, то VBA является одним из самых быстрых вариантов, но он все еще включает COM, и поэтому вызовы C ++ с использованием надстройки XLL будут самыми быстрыми. Но VBA все еще довольно быстр с точки зрения обращений к объектной модели Excel. Что касается фактической скорости вычислений, однако, VBA работает как pcode, а не как полностью скомпилированный код, и поэтому выполняется примерно в 2-3 раза медленнее, чем собственный код. Это звучит очень плохо, но это не потому, что подавляющее большинство времени выполнения, затрачиваемого на обычную надстройку или приложение Excel, связано с вызовами объектной модели Excel, поэтому VBA против полностью скомпилированной надстройки COM, скажем, с использованием изначально скомпилированный VB 6.0 будет работать только на 5-15% медленнее, что не заметно.
VB 6.0 - это скомпилированный подход COM, который работает в 2-3 раза быстрее, чем VBA для вызовов, не связанных с Excel, но на данный момент VB 6.0 уже около 12 лет, и он не будет работать в 64-битном режиме, например, при установке Office 2010, который можно установить для запуска 32-разрядной или 64-разрядной версии. Использование 64-битного Excel на данный момент незначительно, но будет расти, поэтому по этой причине я бы отказался от VB 6.0.
C #, если при работе в качестве надстройки Excel выполняются вызовы объектной модели Excel так же быстро, как VBA, и выполняются вызовы, не относящиеся к Excel, в 2-3 раза быстрее, чем VBA - если выполняется без помех. Тем не менее, рекомендуемый Microsoft подход заключается в том, чтобы работать в полном режиме, например, с помощью COM Shim Wizard . Благодаря использованию Shimmed Excel защищен от вашего кода (если он неисправен), а ваш код полностью защищен от других сторонних надстроек, которые в противном случае могли бы вызвать проблемы. Недостатком этого является, однако, то, что решение с ограниченным доступом работает в отдельном домене приложений, что требует маршалинга между доменами приложений, что влечет за собой снижение скорости выполнения примерно в 40 раз, что очень заметно во многих контекстах.
Надстройки с использованием Visual Studio Tools for Office (VSTO) автоматически загружаются в оболочку и выполняются в отдельном домене приложения. Этого нельзя избежать при использовании VSTO. Следовательно, вызовы объектной модели Excel также могут привести к снижению скорости выполнения примерно в 40 раз. VSTO - великолепная система для создания очень богатых надстроек Excel, но скорость выполнения - ее слабость для таких приложений, как ваше.
ExcelDna - это бесплатный проект с открытым исходным кодом, который позволяет использовать код C #, который затем преобразуется для вас в надстройку XLL, использующую код C ++. То есть ExcelDna анализирует ваш код C # и создает для вас необходимый код C ++. Я не использовал это сам, но я знаком с процессом, и это очень впечатляет. ExcelDna получает очень хорошие отзывы от тех, кто его использует. [Редактировать: обратите внимание на следующее исправление в соответствии с комментариями Говерта ниже: «Привет, Майк. Я хочу добавить небольшое исправление, чтобы прояснить реализацию Excel-ДНК: все склейки от управляемого к Excel работают во время выполнения из управляемой сборки с использованием отражение - нет дополнительного этапа предварительной компиляции или генерации кода на C ++. Кроме того, хотя Excel-Dna использует .NET, при общении с Excel не требуется никакого COM-взаимодействия - в качестве .xll можно напрямую использовать собственный интерфейс из .NET (хотя вы также можете использовать COM, если хотите). Это делает возможными высокопроизводительные пользовательские функции и макросы ». - Говерт]
Вы также можете посмотреть на надстройку Express.Это не бесплатно, но это позволит вам кодировать на C #, и, хотя оно объединяет ваше решение в отдельный домен приложений, я считаю, что скорость его выполнения является выдающейся.Если я правильно понимаю скорость его выполнения, то я не уверен, как это делает Add-in Express, но он может воспользоваться преимуществами маршалинга FastPath AppDomain.Однако не цитируйте меня по этому поводу, поскольку я не очень знаком с надстройкой Express.Вы должны проверить это и сделать свое собственное исследование. [Редактировать: Читая ответ Чарльза Уильямса, похоже, что Add-in Express обеспечивает доступ к COM и C API.А Говерт заявляет, что Excel DNA также обеспечивает как COM, так и более быстрый доступ к C API.Так что вы, вероятно, захотите проверить оба и сравнить их с ExcelDna.]
Мой совет - изучить надстройку 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 для чтения массива значений из диапазона за один шаг.Выполнение этого и последующее циклическое переключение значений в массиве происходит намного быстрее, чем циклическое повторение значений в ячейках диапазона по отдельности.