Почему функция СокрЛП() в 1С не удаляет пробелы при загрузке данных из Excel?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

При интеграции 1С с внешними источниками, такими как таблицы Microsoft Excel, HTML-страницы или текстовые файлы, разработчики часто сталкиваются с ситуацией, когда стандартная функция СокрЛП() (а также СокрЛ() и СокрП()) визуально игнорирует начальные и конечные пробелы. В результате в информационную базу попадают строки с лишними отступами, что приводит к некорректному поиску элементов справочников по наименованию или ошибкам сопоставления артикулов.

В этой статье мы подробно разберем, почему возникает такое поведение, проанализируем внутренние механизмы платформы 1С и рассмотрим несколько надежных способов корректной очистки строк от любых пробельных и непечатаемых символов.

Выясняем причину: почему СокрЛП() не обрезает строку

Давайте проанализируем типовой фрагмент кода чтения ячейки Excel, в котором возникает ошибка:


Зн = НашЛист.Cells(i, 1).Value;
нЗн = СокрЛП(Зн);

Если после выполнения данного кода длина строки не изменилась и визуальные пробелы по краям остались на месте, причиной обычно является одна из следующих особенностей:

  1. Неразрывный пробел (Non-breaking space): Встроенная функция СокрЛП() платформы 1С удаляет исключительно стандартный пробел с кодом ASCII 32. В таблицах Excel, скопированных из веб-страниц, отчетов сторонних систем или текстовых редакторов, пробельные отступы очень часто представлены неразрывным пробелом с кодом 160 (в шестнадцатеричной системе — 0xA0). Так как для платформы 1С символ с кодом 160 является обычным печатным символом, функция СокрЛП() его не затрагивает.
  2. Прочие непечатаемые и управляющие символы: В начале или конце строки могут находиться знаки табуляции (код 9), переводы строк (коды 10 и 13), мягкие переносы (код 173) или маркеры последовательности байтов UTF-8 (BOM, код 65279). Все они воспринимаются функцией СокрЛП() как значащие символы текста.
  3. Запись в реквизит фиксированной длины: Если результат работы СокрЛП() сразу помещается в реквизит справочника или документа строкового типа с фиксированной длиной (например, Строка(50)), платформа автоматически дополняет строку обычными пробелами справа до указанной максимальной длины.

Чтобы убедиться в наличии неразрывных пробелов, проверим код первого или последнего символа строки с помощью встроенных функций КодСимв() и Сред():


СимволПервый = Сред(Зн, 1, 1);
Сообщить("Код первого символа: " + КодСимв(СимволПервый));

Если в окне сообщений вы увидите значение 160, значит, мы имеем дело с неразрывным пробелом, требующим предварительной обработки.

Способ 1. Замена неразрывного пробела через СтрЗаменить()

Самый простой и быстрый способ решения проблемы — заменить символ с кодом 160 на пустую строку или стандартный пробел перед вызовом СокрЛП().

Рассмотрим вариант с удалением символа 160:


ТекстЯчейки = НашЛист.Cells(i, 1).Text;
ОчищенныйТекст = СокрЛП(СтрЗаменить(ТекстЯчейки, Симв(160), ""));

Обратите внимание: если неразрывный пробел используется как разделитель слов внутри наименования (например, "Товар №1"), полное удаление символа 160 приведет к склеиванию слов ("Товар№1"). В таких ситуациях безопаснее сначала заменить символ 160 на обычный пробел, при необходимости свернуть повторяющиеся пробелы в один, а затем вызвать СокрЛП().

Посмотрим на пример безопасной нормализации строки:


ТекстЯчейки = НашЛист.Cells(i, 1).Text;

// Заменяем неразрывные пробелы на стандартные пробелы
ТекстЯчейки = СтрЗаменить(ТекстЯчейки, Симв(160), " ");

// Удаляем сдвоенные пробелы внутри текста
Пока Найти(ТекстЯчейки, "  ") > 0 Цикл
    ТекстЯчейки = СтрЗаменить(ТекстЯчейки, "  ", " ");
КонецЦикла;

// Обрезаем пробелы по краям
Результат = СокрЛП(ТекстЯчейки);

Способ 2. Функция пограничной обрезки символов

Когда требуется очистить строку по краям не только от пробелов и символа 160, но и от табуляций, переводов строк и других управляющих кодов, не затрагивая при этом структуру текста внутри строки, напишем собственную универсальную функцию обрезки.

