Самый быстрый способ взаимодействия между живыми (несохраненными) данными Excel и объектами C #

Я хочу знать, какой самый быстрый способ чтения и записи данных в открытую книгу Excel и из нее в объекты C #. Предыстория состоит в том, что я хочу разработать приложение на C #, которое используется из Excel и использует данные, хранящиеся в 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

Спасибо.


person jw_pr    schedule 01.10.2010    source источник


Ответы (6)


Если приложение 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
comment
По поводу скорости: это тоже мой опыт. VSTO может быть очень быстрым, если вы правильно его используете, то есть записываете сразу во все диапазоны. - person Francesco De Vittori; 04.10.2010
comment
Привет, Франческо, да, VSTO работает в отдельном домене приложений из Excel для защиты Excel и своей собственной. Но вызовы между доменами приложений примерно в 40 раз медленнее, чем стандартные вызовы, что очень заметно. Например, подпрограмма, которая раньше занимала 0,1 секунды, теперь займет 4,0 полных секунды. Поэтому я полностью согласен с тем, что в этом сценарии нужно быть еще более осторожным, чем когда-либо, чтобы переместить все данные за один раз, чтобы минимизировать вызовы объектной модели Excel. - person Mike Rosenblum; 04.10.2010
comment
Привет, Майк! Я хочу добавить небольшое исправление, чтобы прояснить реализацию Excel-Dna: все связующее звено между управляемым и Excel работает во время выполнения из вашей управляемой сборки с использованием отражения - нет дополнительного этапа предварительной компиляции или генерации кода C ++. Кроме того, даже несмотря на то, что Excel-Dna использует .NET, при разговоре с Excel не требуется участия какого-либо COM-взаимодействия - как .xll собственный интерфейс может использоваться непосредственно из .NET (хотя вы также можете использовать COM, если хотите). Это делает возможными высокопроизводительные UDF и макросы. - person Govert; 06.10.2010
comment
Привет, спасибо Govert за это прекрасное объяснение - я предположил реализацию и ошибся. Спасибо, что прояснили это. Я знал о возможностях API COM и C, но пренебрегал этим в моем описании выше, которое я исправлю сейчас. Спасибо, Говерт! - person Mike Rosenblum; 07.10.2010

Я приму это как вызов и готов поспорить, что самый быстрый способ перетасовать данные между Excel и C # - использовать Excel-DNA - http://excel-dna.net. (Отказ от ответственности: я разрабатываю Excel-DNA. Но это все еще правда ...)

Поскольку он использует собственный интерфейс .xll, он пропускает все накладные расходы на интеграцию COM, которые могут возникнуть при использовании VSTO или другой надстройки на основе COM. С помощью Excel-DNA вы можете создать макрос, который подключается к кнопке меню или ленты, которая считывает диапазон, обрабатывает его и записывает обратно в диапазон в Excel. И все это с использованием собственного интерфейса Excel из C #, а не COM-объекта в поле зрения.

Я сделал небольшую тестовую функцию, которая переводит текущий выбор в массив, возводит в квадрат каждое число в массиве и записывает результат на лист 2, начиная с ячейки A1. Вам просто нужно добавить (бесплатную) среду выполнения Excel-DNA, которую вы можете загрузить с http://excel-dna.net < / а>.

Я читаю в C #, обрабатываю и записываю обратно в Excel диапазон из миллиона ячеек менее чем за секунду. Это достаточно быстро для вас?

Моя функция выглядит так:

