При импорте данных, интеграции со сторонними системами или ручном вводе информации пользователи часто сталкиваются с ситуацией, когда в ключевых полях (например, в артикулах или наименованиях номенклатуры) появляются лишние символы. Одним из самых «капризных» символов является обычная прямая кавычка. Ее наличие в строке может полностью заблокировать стандартный поиск в базе данных, например, через метод НайтиПоРеквизиту, или нарушить сопоставление номенклатуры при обмене данными.
В рамках этой статьи мы подробно разберем, почему возникает эта проблема, как устроена работа со строковыми литералами в платформе 1С, и рассмотрим несколько эффективных способов удаления или замены кавычек в коде — от простых встроенных функций до регулярных выражений и системных механизмов БСП.
Для начала проанализируем ситуацию, с которой часто сталкиваются разработчики. Допустим, у нас есть артикул вида ПС03" или строка, где кавычки обрамляют значение: "ПС03". Если мы попытаемся выполнить поиск элемента в справочнике стандартным методом НайтиПоРеквизиту, система может вернуть пустую ссылку, даже если элемент с таким артикулом физически присутствует в базе данных.
Основная сложность для начинающих программистов заключается в синтаксисе самого языка 1С. Поскольку двойная кавычка является служебным символом, определяющим начало и конец текстовой строки, мы не можем просто так написать ее внутри строкового литерала. Давайте разберем по шагам, как компилятор 1С воспринимает текстовые строки.
Для того чтобы система поняла, что кавычка внутри текста — это не признак окончания строки, а обычный текстовый символ, применяется правило экранирования. В языке 1С роль экрана выполняет сама же кавычка. Это означает, что для получения одной кавычки внутри строки ее необходимо удвоить.
Посмотрим на пример объявления переменной, содержащей ровно один символ кавычки:
МояКавычка = """";
Давайте разберем, почему здесь именно четыре кавычки подряд:
Если нам нужно описать строку, внутри которой находится текст в кавычках (например, Кабель "нг-LS"), код будет выглядеть следующим образом:
ИмяНоменклатуры = "Кабель ""нг-LS""";
Понимая это базовое правило платформы, мы можем перейти к практическим вариантам решения проблемы очистки строк.
Самый очевидный и простой способ избавиться от ненужных символов — применить встроенную функцию СтрЗаменить. Она производит поиск всех вхождений подстроки поиска и заменяет их на подстроку замены.
Если перед нами стоит задача полностью удалить все кавычки из переменной, мы должны передать в качестве подстроки поиска экранированную кавычку, а в качестве подстроки замены — пустую строку "".
Рассмотрим пример кода:
ИсходныйАртикул = СтрТч["НоменклатураАртикул"];
ОчищенныйАртикул = СтрЗаменить(ИсходныйАртикул, """", "");
В данном случае строка """" (состоящая из четырех кавычек) передает в функцию символ одинарной прямой кавычки. Функция находит все такие символы в переменной ИсходныйАртикул и безжалостно заменяет их на пустую строку, фактически удаляя их.
Преимущества метода: работает чрезвычайно быстро на уровне платформы, не требует подключения сторонних библиотек и модулей.
Недостатки метода: конструкция с четырьмя кавычками визуально перегружена. При чтении кода легко запутаться в количестве кавычек, что часто приводит к синтаксическим ошибкам при разработке.
Чтобы избежать путаницы с подсчетом кавычек в коде и сделать его максимально понятным для любого разработчика (включая тех, кто будет сопровождать вашу конфигурацию в будущем), мы рекомендуем использовать встроенную функцию Символ.
Каждый символ имеет свой уникальный код в таблице ASCII/Unicode. Символ прямой кавычки имеет код 34. Таким образом, обращение к Символ(34) вернет нам чистую кавычку без необходимости городить сложные конструкции с экранированием.
Давайте посмотрим на пример кода с использованием этого подхода:
ИсходныйАртикул = СтрТч["НоменклатураАртикул"];
ОчищенныйАртикул = СтрЗаменить(ИсходныйАртикул, Символ(34), "");
Этот код выполняет абсолютно ту же работу, что и классический вариант в первом решении, но читается он в разы легче. Вы сразу видите, какой именно символ подлежит замене, и застрахованы от случайных синтаксических ошибок, связанных с пропущенной кавычкой в конфигураторе.
Если вы работаете в любой типовой конфигурации 1С (будь то «1С:ERP», «1С:Комплексная автоматизация», «1С:Управление торговлей» или «1С:Бухгалтерия»), то в вашем распоряжении находится мощный инструмент — Библиотека Стандартных Подсистем (БСП).
В БСП предусмотрен специальный общий модуль СтроковыеФункцииКлиентСервер, содержащий множество полезных методов для работы с текстом. Проанализируем типичную проблему: при импорте данных артикул может приходить в виде "ПС03" (в кавычках по краям). Если мы применим обычный метод СтрЗаменить, то удалим абсолютно все кавычки. Но что, если кавычки внутри названия нам важны? Например, наименование Кабель "нг-LS" 3х2.5 после тотальной очистки превратится в Кабель нг-LS 3х2.5, что нарушит стандарты обозначения номенклатуры.
Для решения этой проблемы в БСП есть специализированный метод, который удаляет кавычки только по краям строки, не затрагивая содержимое внутри нее. Разберем этот пример:
ИсходноеЗначение = СтрТч["НоменклатураАртикул"];
// Метод удаляет двойные кавычки в начале и в конце строки, если они там есть
ОчищенноеЗначение = СтроковыеФункцииКлиентСервер.СократитьДвойныеКавычки(ИсходноеЗначение);
Применение готовых методов БСП позволяет писать более надежный код, сохраняя внутреннюю структуру данных в целостности. Для реализации различных специализированных строковых операций также можно использовать набор функций для расширенной работы со строками в 1С.
Иногда бизнес-требования не позволяют полностью избавиться от кавычек, так как они необходимы для корректного отображения названий брендов, стандартов или контрагентов в печатных формах документов. При этом технические прямые кавычки " выглядят неэстетично и могут мешать алгоритмам выгрузки данных.
Отличным выходом является автоматическая замена некрасивых прямых кавычек на правильные типографские «ёлочки» (« и »). Простая замена всех символов на один вид кавычек не подойдет — мы получим некорректный текст вида «Номенклатура«. Нам необходим алгоритм, который будет отслеживать парность кавычек: нечетные кавычки делать открывающими, а четные — закрывающими.
Давайте разберем по шагам функцию, реализующую этот алгоритм:
Функция ЗаменитьКавычкиНаЕлочки(ВходнаяСтрока) Экспорт
Результат = "";
Открыта = Ложь;
Для Индекс = 1 По СтрДлина(ВходнаяСтрока) Цикл
ТекущийСимвол = Сред(ВходнаяСтрока, Индекс, 1);
Если ТекущийСимвол = Символ(34) Тогда
Если Открыта Тогда
Результат = Результат + "»";
Открыта = Ложь;
Иначе
Результат = Результат + "«";
Открыта = Истина;
КонецЕсли;
Иначе
Результат = Результат + ТекущийСимвол;
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Данная функция последовательно перебирает каждый символ строки. При обнаружении прямой кавычки программа проверяет статус переменной Открыта. Если кавычка еще не была открыта, система вставляет символ « и фиксирует открытие. Следующая встреченная кавычка закроет пару символом ».
В некоторых случаях стандартных функций работы со строками становится недостаточно. Представим ситуацию: нам нужно удалить кавычку только в том случае, если она стоит в самом конце строки после цифр (например, в конце артикула ПС03"), но при этом мы хотим оставить нетронутыми кавычки в середине строки.
Для реализации такой сложной логики идеально подходят регулярные выражения. В платформе 1С для этого можно использовать COM-объект VBScript.RegExp (обратите внимание, что данный метод работает на операционных системах семейства Windows).
Рассмотрим пример использования регулярных выражений для удаления кавычки на конце строки:
// Создаем объект для работы с регулярными выражениями
RegExp = Новый COMОбъект("VBScript.RegExp");
RegExp.IgnoreCase = Истина;
RegExp.Global = Истина;
// Задаем шаблон поиска: кавычка, после которой следует конец строки ($)
RegExp.Pattern = """$";
ИсходныйАртикул = СтрТч["НоменклатураАртикул"];
// Выполняем замену найденного шаблона на пустую строку
Результат = RegExp.Replace(ИсходныйАртикул, "");
Использование регулярных выражений существенно расширяет возможности разработчика по валидации и очистке текстовых полей при интеграции 1С с внешними информационными системами.
Возвращаясь к исходной проблеме автора темы: почему поиск через метод НайтиПоРеквизиту не приносил результатов? Дело в том, что при передаче параметров в методы объектной модели платформы строки с кавычками могут интерпретироваться некорректно в зависимости от контекста выполнения кода.
Если вам необходимо найти элемент справочника по реквизиту (например, по артикулу), и вы знаете, что в значении могут содержаться кавычки или другие спецсимволы, самым надежным и профессиональным решением будет использование полноценного механизма Запросов.
Когда вы передаете искомую строку в качестве параметра запроса, СУБД обрабатывает это значение «как есть». Платформе и базе данных абсолютно не мешают внутренние кавычки, так как параметр передается отдельно от текста самой SQL-команды. Это исключает любые синтаксические ошибки компиляции запроса.
Посмотрим на пример безопасного поиска элемента номенклатуры:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ
| Номенклатура.Ссылка КАК Ссылка
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Артикул = &Артикул";
// Даже если в Артикуле содержатся кавычки, запрос отработает корректно
Запрос.УстановитьПараметр("Артикул", СтрТч["НоменклатураАртикул"]);
РезультатЗапроса = Запрос.Выполнить();
Если Не РезультатЗапроса.Пустой() Тогда
Выборка = РезультатЗапроса.Выбрать();
Выборка.Следующий();
НайденнаяНоменклатура = Выборка.Ссылка;
Иначе
НайденнаяНоменклатура = Справочники.Номенклатура.ПустаяСсылка();
КонецЕсли;
Использование запросов для поиска данных по ключевым реквизитам — это стандарт разработки «1С:Совместимо». Данный метод не только решает проблему с поиском строк, содержащих кавычки, но и работает значительно быстрее стандартного метода НайтиПоРеквизиту при работе в клиент-серверном режиме базы данных.