При интеграции 1С с Microsoft Excel через COM-объект разработчики часто сталкиваются с задачами очистки и подготовки файлов: удалением лишних шапок, технических строк или пустых интервалов. На первый взгляд вызов методов удаления кажется простым, однако при передаче динамических переменных возникают трудноуловимые ошибки COM-объекта (например, 0x800a03ec) или синтаксические ошибки платформы 1С. Разберем по шагам, почему это происходит и как правильно реализовать удаление строк.
Проанализируем две ключевые проблемы, из-за которых код удаления строк в Excel дает сбой:
Строка(Число) платформа 1С по умолчанию форматирует числа с разделителями групп разрядов (неразрывными пробелами). Например, число 15000 превращается в "15 000". В итоге результирующий адрес диапазона принимает вид "A15:A15 000", который Excel не может обработать и возвращает исключительную ситуацию.Rows ожидает адресацию только по номерам строк (например, "15:150"), в то время как передача имени колонки "A15:A150" приводит к ошибке. Кроме того, свойство Selection относится к объекту самого приложения (ExcelApp.Selection), а попытка обратиться к нему через лист (Sheet.Selection) вызывает исключение.Рассмотрим рабочие варианты синтаксиса для удаления диапазона строк с учетом правильного форматирования числовых индексов.
Вариант 1. Использование метода Range с EntireRow
Это наиболее универсальный и надежный способ. Чтобы исключить пробелы-разделители, обязательно используем функцию Формат() с параметром ЧГ=0 либо функцию XMLСтрока():
ИндексНачала = 15;
ИндексКонца = 15000;
// Формируем строковый адрес без разделителей разрядов
СтрНачало = Формат(ИндексНачала, "ЧГ=0");
СтрКонец = Формат(ИндексКонца, "ЧГ=0");
АдресДиапазона = "A" + СтрНачало + ":A" + СтрКонец;
// Выполняем удаление строк целиком
Sheet.Range(АдресДиапазона).EntireRow.Delete();
Вариант 2. Адресация через коллекцию Rows
Если мы работаем напрямую с коллекцией Rows объекта листа, передавать буквы колонок нельзя — передаются только номера граничных строк через двоеточие:
СтрНачало = Формат(ИндексНачала, "ЧГ=0");
СтрКонец = Формат(ИндексКонца, "ЧГ=0");
Sheet.Rows(СтрНачало + ":" + СтрКонец).Delete();
Вариант 3. Использование метода Cells внутри Range (без строковых адресов)
Чтобы полностью избежать конкатенации строк и проблем с локализацией форматов, можно передавать объекты ячеек напрямую по их числовым координатам:
// Передаем номера строк и номер колонки напрямую в числах
Sheet.Range(Sheet.Cells(ИндексНачала, 1), Sheet.Cells(ИндексКонца, 1)).EntireRow.Delete();
Если в процессе обработки требуется удалить несколько разрозненных диапазонов или строк по данным таблицы значений, необходимо учитывать следующие архитектурные особенности:
Для Сч = -(КоличествоСтрок - 1) По 0 Цикл
ИндексТЗ = -Сч;
// Получение индексов и удаление диапазона
КонецЦикла;
ExcelApp.ScreenUpdating = Ложь;
ExcelApp.Calculation = -4135; // Константа xlCalculationManual (ручной пересчет)
ExcelApp.EnableEvents = Ложь;
// ... Блок удаления диапазонов ...
// Возвращаем исходные настройки
ExcelApp.ScreenUpdating = Истина;
ExcelApp.Calculation = -4105; // Константа xlCalculationAutomatic
ExcelApp.EnableEvents = Истина;
Workbook.Close(), ExcelApp.Quit() с последующим присвоением переменным значения Неопределено.Для ускорения обработки и обеспечения кроссплатформенности (например, при работе на сервере под Linux) часто эффективнее отказаться от COM-объекта в пользу встроенных механизмов платформы 1С:
ТабДок = Новый ТабличныйДокумент;
ТабДок.Прочитать(ПутьКФайлу, СпособЧтенияЗначенийТабличногоДокумента.Значение);
// Удаляем диапазон строк средствами 1С
ОбластьУдаления = ТабДок.Область(ИндексНачала, 1, ИндексКонца, ТабДок.ШиринаТаблицы);
ТабДок.УдалитьОбласть(ОбластьУдаления, ТипСмещенияТабличногоДокумента.ПоВертикали);
ТабДок.Записать(ПутьКФайлу, ТипФайлаТабличногоДокумента.XLSX);
Такой подход не требует наличия установленного Microsoft Excel на клиентском или серверном компьютере и отрабатывает существенно быстрее COM-вызовов.