using ExcelDna.Integration;
public static class RangeTools {

[ExcelCommand(MenuName="Range Tools", MenuText="Square Selection")]
public static void SquareRange()
{
    object[,] result;
    
    // Get a reference to the current selection
    ExcelReference selection = (ExcelReference)XlCall.Excel(XlCall.xlfSelection);
    // Get the value of the selection
    object selectionContent = selection.GetValue();
    if (selectionContent is object[,])
    {
        object[,] values = (object[,])selectionContent;
        int rows = values.GetLength(0);
        int cols = values.GetLength(1);
        result = new object[rows,cols];
        
        // Process the values
        for (int i = 0; i < rows; i++)
        {
            for (int j = 0; j < cols; j++)
            {
                if (values[i,j] is double)
                {
                    double val = (double)values[i,j];
                    result[i,j] = val * val;
                }
                else
                {
                    result[i,j] = values[i,j];
                }
            }
        }
    }
    else if (selectionContent is double)
    {
        double value = (double)selectionContent;
        result = new object[,] {{value * value}}; 
    }
    else
    {
        result = new object[,] {{"Selection was not a range or a number, but " + selectionContent.ToString()}};
    }
    
    // Now create the target reference that will refer to Sheet 2, getting a reference that contains the SheetId first
    ExcelReference sheet2 = (ExcelReference)XlCall.Excel(XlCall.xlSheetId, "Sheet2"); // Throws exception if no Sheet2 exists
    // ... then creating the reference with the right size as new ExcelReference(RowFirst, RowLast, ColFirst, ColLast, SheetId)
    int resultRows = result.GetLength(0);
    int resultCols = result.GetLength(1);
    ExcelReference target = new ExcelReference(0, resultRows-1, 0, resultCols-1, sheet2.SheetId);
    // Finally setting the result into the target range.
    target.SetValue(result);
}
}
person Govert    schedule 05.10.2010
comment
Большое спасибо, Говерт! Это очень интересно и должно быть самым быстрым подходом! Ради интереса, есть ли какие-то ограничения у этого подхода по сравнению с другими подходами, которые мы обсуждали, которые вы могли бы придумать? Еще раз спасибо за очень поучительный ответ. - person jw_pr; 07.10.2010
comment
Я предполагаю, что использование собственного API требует некоторого привыкания, если у вас есть опыт работы только с VBA или VSTO, хотя Excel-Dna делает это намного проще, чем это было бы в C / C ++. Как и в случае с любым другим планом на основе .NET, вам необходимо рассмотреть возможность обфускации, если вы хотите защитить свой источник. Однако развертывание - это удовольствие - вы можете упаковать все (включая другие ваши библиотеки C #) в один файл .xll, чтобы пользователи могли его открыть. - person Govert; 09.10.2010
comment
+1 (Я бы проголосовал за это * 10, если бы мог, я нашел Excel-DNA неделю назад и, похоже, это было именно то программное обеспечение, которое мне не хватало для моей работы последние 5 лет) - person Doc Brown; 12.11.2010
comment
Отличная работа! Мне интересно, может ли Excel-DNA обрабатывать RichText в ячейках (с сохраненными форматами)? - person SOUser; 23.11.2012
comment
На самом деле я провел некоторое тестирование, и этот подход, похоже, дает те же результаты, что и использование set_Value из Interop. Хуже того - этот подход кажется намного проще, чем метод interop set_Value. Большое количество текстовых ячеек заполняет. (Оба подхода были протестированы изнутри плагина .Xll). - person Aleksander Fular; 06.03.2015
comment
Если я устанавливаю ячейку с selection.SetValue("=1+2"), она выводит строку, а не формулу. Есть ли способ заставить Excel рассматривать это как формулу, а не строку? - person Matthew Molloy; 15.03.2015

В дополнение к комментариям Майка Розенблюма об использовании массивов, я хотел бы добавить, что я использовал сам подход (массивы VSTO +), и когда я его измерил, фактическая скорость чтения была в пределах миллисекунд. Просто не забудьте отключить обработку событий и обновление экрана перед чтением / записью и не забудьте снова включить после завершения операции.

Используя C #, вы можете создавать массивы на основе 1 точно так же, как это делает сам Excel VBA. Это очень полезно, особенно потому, что даже в VSTO, когда вы извлекаете массив из объекта Excel.Range, массив основан на 1, поэтому сохранение ориентированных на Excel массивов на основе 1 помогает избежать необходимости всегда проверять, массив отсчитывается от единицы или от нуля. (Если позиция столбца в массиве имеет для вас значение, иметь дело с массивами, начинающимися с 0 и с 1, может быть настоящей проблемой).

Обычно чтение Excel.Range в массиве будет выглядеть примерно так:

var myArray = (object[,])range.Value2;


В моем варианте записи массива Майка Розенблюма используется массив на основе 1, например:

int[] lowerBounds = new int[]{ 1, 1 };
int[] lengths = new int[] { rowCount, columnCount };  
var myArray = 
    (object[,])Array.CreateInstance(typeof(object), lengths, lowerBounds);

var dataRange = GetRangeFromMySources();

// this example is a bit too atomic; you probably want to disable 
// screen updates and events a bit higher up in the call stack...
dataRange.Application.ScreenUpdating = false;
dataRange.Application.EnableEvents = false;

dataRange = dataRange.get_Resize(rowCount, columnCount);
dataRange.set_Value(Excel.XlRangeValueDataType.xlRangeValueDefault, myArray);

dataRange.Application.ScreenUpdating = true;
dataRange.Application.EnableEvents = true;
person code4life    schedule 04.10.2010
comment
Большое спасибо code4life, это очень полезно! Когда вы сказали, что разница в скорости чтения была минимальной, в пределах миллисекунд, вы имеете в виду по сравнению с VBA (потому что Майк отмечает, что вызовы между доменами приложений примерно в 40 раз медленнее, поэтому похоже, что VSTO будет намного медленнее, чем VBA при взаимодействии с Excel)? Между прочим, я все еще пытаюсь получить ответ от Add-In Express, дам вам знать, когда я получу ответ. Спасибо. - person jw_pr; 04.10.2010
comment
@jw_pr, я думаю, Майк совершенно прав в том, что говорит. Я думаю, вам нужно сократить количество вызовов VSTO до минимума. При этом, я думаю, фактическое манипулирование содержимым массива намного быстрее на стороне VSTO (но это анекдотично). - person code4life; 05.10.2010
comment
Я предполагаю, что это находится в диапазоне десятков миллисекунд при пересечении AppDomain с использованием VSTO. Но если у вас есть сетка 10x10 ячеек, 10 мс для обработки каждой ячейки составляют примерно 1 полную секунду для всей сетки из 100 ячеек. Это слишком медленно, и вы можете наблюдать за этим процессом невооруженным глазом. Вы также должны протестировать это на различных вызовах: установка значений, изменение форматирования и т. Д. - person Mike Rosenblum; 05.10.2010
comment
@Mike, я согласен, чем больше обращений к Excel, тем медленнее он работает. Я стараюсь свести мои вызовы (object [,]) Range.Value2 и Range.set_Value () к минимуму. Кроме того, повторение содержимого диапазона без использования массива является жестоким. - person code4life; 05.10.2010

Самый быстрый интерфейс для данных Excel - это C API. Существует ряд продуктов, которые связывают .NET с Excel с помощью этого интерфейса.

Мне нравятся 2 продукта: Excel DNA (бесплатная программа с открытым исходным кодом) и Addin Express (коммерческий продукт, имеющий как C API, так и интерфейс COM).

person Charles Williams    schedule 02.10.2010
comment
Спасибо. Я нашел еще одну ссылку на это здесь: wilmott.com/messageview.cfm?catid= 10 & threadid = 70379, однако я не уверен, можно ли читать данные из живого (несохраненного) файла Excel из приложения c # с помощью Addin Express? Вы знаете? Я задал вопрос на их сайте. Спасибо. - person jw_pr; 02.10.2010
comment
Addin Express определенно может читать или писать в несохраненную книгу Excel по желанию, без каких-либо вопросов. Более серьезная проблема заключается в том, насколько быстро он выполняется, но я верю, что это одновременно и решение с совместимостью, и работает шокирующе быстро, учитывая его наличие. Я могу ошибаться в этом, поэтому вам нужно провести собственное исследование и проверить время. См. Мой полный ответ по этому поводу, но я думаю, что главными претендентами на вас будут либо ExcelDna, либо Addin Express. - person Mike Rosenblum; 02.10.2010
comment
Вау, спасибо за исчерпывающий ответ, Майк! Я очень ценю это. Я исследую обоих претендентов, а также изучу другую информацию, которую вы мне дали. - person jw_pr; 02.10.2010
comment
Хорошо, звучит хорошо, отправьте ответ, когда закончите ... Мне было бы любопытно, что вы узнаете. Бьюсь об заклад, другие тоже. - person Mike Rosenblum; 03.10.2010

Во-первых, вашим решением не может быть Excel UDF (определяемая пользователем функция). В наших руководствах мы даем следующее определение: «UDF Excel используются для создания пользовательских функций в Excel, чтобы конечный пользователь мог использовать их в формулах». Не возражаю, если вы предложите определение получше :)

