Если приложение 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. Благодаря оболочке Excel защищен от вашего кода (если он неисправен), а ваш код полностью защищен от других сторонних надстроек, которые в противном случае могут вызвать проблемы. Обратной стороной этого, однако, является то, что решение с совместимостью запускается в отдельном домене приложений, что требует маршалинга между доменами приложений, что приводит к снижению скорости выполнения примерно в 40 раз, что очень заметно во многих контекстах.
Надстройки, использующие Visual Studio Tools для Office (VSTO), автоматически загружаются в оболочку оболочки и выполняются в отдельном домене приложений. Этого нельзя избежать при использовании VSTO. Следовательно, вызовы объектной модели Excel также приведут к снижению скорости выполнения примерно в 40 раз. VSTO - великолепная система для создания очень богатых надстроек Excel, но скорость выполнения является ее слабым местом для таких приложений, как ваше.
ExcelDna - это бесплатный проект с открытым исходным кодом, который позволяет использовать код C #, который затем преобразуется для вас в надстройку XLL, использующую код C ++. То есть ExcelDna анализирует ваш код C # и создает для вас требуемый код C ++. Сам я не использовал его, но я знаком с процессом, и он очень впечатляет. ExcelDna получает очень хорошие отзывы от тех, кто ее использует. [Изменить: обратите внимание на следующее исправление в соответствии с комментариями Говерта ниже: «Привет, Майк! Я хочу добавить небольшое исправление, чтобы прояснить реализацию Excel-Dna: все связующее звено между управляемым и Excel работает во время выполнения из вашей управляемой сборки с использованием отражение - нет дополнительного этапа предварительной компиляции или генерации кода C ++. Кроме того, даже несмотря на то, что Excel-Dna использует .NET, при разговоре с Excel не требуется участия какого-либо COM-взаимодействия - как .xll собственный интерфейс может использоваться напрямую из .NET (хотя вы также можете использовать COM, если хотите). Это делает возможными высокопроизводительные UDF и макросы ». - Говерт]
Вы также можете посмотреть надстройку Express. Это не бесплатно, но это позволит вам писать код на C #, и, хотя он помещает ваше решение в отдельный домен приложений, я считаю, что скорость его выполнения выдающаяся. Если я правильно понимаю скорость его выполнения, то я не уверен, как надстройка Express это делает, но, возможно, он использует что-то, называемое маршалингом FastPath AppDomain. Однако не цитируйте меня по этому поводу, так как я не очень хорошо знаком с Add-in 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 для чтения массива значений из диапазона за один шаг. Выполнение этого и последующий цикл по значениям в массиве намного быстрее, чем цикл по значениям внутри ячеек диапазона по отдельности.
person
Mike Rosenblum
schedule
02.10.2010