Как исключить определенные строки при загрузке данных из Excel в 1С?

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

При написании обработок загрузки данных из внешних таблиц часто возникает задача пропустить определенные строки — например, товары из архивных папок, служебные заголовки или позиции со статусом «Не продавать». Если условие фильтрации составлено неверно, алгоритм загружает все строки без исключения или завершает работу с ошибкой. Разберем по шагам, почему возникает эта ошибка и как правильно отфильтровать строки при чтении файла.

Анализ типовой ошибки при проверке условий

Рассмотрим фрагмент кода, в котором разработчик пытается отфильтровать строки со значением группы «Архив»:


// Ошибочный вариант
Если ЗначениеЗаполнено(СокрЛП(Excel.Cells(СтрокаЕксель, КолонкаГруппы).Value)) = "Архив" Тогда 
    Прервать;
КонецЕсли;

В этом коде допущены сразу две логические ошибки:

  1. Несоответствие типов: системная функция ЗначениеЗаполнено() возвращает значение булева типа (Истина или Ложь). Сравнение логического типа со строкой "Архив" всегда возвращает Ложь, из-за чего блок условия никогда не выполняется.
  2. Неправильный оператор прерывания: оператор Прервать полностью останавливает выполнение цикла. Если строка с группой «Архив» встретится в середине списка, дальнейшее чтение файла прекратится. Чтобы пропустить только текущую итерацию и перейти к следующей строке, необходимо использовать оператор Продолжить.

Корректная фильтрация строк при обходе ячеек

Для корректного отбора сначала считаем строковое значение ячейки в переменную, очистим его от лишних пробелов, а затем выполним сравнение. Посмотрим на пример реализации:


ЗначениеГруппы = СокрЛП(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-соединения

Использование COM-технологии имеет существенные ограничения: необходимость установленного пакета MS Office, зависимость от Windows и низкую скорость при поячеечном считывании больших таблиц. Разберем альтернативные варианты:

  1. Использование объекта ТабличныйДокумент: начиная с платформы 8.3.6, поддерживается прямое чтение файлов Excel без внешних библиотек через вызов ТабДок.Прочитать(ИмяФайла, СпособЧтенияЗначенийТабличногоДокумента.Значение). Этот метод работает на любых операционных системах (включая Linux).
  2. Чтение диапазона в массив (COMSafeArray): если необходимо оставить работу через COM, чтение ускоряется в десятки раз, если выгрузить используемую область листа целиком через Лист.UsedRange.Value и производить проверку значений в памяти 1С.
← На главную