Это определение показывает, что UDF не может добавить кнопку в пользовательский интерфейс (я знаю, что XLL-файлы могут изменять пользовательский интерфейс CommandBar) или перехватывать сочетания клавиш, а также события Excel.

То есть ExcelDNA выходит за рамки, потому что он предназначен для разработки надстроек XLL. То же самое относится к функциональности надстройки Express, ориентированной на Excel, поскольку она позволяет разрабатывать надстройки XLL и надстройки автоматизации Excel.

Поскольку вам необходимо обрабатывать события Excel, ваше решение может быть автономным приложением, но у такого подхода есть очевидные ограничения. Единственный реальный способ - создать надстройку COM; он позволяет обрабатывать события Excel и добавлять пользовательские элементы в пользовательский интерфейс Excel. У вас есть три возможности:

  • ВСТО
  • Надстройка Express (функциональность надстройки COM)
  • Общая надстройка (см. Соответствующий пункт в диалоговом окне «Новый проект» в VS)

Если говорить о разработке надстройки Excel для COM, то три перечисленных выше инструмента предоставляют разные функции: визуальные конструкторы, регулировку шиммирования и т. Д. Но я не думаю, что они различаются по скорости доступа к объектной модели Excel. Скажем, я не знаю (и не могу представить), почему получение COM-объекта из Default AppDomain должно отличаться от получения того же COM-объекта из другого AppDomain. Кстати, вы можете проверить, влияет ли шиммирование на скорость работы, создав общую надстройку, а затем используя COM Shim Wizard, чтобы установить прокладку.

