В процессе работы в программе 1С:Предприятие (особенно в конфигурациях уровня «Управление торговлей 11») пользователи часто сталкиваются с ситуацией, когда из-за некорректных действий сотрудников или ошибок импорта сбиваются важные реквизиты номенклатуры, такие как артикулы. Например, всем позициям присваивается единое значение, или они полностью очищаются. Когда позиций в базе данных тысячи, ручное исправление становится невозможным.
В этой статье мы подробно разберем, как написать внешнюю обработку для автоматического присвоения уникальных артикулов номенклатуре (например, от "000001" до "014000"). Мы также проанализируем, почему стандартные методы преобразования чисел в 1С могут приводить к появлению нежелательных символов (запятых или пробелов), и как правильно оптимизировать этот процесс для базы данных с десятками тысяч товаров.
Давайте разберем типичную ошибку, с которой сталкиваются начинающие разработчики при написании обработок перенумерации. На форумах часто предлагают использовать конструкцию вида Строка(Счетчик) внутри цикла с последующим ручным добавлением лидирующих нулей.
Однако при достижении счетчиком значения 1000 система внезапно начинает записывать артикулы в некорректном формате — например, "001,000" или "001 000". Выясним, почему это происходит.
Дело в том, что стандартная функция 1С Строка() преобразует число в текстовый формат с учетом региональных настроек (локализации) операционной системы или сервера 1С:Предприятия. По умолчанию для русской и многих других локалей применяется правило группировки триад. Это означает, что каждые три знака в числе визуально отделяются друг от друга разделителем групп (неразрывным пробелом или запятой в зависимости от настроек СУБД и ОС).
Когда счетчик равен 999, функция Строка(999) возвращает обычные три символа "999". Но как только значение становится равным 1000, функция преобразует его в "1 000" или "1,000". Ручные проверки длины строки типа СтрДлина(Объект.Артикул) начинают работать неверно, а лишние нецифровые символы попадают прямо в карточку номенклатуры.
Участники обсуждения на форумах часто пытаются исправить эту проблему «в лоб» — с помощью функции СтрЗаменить(), пытаясь удалить запятые или пробелы постфактум. Посмотрим на этот пример кода:
Если Найти(Объект.Артикул, ",") > 0 Тогда
Объект.Артикул = СтрЗаменить(Объект.Артикул, ",", "");
КонецЕсли;
Почему это плохое решение?
Пока СтрДлина(Артикул) < 6 работает медленно и перегружает процессор ненужными итерациями.Для гарантированного получения строки нужной длины с лидирующими нулями и без каких-либо разделителей групп в 1С существует стандартная, быстрая и надежная функция Формат(). Рассмотрим ее параметры подробнее.
Для нашей задачи идеально подходит форматная строка: "ЧЦ=6; ЧВН=; ЧГ=0". Разберем значение каждого параметра:
Пример использования функции:
НовыйАртикул = Формат(1000, "ЧЦ=6; ЧВН=; ЧГ=0"); // Результат: "001000"
Этот способ работает мгновенно, не требует циклов Пока и последующих замен символов.
В конфигурациях «Управление торговлей 11», «ERP» или «Комплексная автоматизация» справочник «Номенклатура» является ключевым и очень тяжелым объектом. При обычной программной записи элемента система выполняет множество фоновых проверок: контролирует уникальность штрихкодов, проверяет заполнение обязательных реквизитов, записывает данные в регистры сведений и запускает подписки на события «ПриЗаписи».
Если выполнять обычную запись 14 000 товаров, этот процесс на рабочем сервере может занять от 30 минут до нескольких часов, параллельно заблокировав работу остальных пользователей базы данных.
Чтобы ускорить выполнение обработки в десятки раз, применим профессиональные методы оптимизации:
ОбменДанными.Загрузка = Истина сообщает системе, что запись производится в режиме загрузки данных. Это отключает большинство тяжелых проверок конфигурации, позволяя записать артикул практически напрямую в СУБД.НачатьТранзакцию() и ЗафиксироватьТранзакцию()), мы заставим СУБД записать все изменения единым блоком данных, что колоссально снизит дисковую нагрузку.ГДЕ НЕ Номенклатура.ЭтоГруппа.Ниже представлен готовый листинг кода, который необходимо разместить в модуле внешней обработки (например, по нажатию на кнопку формы). Этот код безопасно, быстро и правильно перенумерует всю вашу номенклатуру:
&НаСервере
Процедура ПеренумероватьАртикулыНаСервере()
// Шаг 1. Формируем запрос для выборки всех элементов номенклатуры, исключая папки
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| НЕ Номенклатура.ЭтоГруппа";
РезультатЗапроса = Запрос.Выполнить();
Если РезультатЗапроса.Пустой() Тогда
Сообщить("Номенклатура для изменения не найдена!");
Возврат;
КонецЕсли;
Выборка = РезультатЗапроса.Выбрать();
Счетчик = 1;
// Шаг 2. Открываем транзакцию для максимального ускорения записи
НачатьТранзакцию();
Попытка
Пока Выборка.Следующий() Цикл
// Получаем объект для редактирования
НоменклатураОбъект = Выборка.Ссылка.ПолучитьОбъект();
// Применяем правильное форматирование без запятых и пробелов
НоменклатураОбъект.Артикул = Формат(Счетчик, "ЧЦ=6; ЧВН=; ЧГ=0");
// Отключаем лишние проверки при записи в УТ 11
НоменклатураОбъект.ОбменДанными.Загрузка = Истина;
// Записываем измененный объект в базу данных
НоменклатураОбъект.Записать();
Счетчик = Счетчик + 1;
КонецЦикла;
// Шаг 3. Фиксируем изменения в базе данных
ЗафиксироватьТранзакцию();
Сообщить("Перенумерация успешно завершена! Обработано элементов: " + (Счетчик - 1));
Исключение
// Если произошла любая непредвиденная ошибка, отменяем все изменения
ОтменитьТранзакцию();
Сообщить("Произошла ошибка при выполнении операции! Изменения отменены.", СтатусСообщения.Важное);
Сообщить(ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
Прежде чем запускать групповую обработку изменения артикулов в рабочей базе компании, обязательно проанализируйте возможные последствия для бизнес-процессов:
Рекомендация: Всегда создавайте резервную копию базы данных (резервный архив .dt) перед выполнением любых обработок группового изменения реквизитов! Тестируйте работу кода сначала на копии базы данных.