В процессе работы с конфигурацией 1С:Управление производственным предприятием 1.3 (УПП) часто возникает задача автоматизации рутинных процессов. Одной из таких задач является автоматическое заполнение поля Артикул при создании новой позиции в справочнике Номенклатура. Это позволяет избежать дублирования номеров и придерживаться единого стандарта кодирования товаров в организации.
Рассмотрим ситуацию, когда необходимо формировать артикул по определенной маске, например, с префиксом "МК" и порядковым номером. Разберем типичные ошибки начинающих разработчиков и напишем корректный код для решения этой задачи.
Проанализируем фрагмент кода, который часто вызывает затруднения у программистов при попытке реализовать генерацию номера через запрос. Основная ошибка заключается в неправильном синтаксисе текста запроса и путанице между объектом Запрос и результатом его выполнения.
Посмотрим на типичную ошибку в операторе ПОДОБНО. В 1С этот оператор используется для поиска по строковой маске. Ошибка заключается в попытке вставить строковую переменную или регулярное выражение прямо в текст запроса без использования параметров или правильной конкатенации.
Вторая критическая ошибка — это обращение к методу Следующий() непосредственно у объекта Запрос. Важно помнить, что метод Следующий() принадлежит объекту ВыборкаИзРезультатаЗапроса, а не самому запросу.
Выясним причину, по которой конфигуратор выдает ошибку "Неопознанный оператор". При написании запроса внутри модуля объекта 1С, текст запроса — это обычная строка. Если мы хотим использовать маску поиска, нам нужно либо передать ее через параметр, либо правильно оформить внутри кавычек.
Рассмотрим правильный способ передачи префикса. Рекомендуется использовать параметры запроса, так как это делает код более читаемым и защищенным от ошибок:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| Номенклатура.Артикул КАК Артикул
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Артикул ПОДОБНО &МаскаПоиска
|УПОРЯДОЧИТЬ ПО
| Артикул УБЫВ";
Запрос.УстановитьПараметр("МаскаПоиска", "МК%");
В данном примере символ % означает любое количество произвольных символов. Если нам нужно найти только те артикулы, где после "МК" идут только цифры, мы можем уточнить маску, используя символ подчеркивания _ (один любой символ) или просто полагаться на сортировку по убыванию, чтобы получить последний созданный номер.
Теперь разберем, как правильно получить данные из базы. После того как Запрос.Выполнить() возвращает результат, нам необходимо создать выборку. Проанализируем правильную последовательность действий:
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Если Выборка.Следующий() Тогда
// Обработка найденного максимального артикула
ПоследнийАртикул = Выборка.Артикул;
Иначе
// Если справочник пуст или артикулов с таким префиксом нет
ПоследнийАртикул = "МК000000";
КонецЕсли;
Обратите внимание, что мы используем ВЫБРАТЬ ПЕРВЫЕ 1 и УПОРЯДОЧИТЬ ПО Артикул УБЫВ. Это позволяет нам не перебирать все записи справочника, а сразу получить "самый большой" существующий артикул.
После того как мы получили строку последнего артикула (например, "МК000125"), нам нужно выделить числовую часть, увеличить ее на единицу и собрать строку обратно с сохранением длины. Для этого воспользуемся функциями Прав(), Число() и Формат().
Рассмотрим алгоритм внутри процедуры ПередЗаписью. Важно добавить проверку ЭтоНовый(), чтобы артикул не перезаписывался каждый раз при редактировании уже существующего товара.
Процедура ПередЗаписью(Отказ)
// Артикул заполняем только для новых объектов или если он пустой
Если НЕ ЭтоНовый() И ЗначениеЗаполнено(Артикул) Тогда
Возврат;
КонецЕсли;
// Если артикул уже заполнен вручную, не трогаем его
Если ЗначениеЗаполнено(Артикул) Тогда
Возврат;
КонецЕсли;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| Номенклатура.Артикул КАК Артикул
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Артикул ПОДОБНО &Префикс
|УПОРЯДОЧИТЬ ПО
| Артикул УБЫВ";
Запрос.УстановитьПараметр("Префикс", "МК" + "%");
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
// Извлекаем цифры. Предположим, длина цифровой части 8 символов
СтрокаЦифр = Прав(Выборка.Артикул, СтрДлина(Выборка.Артикул) - 2);
Попытка
НомерЧислом = Число(СтрокаЦифр) + 1;
Исключение
НомерЧислом = 1;
КонецПопытки;
Иначе
НомерЧислом = 1;
КонецЕсли;
// Формируем новый артикул с ведущими нулями
// ЧЦ=8 - общее количество цифр, ЧВН= - выводить ведущие нули, ЧГ= - убрать группировку разрядов
Артикул = "МК" + Формат(НомерЧислом, "ЧЦ=8; ЧВН=; ЧГ=");
КонецПроцедуры
При реализации автоматической нумерации важно учитывать несколько технических нюансов, которые могут повлиять на стабильность работы системы 1С:Предприятие:
Артикул должно иметь свойство "Индексировать" в метаданных справочника. Если индекс отсутствует, запрос ПОДОБНО будет выполнять полное сканирование таблицы, что значительно замедлит запись новой номенклатуры при большом объеме данных (десятки и сотни тысяч позиций).ПередЗаписью не гарантирует уникальность в многопользовательской среде. Если два пользователя одновременно создают карточку, они могут получить один и тот же "максимальный" номер. Для решения этой проблемы в высоконагруженных системах рекомендуется использовать механизмы БлокировкаДанных или специальные регистры сведений для хранения счетчиков.Попытка ... Исключение при преобразовании строки в число. В справочнике могут оказаться артикулы, введенные вручную в произвольном формате, что приведет к фатальной ошибке при попытке выполнения Число().Проанализируем еще один способ. В платформе 1С уже встроен мощный механизм автонумерации для поля Код. Если вам не принципиально использование именно поля Артикул, лучше настроить маску и длину кода в свойствах справочника Номенклатура. Платформа сама будет генерировать номера вида "МК00000001" и гарантировать их уникальность без написания лишнего кода.
Если же бизнес-процесс требует именно заполнения поля Артикул, вы можете в событии ПриУстановкеНовогоКода или ПередЗаписью просто копировать значение кода в артикул:
Процедура ПередЗаписью(Отказ)
Если ЭтоНовый() Тогда
// Артикул будет равен коду, который сгенерирует платформа
Артикул = Код;
КонецЕсли;
КонецПроцедуры
Подводя итог, мы рассмотрели, как исправить синтаксические ошибки в запросах 1С, как правильно работать с выборкой данных и как реализовать надежный алгоритм инкремента строкового номера. Используйте предложенные примеры кода для настройки вашей конфигурации УПП 1.3.