Проверка работоспособности, если лист не содержит ошибок в C # Interop - PullRequest
0 голосов
/ 14 октября 2019

Нам нужно найти ошибки формул в большой рабочей книге, содержащей около 3 миллионов ячеек. Производительность имеет решающее значение. Мы реализовали функцию-обертку вокруг специальных ячеек, которая позволяет нам отлавливать исключение в случае отсутствия ячеек ошибок на этом листе. Аналогично:

Обработка «Ячейки не найдены». Ошибка в Excel

Но проблема в том, что проверка становится мучительно медленной, когда выдается исключение COM. Более конкретно, когда на листе есть хотя бы одна ошибка, мы записали время выполнения от 1 до 4 мс. Когда выдается ошибка, мы наблюдаем около 80 мс.

Есть ли у кого-нибудь креативная быстрая альтернатива проверке на отсутствие ошибок?

Наш код:

try
{
  dynamic cellsWithErrors = cells.SpecialCells(cellType, valueType);
  return cellsWithErrors;
}
catch (COMException)
{
  return null;
}         

Примечания:

  • Нахождение ошибок, когда они существуют, прекрасно, поэтому нет необходимости фокусироваться на этом.

  • Я уже обнаружил умеренное ускорение, используя вместо типов Range динамические типы

  • Наша проверка повторяет все листы во всей книге. Поэтому мы будем рады любому решению, которое также распространяется на всю книгу, но сомневаемся, что оно существует.

  • Мы пишем это как часть надстройки VSTO и используем слой Interop.

Решения уже рассмотрены

Мы могли читать весь диапазон как значения и перебирать его, но надеялись увидеть, есть ли что-то еще. Потому что в случае ошибок это будет медленнее.

Текущая идея

Так что загадка сводится к этому. С одной стороны, SpecialCells исключительно быстр, когда он находит результаты. Но исключение может привести к замедлению в 20–80 раз. С другой стороны, чтение всего используемого диапазона листа довольно стабильно с точки зрения производительности: я бы сказал, что оно линейно по числу ячеек с небольшим постоянным авансовым платежом. Теперь, проверяя значения ячеек, можно найти ошибки, используя ответ Майка Розенблюма: Как узнать, есть ли в ячейке ошибка в формуле в C # . Если так, то у нас был бы альтернативный способ проверки ошибок.

Идея состоит в том, чтобы написать главную функцию, которая поворачивается на размер рассматриваемого листа. Если это очень большой лист (у нас один с примерно 2 миллионами ячеек), то мы могли бы просто использовать SpecialCells и принять стоимость исключения, если оно произойдет. Но для меньших листов, где стоимость исключения превышает стоимость чтения во всем диапазоне и повторения его в памяти, мы должны просто сделать последнее.

Ключевую вещь, которую нам нужно определитьдля этого подхода и есть точка пересечения: где SpecialCells начинает превосходить чтение и итерацию? Мы также можем захотеть использовать наши собственные знания нашей рабочей книги, чтобы эвристически угадать, какие листы могут иметь ошибки, а какие нет. Я отправлю ответ, если мы его разработаем, и у меня будет время.

1 Ответ

0 голосов
/ 15 октября 2019

Оказывается, статистика производительности по вопросу ОП была неверной. Они были записаны в режиме отладки. Таким образом, реальный ответ на этот вопрос: не проводите тестирование в режиме отладки. Duh. В режиме отладки должна быть огромная стоимость обработки исключений, хотя мы заметили огромные различия на моей машине и на машине моего партнера по команде, поэтому, возможно, это мои локальные настройки отладки. Я уверен, что другие смогут прокомментировать больше.

Производительность true функции SpecialCells в среднем составляла 4 мс при работе вне режима отладки. Это было вполне приемлемо для нашего варианта использования. Тем не менее, мы уже провели рефакторинг нашего кода к тому времени, когда он был обнаружен, и фактически получили дальнейшее повышение производительности ...

Silver Lining

В итоге мы выбрали гибридное решение,Если на рассматриваемом листе было более 200_000 ячеек, мы просто использовали выноску SpecialCells, которая стоила в среднем 4 мс. Но если на листе было меньше этого числа ячеек, мы читали во всем используемом диапазоне и повторяли все его ячейки, проверяя типы ошибок, просматривая значения, аналогично ответу Майка Розенблюма: Какзнать, если в ячейке есть ошибка в формуле в C # . Стоимость обхода этих <200_000 ячеек в среднем для нас немного дешевле, чем вызов функции SpecialCells. Это снизило наше среднее значение с 4 до 3 мс. Скромный, но ускорение тем не менее. </p>

...