Как удалить невидимые символы и пробелы из строки в 1С?

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

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

Главная причина такого поведения — это наличие в строке символов, которые выглядят как пробелы или являются невидимыми, но по своему коду отличаются от обычного пробела (Символ(32)). Платформа 1С корректно обрабатывает символы по их числовому коду, и если мы пытаемся заменить одно значение, а в строке присутствует другое, функция СтрЗаменить() просто не сработает.

Пошаговая диагностика и идентификация проблемных символов

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

  1. Посимвольный анализ с выводом кодов:

    Это один из самых надежных способов. Мы будем последовательно перебирать каждый символ в строке и выводить его код. Таким образом, мы сможем увидеть, какой символ является "проблемным".

    
    ИсходнаяСтрока = "  Какая" + Символ(160) + "то" + Символ(0) + " строка " + Символ(9) + " с пробелами ";
    Сообщить("Исходная строка: """ + ИсходнаяСтрока + """");
    Сообщить("Длина исходной строки: " + СтрДлина(ИсходнаяСтрока));
            
    Для Индекс = 1 По СтрДлина(ИсходнаяСтрока) Цикл
        СимволСтроки = Сред(ИсходнаяСтрока, Индекс, 1);
        КодСимвола = КодСимвола(СимволСтроки);
        Сообщить("Символ: """ + СимволСтроки + """ (Код: " + КодСимвола + ")");
    КонецЦикла;
    

    После выполнения этого кода мы увидим список всех символов и их числовых кодов. Например, если обнаружится строка "Символ: "" (Код: 0)", это будет означать, что в строке присутствует нулевой символ.

  2. Визуальное копирование проблемного символа:

    Этот метод часто оказывается удивительно эффективным. Если мы видим в строке "пробел", который не реагирует на стандартную замену, мы можем просто скопировать его и вставить непосредственно в функцию СтрЗаменить().

    1. Откройте значение строки в отладчике 1С или выведите его в окно сообщений.
    2. Аккуратно выделите и скопируйте тот самый "пробел" или невидимый символ (например, с помощью Ctrl+C).
    3. Вставьте скопированное значение в качестве второго параметра в функцию СтрЗаменить().

    Пример:

    
    // Допустим, в строке "Моя строка с  проблемой" есть неразрывный пробел между "с" и "проблемой"
    // Визуально он выглядит как обычный пробел, но имеет код Символ(160)
            
    СтрокаСПроблемой = "Моя строка" + Символ(160) + "с проблемой"; // Пример создания такой строки
            
    // Попытка 1: Обычный пробел не помогает
    СтрокаБезПробелов_1 = СтрЗаменить(СтрокаСПроблемой, " ", ""); 
    Сообщить("Результат 1 (обычный пробел): """ + СтрокаБезПробелов_1 + """"); // Проблема останется
            
    // Попытка 2: Копируем неразрывный пробел и вставляем (визуально будет выглядеть как пробел)
    // Представим, что мы скопировали Символ(160) из "СтрокаСПроблемой"
    // Для примера, мы вставим его явно:
    СтрокаБезПробелов_2 = СтрЗаменить(СтрокаСПроблемой, Символ(160), ""); 
    Сообщить("Результат 2 (скопированный символ): """ + СтрокаБезПробелов_2 + """"); // Проблема решена
    

    Этот метод работает, потому что 1С воспринимает скопированный символ как его точное значение, независимо от того, как он отображается.

  3. Использование внешних текстовых редакторов:

    В некоторых случаях, когда символ совсем не отображается или его сложно выделить, можно прибегнуть к помощи продвинутых текстовых редакторов, таких как Sublime Text, VS Code или Notepad++. Скопируйте всю проблемную строку в такой редактор, затем скопируйте из него невидимый символ и вставьте его в СтрЗаменить() в 1С. Эти редакторы часто имеют функции, которые помогают визуализировать или определить коды непечатаемых символов.

Наиболее распространенные "невидимые" и специальные символы

На основе практики и дополнительной информации, мы можем выделить следующие часто встречающиеся проблемные символы, которые могут выглядеть как пробелы или быть полностью невидимыми:

Методы удаления нежелательных символов

После того как мы идентифицировали проблемные символы, нам необходимо их удалить. Рассмотрим несколько эффективных стратегий:

  1. Последовательное использование СтрЗаменить():

    Если нам известны коды нескольких нежелательных символов, мы можем последовательно вызывать функцию СтрЗаменить() для каждого из них. Этот подход прост и понятен.

    
    &НаКлиенте
    Процедура УдалитьПроблемныеСимволы()
        ИсходнаяСтрока = "  Начало" + Символ(160) + "строки" + Символ(0) + "с разными" + Символ(9) + "проблемами  ";
        Сообщить("Исходная строка: """ + ИсходнаяСтрока + """");
                
        // 1. Удаляем нулевой символ (Символ(0))
        ИсходнаяСтрока = СтрЗаменить(ИсходнаяСтрока, Символ(0), "");
                
        // 2. Заменяем неразрывный пробел (Символ(160)) на обычный пробел (Символ(32))
        ИсходнаяСтрока = СтрЗаменить(ИсходнаяСтрока, Символ(160), " ");
                
        // 3. Заменяем табуляцию (Символ(9)) на обычный пробел
        ИсходнаяСтрока = СтрЗаменить(ИсходнаяСтрока, Символ(9), " ");
                
        // 4. Удаляем символы переноса строк, если они не нужны
        ИсходнаяСтрока = СтрЗаменить(ИсходнаяСтрока, Символы.ПС, "");
        ИсходнаяСтрока = СтрЗаменить(ИсходнаяСтрока, Символы.ВК, "");
        ИсходнаяСтрока = СтрЗаменить(ИсходнаяСтрока, Символы.НС, "");
                
        // 5. Удаляем Символ(20), если он был обнаружен
        ИсходнаяСтрока = СтрЗаменить(ИсходнаяСтрока, Символ(20), "");
                
        // 6. Удаляем повторяющиеся пробелы, чтобы остался только один между словами
        Пока Найти(ИсходнаяСтрока, "  ") > 0 Цикл
            ИсходнаяСтрока = СтрЗаменить(ИсходнаяСтрока, "  ", " ");
        КонецЦикла;
                
        // 7. Обрезаем лишние пробелы по краям строки
        ИсходнаяСтрока = СокрЛП(ИсходнаяСтрока);
                
        Сообщить("Очищенная строка: """ + ИсходнаяСтрока + """");
    КонецПроцедуры
    

    Обратите внимание на последовательность: сначала удаляем или заменяем специфические символы, затем нормализуем обычные пробелы и обрезаем по краям.

  2. "Белый список" символов (фильтрация по разрешенным):

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

    
    &НаКлиенте
    Функция ОчиститьСтрокуПоБеломуСписку(ИсходнаяСтрока)
        РазрешенныеСимволы = "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщъыьэюя"
                            + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
                            + "0123456789 .,:;!?-()" + Символ(32); // Добавляем обычный пробел
                
        НоваяСтрока = "";
        Для Индекс = 1 По СтрДлина(ИсходнаяСтрока) Цикл
            СимволСтроки = Сред(ИсходнаяСтрока, Индекс, 1);
            Если СтрНайти(РазрешенныеСимволы, СимволСтроки) > 0 Тогда
                НоваяСтрока = НоваяСтрока + СимволСтроки;
            КонецЕсли;
        КонецЦикла;
        Возврат НоваяСтрока;
    КонецФункции
            
    Процедура ПримерОчисткиПоБеломуСписку()
        ИсходнаяСтрока = "Текст с" + Символ(160) + "неразрывным" + Символ(0) + "пробелом и" + Символ(9) + "табуляцией!";
        Сообщить("Исходная строка: """ + ИсходнаяСтрока + """");
                
        ОчищеннаяСтрока = ОчиститьСтрокуПоБеломуСписку(ИсходнаяСтрока);
        Сообщить("Очищенная строка по белому списку: """ + ОчищеннаяСтрока + """");
    КонецПроцедуры
    

    Этот метод очень robustный, так как он игнорирует все неизвестные и нежелательные символы, оставляя только то, что мы явно разрешили.

  3. Использование регулярных выражений (через COM-объекты):

    Для более сложных сценариев очистки, особенно когда требуется удалять символы по шаблону (например, все небуквенные и нецифровые символы, кроме некоторых), можно использовать регулярные выражения. В платформе 1С нет встроенных средств для работы с регулярными выражениями, но мы можем использовать COM-объекты, такие как VBScript.RegExp.

    
    // Этот код выполняется на сервере или в толстом клиенте с доступом к COM
    &НаСервере
    Функция ОчиститьСтрокуРегулярнымВыражением(ИсходнаяСтрока)
        Попытка
            RegExp = Новый COMОбъект("VBScript.RegExp");
            RegExp.Global = Истина; // Заменять все вхождения
            RegExp.IgnoreCase = Истина; // Игнорировать регистр (если применимо)
                    
            // Пример: Удалить все символы, которые НЕ являются буквами, цифрами или обычными пробелами
            // [^a-zA-Zа-яА-Я0-9\s] означает "любой символ, который НЕ входит в указанные диапазоны"
            // \s - это любой пробельный символ (включая обычный пробел, табуляцию, переводы строк)
            // Если нужно удалить все *специальные* пробелы, но оставить обычные и буквы/цифры:
            // [^a-zA-Zа-яА-Я0-9 ]|[\u00A0\u0000\u2000-\u200B\uFEFF]
            // Для простоты, удалим все "невидимые" пробелы и управляющие символы, оставим буквы, цифры, обычный пробел и основные знаки препинания.
            RegExp.Pattern = "[^a-zA-Zа-яА-Я0-9 .,:;!?-]"; // Удаляем все, что не буквы, цифры, пробел и знаки препинания
                    
            ОчищеннаяСтрока = RegExp.Replace(ИсходнаяСтрока, " "); // Заменяем на пробел
                    
            // Дополнительно удалим повторяющиеся пробелы и обрежем по краям
            RegExp.Pattern = "\s{2,}"; // Два и более пробельных символа
            ОчищеннаяСтрока = RegExp.Replace(ОчищеннаяСтрока, " ");
            ОчищеннаяСтрока = СокрЛП(ОчищеннаяСтрока);
                    
            Возврат ОчищеннаяСтрока;
        Исключение
            Сообщить("Ошибка при использовании регулярных выражений: " + ОписаниеОшибки());
            Возврат ИсходнаяСтрока; // В случае ошибки возвращаем исходную строку
        КонецПопытки;
    КонецФункции
            
    Процедура ПримерОчисткиРегулярнымВыражением()
        ИсходнаяСтрока = "Тест" + Символ(160) + "строки" + Символ(0) + "с" + Символ(9) + "разными" + Символы.ПС + "спец.символами!";
        Сообщить("Исходная строка: """ + ИсходнаяСтрока + """");
        ОчищеннаяСтрока = ОчиститьСтрокуРегулярнымВыражением(ИсходнаяСтрока);
        Сообщить("Очищенная строка (RegExp): """ + ОчищеннаяСтрока + """");
    КонецПроцедуры
    

    Использование регулярных выражений требует более глубокого понимания синтаксиса, но предоставляет максимальную гибкость в очистке строк. Важно помнить, что COM-объекты могут быть недоступны в некоторых средах (например, в тонком клиенте или веб-клиенте без дополнительных настроек).

Важность понимания происхождения символов

Подобные "проблемные" символы чаще всего появляются при:

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

Заключение

Проблема с "невидимыми" символами в строках 1С — это распространенное явление, с которым сталкиваются многие разработчики и пользователи. Мы рассмотрели различные методы диагностики, включая посимвольный анализ и копирование символа, а также предложили несколько подходов к их удалению: от последовательных вызовов СтрЗаменить() до более продвинутых техник с "белым списком" и регулярными выражениями. Выбор метода зависит от конкретной ситуации и степени неопределенности относительно типа проблемных символов. Главное — помнить, что для эффективного решения нужно сначала точно идентифицировать, что именно мы хотим удалить.

← На главную