В процессе сопровождения баз данных 1С часто возникают задачи по массовому изменению реквизитов. Одной из типичных ситуаций является необходимость привести номера подчиненных документов (например, СчетФактураВыданный) в соответствие с номерами документов-оснований (например, РеализацияТоваровУслуг). Рассмотрим, какими способами можно решить эту задачу, разберем типичные ошибки программирования и выясним, как правильно работать с объектами метаданных для записи изменений.
Стандартная типовая обработка «Групповое изменение реквизитов» (входящая в состав БСП) — это мощный инструмент, но он имеет свои пределы. Зачастую в ней невозможно напрямую прописать обращение через точку к реквизитам другого документа, например: Объект.ДокументОснование.Номер. Это происходит потому, что обработка ориентирована на прямую замену значений простыми типами или ссылками.
Для решения сложных задач, требующих вычислений или обращения к связанным данным, мы можем использовать один из двух подходов:
Рассмотрим по шагам процесс создания алгоритма для изменения номеров документов. Проанализируем ситуацию, когда нам нужно найти все проведенные счета-фактуры за определенный период и заменить их номера номерами оснований.
Шаг 1. Формирование запроса. Сначала нам нужно получить данные. Использование запроса — самый эффективный способ, так как он минимизирует нагрузку на сервер. Нам необходима ссылка на документ и номер его основания.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| СчетФактураВыданный.Ссылка КАК Ссылка,
| СчетФактураВыданный.ДокументОснование.Номер КАК ДокументОснованиеНомер
|ИЗ
| Документ.СчетФактураВыданный КАК СчетФактураВыданный
|ГДЕ
| СчетФактураВыданный.Дата МЕЖДУ &ДатаНачала И &ДатаОкончания
| И СчетФактураВыданный.Проведен = ИСТИНА
| И СчетФактураВыданный.ПометкаУдаления = ЛОЖЬ";
Запрос.УстановитьПараметр("ДатаНачала", '20230101');
Запрос.УстановитьПараметр("ДатаОкончания", '20231231');
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Шаг 2. Обход результатов и изменение данных. Здесь важно помнить о ключевом отличии Ссылки от Объекта. Попытка изменить реквизит непосредственно у переменной, полученной из запроса (ссылки), приведет к ошибке «Метод объекта не обнаружен (Записать)». Ссылка предназначена только для чтения. Для изменения данных необходимо получить объект документа.
Проанализируем правильный цикл обработки:
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
// Получаем объект из ссылки для возможности редактирования
ДокументОбъект = ВыборкаДетальныеЗаписи.Ссылка.ПолучитьОбъект();
// Присваиваем новый номер
ДокументОбъект.Номер = ВыборкаДетальныеЗаписи.ДокументОснованиеНомер;
// Пытаемся записать изменения
Попытка
ДокументОбъект.Записать(РежимЗаписиДокумента.Запись);
Исключение
Сообщить("Не удалось записать документ: " + ДокументОбъект.Ссылка + " Ошибка: " + ОписаниеОшибки());
КонецПопытки;
КонецЦикла;
При массовом изменении документов мы часто сталкиваемся с тем, что стандартные проверки в модуле объекта (например, проверка заполнения обязательных полей, которые были добавлены в конфигурацию позже создания документа) мешают записи. Чтобы обойти это и изменить только нужный нам реквизит «малой кровью», рекомендуется использовать свойство ОбменДанными.Загрузка.
Разберем, как это работает: установка флага ОбменДанными.Загрузка = Истина сообщает системе, что объект записывается в режиме загрузки данных, и большинство подписок на события и встроенных проверок будет пропущено. Это значительно ускоряет процесс и позволяет избежать блокирующих ошибок.
ДокументОбъект = Ссылка.ПолучитьОбъект();
ДокументОбъект.Номер = НовыйНомер;
ДокументОбъект.ОбменДанными.Загрузка = Истина; // Отключаем проверки
ДокументОбъект.Записать();
Если задача разовая и писать код в конфигураторе долго, профессионалы часто используют сторонние консоли кода и инструменты, такие как Инструменты разработчика (автор ТормозИТ). Это универсальный набор обработок, который позволяет:
Это значительно экономит время при поиске и исправлении ошибок в данных.
Часто программисты сталкиваются с тем, что при запуске обработки код выполняется, но точки останова внутри процедур &НаСервере или &НаСервереБезКонтекста не срабатывают. Это означает, что на сервере 1С не включен режим отладки.
Выясним, как это исправить. Для включения отладки в клиент-серверном варианте необходимо:
1C:Enterprise 8.3 Server Agent.ImagePath добавить ключ -debug.Только после этих действий конфигуратор сможет «подцепиться» к серверному процессу и позволить вам проанализировать значения переменных в момент выполнения кода.
Любое групповое изменение — это риск. Прежде чем запускать выполнение кода на всей базе, проанализируем следующие правила: Во-первых, всегда делайте резервную копию базы данных. Во-вторых, сначала протестируйте алгоритм на одном конкретном документе, жестко ограничив запрос по ссылке. В-третьих, учитывайте уникальность номеров. Если вы присваиваете номера вручную, убедитесь, что они не дублируются, иначе система может выдать ошибку при записи или нарушить логику автонумерации в будущем.
Рассмотрим пример ограничения запроса для теста:
// Добавьте это условие в запрос для проверки на одном документе
// | ГДЕ СчетФактураВыданный.Ссылка = &ТестоваяСсылка
Таким образом, комбинируя знания о работе с объектами, использование режима загрузки данных и инструменты отладки, мы можем эффективно решать задачи любой сложности по трансформации данных в 1С.