Скорость II. Как я писал вам вчера: «Лучший способ ускорить чтение и запись в диапазон ячеек - это создать переменную типа Excel.Range, ссылающуюся на этот диапазон, а затем читать / записывать массив из / в свойство Value. переменной ". Но вопреки тому, что говорит Франческо, я не приписываю это VSTO; это особенность объектной модели Excel.

Скорость III. Самые быстрые пользовательские функции Excel написаны на собственном C ++, а не на каком-либо языке .NET. Я не сравнивал скорость надстройки XLL, созданной ExcelDNA и надстройкой Express; Не думаю, что вы заметите здесь существенную разницу.

Подводить итоги. Я убежден, что вы ошиблись: надстройки COM, основанные на надстройке Express, VSTO или общей надстройке, должны читать и записывать ячейки Excel с одинаковой скоростью. Буду рад (искренне), если кто-то опровергнет это утверждение.

Теперь по другим вопросам. VSTO не позволяет разрабатывать надстройку COM, поддерживающую Office 2000-2010. Для полной поддержки Office 2003-2010 требуются три разных кодовых базы и как минимум две версии Visual Studio; вам нужно иметь крепкие нервы и немного удачи, чтобы развернуть надстройку на основе VSTO для Excel 2003. С помощью надстройки Express вы создаете надстройку COM для всех версий Office с единой базой кода; Add-in Express предоставляет вам проект установки, готовый для установки вашей надстройки в Excel 2000-2010 (32- и 64-разрядные версии); Развертывание ClickOnce также предусмотрено.

VSTO превосходит Add-in Express в одном: он позволяет создавать так называемые надстройки на уровне документа. Представьте себе книгу или шаблон с некоторым кодом .NET; Однако я не удивлюсь, если развертывание таких вещей станет кошмаром.

О событиях Excel. Все события Excel перечислены в MSDN, например, см. Excel События 2007 года

С уважением из Беларуси (GMT + 2),

Андрей Смолин Руководитель группы надстройки Express