Разберем алгоритм по шагам:

  1. Двигаемся от начала строки слева направо и ищем позицию первого значащего символа (код которого больше 32 и не равен 160).
  2. Двигаемся от конца строки справа налево и ищем позицию последнего значащего символа.
  3. С помощью функции Сред() извлекаем подстроку между найденными границами.

Посмотрим на реализацию такой функции в 1С:


Функция ОчиститьСтрокуПоКраям(Знач ВходнойТекст)
    Длина = СтрДлина(ВходнойТекст);
    Если Длина = 0 Тогда
        Возврат "";
    КонецЕсли;
    
    ПозНачала = 0;
    ПозКонца  = 0;
    
    // Поиск первого печатного символа слева
    Для Ном = 1 По Длина Цикл
        Код = КодСимв(Сред(ВходнойТекст, Ном, 1));
        Если (Код > 32) И (Код <> 160) И (Код <> 173) Тогда
            ПозНачала = Ном;
            Прервать;
        КонецЕсли;
    КонецЦикла;
    
    // Если строка состоит только из пробельных символов
    Если ПозНачала = 0 Тогда
        Возврат "";
    КонецЕсли;
    
    // Поиск первого печатного символа справа
    Для Ном = 0 По Длина - 1 Цикл
        Код = КодСимв(Сред(ВходнойТекст, Длина - Ном, 1));
        Если (Код > 32) И (Код <> 160) И (Код <> 173) Тогда
            ПозКонца = Длина - Ном;
            Прервать;
        КонецЕсли;
    КонецЦикла;
    
    Возврат Сред(ВходнойТекст, ПозНачала, ПозКонца - ПозНачала + 1);
КонецФункции

Способ 3. Очистка средствами Excel через COM-объект

Если чтение данных выполняется через COM-соединение с Excel, мы можем переложить задачу первичной очистки на сам табличный процессор с помощью встроенных функций листа Excel (объект WorksheetFunction):

  1. WorksheetFunction.Clean() — удаляет из текста все непечатаемые символы с кодами ASCII от 0 до 31 (включая табуляции и переводы строк).
  2. WorksheetFunction.Substitute() — выполняет быструю замену символа 160 на уровне движка Excel.
  3. WorksheetFunction.Trim() — в отличие от функции 1С, удаляет не только стандартные начальные и конечные пробелы, но и лишние пробелы между словами, оставляя строго по одному пробелу.

Рассмотрим пример использования:


ExcelApp = НашЛист.Application;
ЗначениеЯчейки = НашЛист.Cells(i, 1).Text;

// Заменяем неразрывный пробел на обычный и удаляем непечатаемые символы
ОчищенноеЗначение = ExcelApp.WorksheetFunction.Substitute(ЗначениеЯчейки, Симв(160), " ");
ОчищенноеЗначение = ExcelApp.WorksheetFunction.Clean(ОчищенноеЗначение);
ОчищенноеЗначение = ExcelApp.WorksheetFunction.Trim(ОчищенноеЗначение);

Результат = СокрЛП(ОчищенноеЗначение);

Способ 4. Использование регулярных выражений (VBScript.RegExp)

Для сложной обработки строковых данных удобно использовать системный COM-объект VBScript.RegExp. Он позволяет одним регулярным выражением удалить все типы пробелов и переводов строк по краям текста.


РегВыражение = СоздатьОбъект("VBScript.RegExp");
РегВыражение.Global = 1;
РегВыражение.Multiline = 1;

// Шаблон удаляет обычные пробелы, табуляцию, переносы (\s) и неразрывный пробел (\xA0) в начале и конце
РегВыражение.Pattern = "^[\s\xA0]+|[\s\xA0]+$";

ИсходнаяСтрока = НашЛист.Cells(i, 1).Text;
Результат = РегВыражение.Replace(ИсходнаяСтрока, "");

Итоги

Функция СокрЛП() работает строго по спецификации платформы и удаляет только базовый символ пробела (код 32). При импорте данных из Excel всегда учитывайте возможность наличия неразрывных пробелов (код 160). Для надежной работы обработок загрузки рекомендуется предварительно заменять символ 160 через СтрЗаменить() либо использовать универсальные функции пограничной обрезки.

← На главную