При работе с базами данных 1С часто возникает необходимость в массовой корректировке данных. Одной из таких задач может быть перенос части информации из одного реквизита объекта в другой, а затем удаление этой части из исходного реквизита. Рассмотрим подробнее ситуацию, когда нам требуется выделить первые десять цифр из наименования контрагента, переместить их в поле «Комментарий» и после этого убрать из самого наименования. Эта операция особенно актуальна, если в наименование контрагента изначально вносился номер лицевого счета или иной цифровой идентификатор, который должен храниться отдельно.
Мы разберем комплексное решение этой задачи, которое включает использование стандартных механизмов платформы 1С:Предприятие 8.3, а также покажем различные подходы к программной реализации логики проверки и преобразования строк.
Для массового изменения данных в 1С 8.3 наиболее эффективным и безопасным способом является использование стандартной обработки "Групповое изменение реквизитов". Эта обработка позволяет нам выполнить произвольный алгоритм для выбранных элементов справочника или документа, что значительно упрощает процесс и минимизирует риски ошибок по сравнению с ручной корректировкой или прямыми изменениями в конфигураторе. Давайте посмотрим, как настроить эту обработку для нашей задачи.
Администрирование, затем Обслуживание и выберем пункт Корректировка данных. Здесь мы найдем ссылку на "Групповое изменение реквизитов".Этот подход гарантирует, что все изменения будут внесены корректно, с соблюдением всех правил работы с объектами 1С (запись, проведение и т.д.), что существенно снижает риск повреждения данных.
Теперь давайте сосредоточимся на программном коде, который мы вставим в поле "Выполнить произвольный алгоритм" обработки "Групповое изменение реквизитов". Этот код будет выполняться для каждого объекта Объект (в нашем случае, для каждого контрагента), выбранного в обработке.
ПервыеДесятьСимволовНаименования = Лев(Объект.Наименование, 10);
Если СтрДлина(ПервыеДесятьСимволовНаименования) = 10 И СтрРазделить(ПервыеДесятьСимволовНаименования,"0123456789",Ложь).Количество = 0 Тогда
Объект.Комментарий = ПервыеДесятьСимволовНаименования;
Объект.Наименование = СокрЛ(Сред(Объект.Наименование, 11));
Объект.НаименованиеПолное = СокрЛ(Сред(Объект.НаименованиеПолное, 11));
КонецЕсли;
Разберем каждую строку этого алгоритма, чтобы полностью понять его логику и функциональность.
ПервыеДесятьСимволовНаименования = Лев(Объект.Наименование, 10);
Здесь мы используем функцию Лев(), которая возвращает подстроку заданной длины с начала строки. Мы извлекаем первые 10 символов из поля Наименование текущего объекта контрагента и сохраняем их в переменную ПервыеДесятьСимволовНаименования. Это предположение о том, что лицевой счет всегда находится в начале наименования и имеет длину в 10 символов.
Если СтрДлина(ПервыеДесятьСимволовНаименования) = 10 И СтрРазделить(ПервыеДесятьСимволовНаименования,"0123456789",Ложь).Количество = 0 Тогда
Это ключевой момент алгоритма, обеспечивающий надежность операции. Мы используем два условия:
СтрДлина(ПервыеДесятьСимволовНаименования) = 10: Первое условие проверяет, что извлеченная подстрока действительно имеет длину 10 символов. Это важно, если наименование может быть короче 10 символов, и мы хотим избежать ошибок.СтрРазделить(ПервыеДесятьСимволовНаименования,"0123456789",Ложь).Количество = 0: Второе условие является наиболее надежным способом проверки того, что строка состоит исключительно из цифр.
СтрРазделить() разбивает исходную строку (ПервыеДесятьСимволовНаименования) на части по символам-разделителям."0123456789", которая содержит все возможные цифры.Ложь указывает, что пустые части не должны игнорироваться.ПервыеДесятьСимволовНаименования содержит только цифры, то функция СтрРазделить() не сможет найти ни одного символа, который *не* является разделителем (т.е. не является цифрой). В этом случае она вернет массив, содержащий только одну пустую строку (если исходная строка не пустая) или будет вести себя специфически. Более надежная интерпретация в данном контексте: если *все* символы являются разделителями, то "неразделимые" части отсутствуют, и количество элементов в результирующем массиве будет равно 0, что говорит нам о том, что строка состоит только из символов, переданных в качестве разделителей. На практике, этот подход очень хорошо работает для проверки на "только цифры". Если бы строка содержала хотя бы один нецифровой символ (например, "123456789А"), то СтрРазделить() создала бы как минимум одну часть, содержащую этот нецифровой символ, и .Количество было бы больше нуля.
Объект.Комментарий = ПервыеДесятьСимволовНаименования;
Если оба условия выполняются, то есть первые десять символов присутствуют и являются только цифрами, мы присваиваем это значение полю Комментарий текущего контрагента.
Объект.Наименование = СокрЛ(Сред(Объект.Наименование, 11));
Здесь мы изменяем исходное поле Наименование.
Сред(Объект.Наименование, 11): Функция Сред() возвращает подстроку, начиная с указанной позиции и до конца строки. В данном случае мы берем все символы, начиная с 11-й позиции (то есть пропускаем первые 10 символов - наш лицевой счет).СокрЛ(...): Функция СокрЛ() удаляет пробелы в начале и конце строки. Это важно, чтобы после удаления лицевого счета не осталось лишних начальных пробелов в наименовании.
Объект.НаименованиеПолное = СокрЛ(Сред(Объект.НаименованиеПолное, 11));
Аналогично, мы выполняем те же действия для поля НаименованиеПолное, если оно также содержит лицевой счет и требует корректировки. Это обеспечивает консистентность данных.
После выполнения этого алгоритма для каждого отобранного контрагента, лицевые счета будут перенесены в комментарии, а наименования будут очищены от этих цифровых префиксов.
Хотя метод с СтрРазделить() является очень надежным для проверки на "только цифры", существуют и другие подходы, которые могут быть рассмотрены или использованы в других контекстах. Мы рассмотрим несколько из них.
Число()Один из очевидных способов проверить, является ли строка числом, это попытаться преобразовать её в число с помощью функции Число(). Если преобразование успешно, то строка содержит число. Однако, этот метод имеет свои нюансы, если нам нужно убедиться, что строка состоит исключительно из цифр без других символов (например, пробелов или знаков).
ПервыеДесятьСимволовНаименования = Лев(Объект.Наименование, 10);
ПервыеДесятьСимволовНаименованияЯвляютсяЧислом = Ложь;
Попытка
// Пытаемся преобразовать строку в число
а = Число(ПервыеДесятьСимволовНаименования);
ПервыеДесятьСимволовНаименованияЯвляютсяЧислом = Истина;
Исключение
// Если преобразование не удалось, значит строка не является числом
// (или содержит нечисловые символы, которые Число() не может обработать)
КонецПопытки;
Если ПервыеДесятьСимволовНаименованияЯвляютсяЧислом Тогда
// Здесь можем выполнить перенос и удаление
Объект.Комментарий = ПервыеДесятьСимволовНаименования;
Объект.Наименование = СокрЛ(Сред(Объект.Наименование, 11));
Объект.НаименованиеПолное = СокрЛ(Сред(Объект.НаименованиеПолное, 11));
КонецЕсли;
Недостатки этого метода: Функция Число() может успешно преобразовать строки, которые содержат только цифры, но также она может обрабатывать строки с пробелами (например, " 123 ") или знаками пунктуации, которые она умеет игнорировать или интерпретировать (например, "123.45"). Если нам критически важно, чтобы строка состояла строго из цифр и ничего более, метод с СтрРазделить() будет более точным.
Начиная с версии платформы 1С:Предприятие 8.3.23, появилась встроенная поддержка регулярных выражений. Это мощный инструмент для работы со строками, позволяющий проверять их на соответствие сложным шаблонам. Если ваша платформа поддерживает эту версию или выше, вы можете использовать регулярные выражения для более элегантной и гибкой проверки.
ПервыеДесятьСимволовНаименования = Лев(Объект.Наименование, 10);
// Проверяем, состоит ли строка из 10 цифр
Если СтрНайтиПоРегулярномуВыражению(ПервыеДесятьСимволовНаименования, "^[0-9]{10}$") > 0 Тогда
// Алгоритм переноса
Объект.Комментарий = ПервыеДесятьСимволовНаименования;
Объект.Наименование = СокрЛ(Сред(Объект.Наименование, 11));
Объект.НаименованиеПолное = СокрЛ(Сред(Объект.НаименованиеПолное, 11));
КонецЕсли;
Объяснение регулярного выражения "^[0-9]{10}$":
^: Обозначает начало строки.[0-9]: Соответствует любой цифре от 0 до 9.{10}: Указывает, что предыдущий символ (или группа) должен повторяться ровно 10 раз.$: Обозначает конец строки.Таким образом, всё выражение "^[0-9]{10}$" означает "строка должна начинаться с 10 цифр и заканчиваться этими 10 цифрами, не содержа других символов". Это делает проверку очень точной. Если лицевой счет находится в начале наименования, а за ним может следовать что угодно, можно использовать "^[0-9]{10}.*", где .* означает "любое количество любых символов после 10 цифр".
В некоторых случаях, если нам нужно выполнить сложный отбор контрагентов на основе шаблона в наименовании, мы можем использовать запросы. Запросы 1С обладают мощными возможностями для выборки данных и могут включать строковые функции и оператор ПОДОБНО для поиска по шаблону. Однако, важно помнить, что запрос сам по себе лишь *выбирает* данные, а для их *изменения* всё равно потребуется программный код, который будет выполняться для каждого выбранного элемента.
Приведем пример запроса, который может выбрать контрагентов, у которых наименование начинается с 10 цифр и при этом поле "Комментарий" пустое:
ВЫБРАТЬ
Контрагенты.Ссылка КАК Ссылка,
СОКРЛП(ПОДСТРОКА(Контрагенты.Наименование, 11, 10000)) КАК НовоеНаименование,
ПОДСТРОКА(Контрагенты.Наименование, 1, 10) КАК НовыйКомментарий
ИЗ
Справочник.Контрагенты КАК Контрагенты
ГДЕ
Контрагенты.Наименование ПОДОБНО "[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]%"
И Выразить(Контрагенты.Комментарий КАК Строка(1)) = ""
Объяснение запроса:
ВЫБРАТЬ ...: Мы выбираем ссылку на контрагента, а также формируем новые значения для наименования и комментария, чтобы видеть, какими они будут после преобразования.
СОКРЛП(ПОДСТРОКА(Контрагенты.Наименование, 11, 10000)) КАК НовоеНаименование: Извлекаем подстроку из наименования, начиная с 11-го символа, и убираем пробелы с обеих сторон. Максимальная длина 10000 символов - это страховка, чтобы захватить всю оставшуюся часть наименования, хотя обычно фактическая длина наименования намного меньше.ПОДСТРОКА(Контрагенты.Наименование, 1, 10) КАК НовыйКомментарий: Извлекаем первые 10 символов для будущего комментария.ИЗ Справочник.Контрагенты КАК Контрагенты: Указываем источник данных - справочник "Контрагенты".ГДЕ Контрагенты.Наименование ПОДОБНО "[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]%": Это условие использует оператор ПОДОБНО для поиска строк, которые начинаются ровно с 10 цифр.
[0-9]: В контексте оператора ПОДОБНО это соответствует любой цифре. Повторив его 10 раз, мы требуем ровно 10 цифр в начале.%: Соответствует любой последовательности символов (или отсутствию символов) после 10 цифр.И Выразить(Контрагенты.Комментарий КАК Строка(1)) = "": Это условие проверяет, что поле "Комментарий" пустое. Критически важно: поле Комментарий часто имеет тип "Строка неограниченной длины". Сравнение его напрямую с пустой строкой (Контрагенты.Комментарий = "") в запросе может привести к ошибке из-за несовместимости типов или особенностей работы с длинными строками в СУБД. Поэтому мы используем функцию Выразить(... КАК Строка(1)), которая явно приводит поле "Комментарий" к строке ограниченной длины (в данном случае, 1 символ), что позволяет корректно сравнить его с пустой строкой. Если поле пустое, то при приведении к Строка(1) оно останется пустой строкой.Использование такого запроса в сочетании с обработкой "Групповое изменение реквизитов" (где запрос может быть использован для формирования списка изменяемых объектов) позволяет очень точно отобрать необходимые элементы для последующей программной обработки.
При выполнении массовых операций с данными всегда важно соблюдать осторожность и учитывать потенциальное влияние на производительность системы.
Наименование, Юридическое/физическое лицо), проиндексированы в базе данных. Это существенно ускоряет выборку данных.Внимательное следование этим рекомендациям поможет вам выполнить задачу переноса данных безопасно и эффективно, сохраняя целостность и производительность вашей информационной системы 1С.