При написании обработок загрузки данных из внешних таблиц часто возникает задача пропустить определенные строки — например, товары из архивных папок, служебные заголовки или позиции со статусом «Не продавать». Если условие фильтрации составлено неверно, алгоритм загружает все строки без исключения или завершает работу с ошибкой. Разберем по шагам, почему возникает эта ошибка и как правильно отфильтровать строки при чтении файла.
Рассмотрим фрагмент кода, в котором разработчик пытается отфильтровать строки со значением группы «Архив»:
// Ошибочный вариант
Если ЗначениеЗаполнено(СокрЛП(Excel.Cells(СтрокаЕксель, КолонкаГруппы).Value)) = "Архив" Тогда
Прервать;
КонецЕсли;
В этом коде допущены сразу две логические ошибки:
ЗначениеЗаполнено() возвращает значение булева типа (Истина или Ложь). Сравнение логического типа со строкой "Архив" всегда возвращает Ложь, из-за чего блок условия никогда не выполняется.Прервать полностью останавливает выполнение цикла. Если строка с группой «Архив» встретится в середине списка, дальнейшее чтение файла прекратится. Чтобы пропустить только текущую итерацию и перейти к следующей строке, необходимо использовать оператор Продолжить.Для корректного отбора сначала считаем строковое значение ячейки в переменную, очистим его от лишних пробелов, а затем выполним сравнение. Посмотрим на пример реализации:
ЗначениеГруппы = СокрЛП(Excel.Cells(СтрокаЕксель, КолонкаГруппы).Value);
// Проверяем исключаемые значения
Если ЗначениеГруппы = "Архив" Или ЗначениеГруппы = "Не продавать" Тогда
Продолжить; // Пропускаем строку и переходим к следующей
КонецЕсли;
При выгрузках из внешних систем данные в ячейках могут содержать неразрывные пробелы или отличаться регистром букв. Чтобы фильтрация работала безотказно независимо от регистра написания («архив», «АРХИВ», «Архив») и скрытых символов, применим функции ВРег() и СтрЗаменить():
// Очищаем значение от неразрывных пробелов (код 160) и переводим в верхний регистр
ЗначениеГруппы = СокрЛП(Excel.Cells(СтрокаЕксель, КолонкаГруппы).Value);
ЗначениеГруппы = СтрЗаменить(ЗначениеГруппы, Символ(160), " ");
ЗначениеГруппы = ВРег(СокрЛП(ЗначениеГруппы));
Если ЗначениеГруппы = "АРХИВ" Или ЗначениеГруппы = "НЕ ПРОДАВАТЬ" Тогда
Продолжить;
КонецЕсли;
Соберем исправленный и дополненный алгоритм. Обратим особое внимание на корректное закрытие COM-соединения: для предотвращения зависания скрытых процессов EXCEL.EXE в диспетчере задач операционной системы необходимо обязательно вызывать метод Quit() внутри блока Попытка ... Исключение.
Процедура ЗагрузитьИзExcel(Команда)
Объект.ТабличнаяЧастьДанные.Очистить();
Если ПустаяСтрока(Объект.ИмяФайла) Тогда
Сообщить("Не выбран файл для загрузки!", СтатусСообщения.ОченьВажное);
Возврат;
КонецЕсли;
Попытка
Excel = Новый COMОбъект("Excel.Application");
Исключение
Сообщить("Не удалось запустить Microsoft Excel. Проверьте установку приложения.");
Возврат;
КонецПопытки;
Попытка
Excel.DisplayAlerts = Ложь;
Excel.ScreenUpdating = Ложь;
Книга = Excel.Workbooks.Open(Объект.ИмяФайла);
КоличествоЛистов = Книга.Sheets.Count;
КолонкаГруппы = 1;
КолонкаАртикул = 2;
КолонкаНаименование = 3;
КолонкаЕдИзмерениеВеса = 6;
КолонкаСтавкаНДС = 35;
КолонкаРознечнаяСтавкаНДС = 35;
КолонкаКодМодификации = 40;
Для НомераЛиста = 1 По КоличествоЛистов Цикл
Лист = Книга.Sheets(НомераЛиста);
// Определяем последнюю заполненную строку
ФайлСтрок = Лист.Cells(1, 1).SpecialCells(11).Row;
Для СтрокаЕксель = 2 По ФайлСтрок Цикл
Наименование = СокрЛП(Лист.Cells(СтрокаЕксель, КолонкаНаименование).Value);
// Если наименование пустое — завершаем обработку текущего листа
Если Не ЗначениеЗаполнено(Наименование) Тогда
Прервать;
КонецЕсли;
// Считываем и нормализуем группу для проверки
ЗначениеГруппы = СокрЛП(Лист.Cells(СтрокаЕксель, КолонкаГруппы).Value);
ЗначениеГруппы = СтрЗаменить(ЗначениеГруппы, Символ(160), " ");
ГруппаВРег = ВРег(СокрЛП(ЗначениеГруппы));
// Пропускаем строки с архивными данными
Если ГруппаВРег = "АРХИВ" Или ГруппаВРег = "НЕ ПРОДАВАТЬ" Тогда
Продолжить;
КонецЕсли;
НовСтр = Объект.ТабличнаяЧастьДанные.Добавить();
НовСтр.Группа = ЗначениеГруппы;
НовСтр.Артикул = СокрЛП(Лист.Cells(СтрокаЕксель, КолонкаАртикул).Value);
НовСтр.КодМодиФикации = СокрЛП(Лист.Cells(СтрокаЕксель, КолонкаКодМодификации).Value);
НовСтр.Наименование = Наименование;
НовСтр.ЕдИзмерениеВеса = СокрЛП(Лист.Cells(СтрокаЕксель, КолонкаЕдИзмерениеВеса).Value);
НовСтр.СтавкаНДС = СокрЛП(Лист.Cells(СтрокаЕксель, КолонкаСтавкаНДС).Value);
НовСтр.РознечнаяСтавкаНДС = СокрЛП(Лист.Cells(СтрокаЕксель, КолонкаРознечнаяСтавкаНДС).Value);
КонецЦикла;
КонецЦикла;
Книга.Close(Ложь);
Исключение
Сообщить("Ошибка при обработке файла: " + ОписаниеОшибки(), СтатусСообщения.Важное);
КонецПопытки;
// Корректное завершение процесса Excel
Если Excel <> Неопределено Тогда
Excel.Quit();
Excel = Неопределено;
КонецЕсли;
КонецПроцедуры
Использование COM-технологии имеет существенные ограничения: необходимость установленного пакета MS Office, зависимость от Windows и низкую скорость при поячеечном считывании больших таблиц. Разберем альтернативные варианты:
ТабличныйДокумент: начиная с платформы 8.3.6, поддерживается прямое чтение файлов Excel без внешних библиотек через вызов ТабДок.Прочитать(ИмяФайла, СпособЧтенияЗначенийТабличногоДокумента.Значение). Этот метод работает на любых операционных системах (включая Linux).Лист.UsedRange.Value и производить проверку значений в памяти 1С.