person Andrei Smolin - Add-in Express    schedule 05.10.2010
comment
Большое спасибо Андрею за то, что разместил здесь свой ответ. Это проясняет мне проблему. Вы правы, что я не хочу использовать UDF, и теперь я понимаю разницу между VSTO и Add-In Express. Я также понимаю, что выбор не будет определяться скоростью. Понятно, что решение должно будет читать диапазоны вместо ячеек, и алгоритм должен будет оптимизировать (минимизировать) взаимодействие с Excel. Еще раз спасибо вам и всем, кто внес свой вклад в этот ответ! Джастин - person jw_pr; 05.10.2010
comment
То есть ExcelDNA выходит за рамки, потому что он предназначен для разработки надстроек XLL. ‹- Как показывает Говерт в своем сообщении выше, Excel-Dna определенно может обрабатывать команды меню, а не только UDF. - person Mike Rosenblum; 09.10.2010
comment
Скажем, я не знаю (и не могу представить), почему получение COM-объекта из Default AppDomain должно отличаться от получения того же COM-объекта из другого AppDomain. ‹- Маршаллинг между доменами приложений примерно на 80% дороже, чем вызовы между процессами. В прошлом я тестировал вызовы объектной модели Excel примерно в 40 раз медленнее при переходе между доменами приложений и примерно в 50 раз медленнее при перекрестном процессе. - person Mike Rosenblum; 09.10.2010
comment
Обратите внимание, что вызовы объектной модели Excel действительно богаты функциональностью и поэтому действительно дороги. Это означает, что стоимость маршалинга между доменами приложений относительно невысока по сравнению с полной стоимостью вызова - поэтому даже при 40-кратном снижении скорости это не так уж плохо по сравнению с упрощенными вызовами. через домен приложений. Обратите внимание на эту статью, в которой упоминается 1000-кратное замедление: Fast Marshaling для прокси-серверов между доменами приложений (codeproject.com/KB/dotnet/FastAppDomainMarshal.aspx?msg=3025184). - person Mike Rosenblum; 09.10.2010
comment
Надстройки COM, основанные на надстройке Express, VSTO или общей надстройке, должны читать и записывать ячейки Excel с одинаковой скоростью. Буду рад (искренне), если кто-то опровергнет это утверждение. ‹- VSTO выделен в отдельный AppDomain, и нет никакого способа обойти это. Управляемую надстройку COM не нужно использовать с оболочкой. Поскольку вы являетесь руководителем группы надстройки Express, может быть, вы сможете объяснить, как работает надстройка Express? Я предполагаю, что он работает в домене приложений по умолчанию при работе с C API и вставляется в отдельный домен приложений при работе с COM API? - person Mike Rosenblum; 09.10.2010
comment
Майк, извини, я только что нашел твои вопросы. Загрузчик надстройки Express обрабатывает IDTExtensibility2; он также создает прокси-класс для передачи вызовов OnConnection, OnDisconnection и т. д. модулю надстройки. Да, из-за мерцания надстройки Add-in Express обрабатывают эти события (их 5) медленнее. Тем не менее, когда загрузчик передает управление модулю надстройки, а модуль обрабатывает все события объектной модели приложения, междоменного маршалинга не происходит. Это потому, что вы подключаетесь к этим событиям в домене приложений самой надстройки, а не в домене DefaultAppdomain. - person Andrei Smolin - Add-in Express; 18.10.2010

Я использовал код VBA (макрос) для сбора и сжатия данных и получения этих данных за один вызов C # и наоборот. Вероятно, это будет наиболее эффективный подход.

Используя C #, вам всегда нужно будет использовать некоторый маршаллинг. При использовании VSTO или COM Interop нижележащий коммуникационный уровень (маршалинг накладных расходов) такой же.

В VBA (Visual Basic для приложений) вы работаете непосредственно с объектами в Excel. Так что доступ к этим данным всегда будет быстрее.

Но .... Если у вас есть данные на C #, обработка этих данных может быть намного быстрее.

Если вы используете VB6 или C ++, вы также используете COM-интерфейс, и вы также столкнетесь с кросс-процессным маршаллингом.

Итак, вы ищете способ минимизировать перекрестные вызовы процессов и маршалинг.

person GvS    schedule 01.10.2010
comment
Спасибо, в этом есть смысл. Проблема в том, что приложению C # потребуется загружать данные в реальном времени во время выполнения из открытого листа Excel, и я не знаю, какие данные ему понадобятся во время запуска процесса. Поэтому VSTO или COM кажутся единственными вариантами, но из вашего сообщения похоже, что выполнение будет намного медленнее, чем VBA. - person jw_pr; 01.10.2010
comment
Связь будет медленнее, но как только обработка данных в C #, вероятно, будет намного быстрее. - person GvS; 01.10.2010