Тестирование проводилось на:
Платформа: 1С:Предприятие 8.3 (8.3.18.1334)
Конфигурация: 1С:ERP Управление предприятием 2 (2.5.6.144)
Старт работы:
- Выбрать набор свойств, табличная часть с доп. реквизитам заполниться сама, если таковые существуют
- Задать настройки выполнения
- В табличной части задать наименование основного реквизита (как в конфигураторе) если необходим перенос и флаг "Очистить" если необходимо очистить значения. Перенос будут выполнен ДО очистки.
У всех настроек есть подсказки. Полный список:
- Кнопка "Проверить". Проверит ТЧ на корректность заполнения. Если не назначено действий или основной реквизит написан неправильно - строка подсветится красным, при начале обработки такие строки будут удалены.
- Поле "Обработать". Указывает количество элементов справочника, которые нужно обработать. Элементы сортируются по наименованию. Если указано 0, будут обработаны все элементы.
- Флаг "Проверять основной реквизит". Проверяет основной реквизит после переноса. Если основной реквизит пустой, элемент не запишется и будет сгенерирована ошибка.
- Флаг "Останавливать при ошибке". При первой же ошибке записи данных обработка будет остановлена. В ином случае обработка продолжит обрабатывать другие элементы. Все ошибки будут сохранены в журнале регистрации.
Код:
&НаКлиенте
Процедура НаборСвойствПриИзменении(Элемент)
ЗаполнитьИмяСправочника();
Если ЗначениеЗаполнено(НаборСвойств) Тогда
ЗаполнитьТаблицуДополнительныеРеквизиты();
КонецЕсли;
КонецПроцедуры
&НаСервере
Процедура ЗаполнитьИмяСправочника()
ИмяСправочника = ?(ЗначениеЗаполнено(НаборСвойств.ИмяПредопределенныхДанных), НаборСвойств.ИмяПредопределенныхДанных, НаборСвойств.ИмяПредопределенногоНабора);
ИмяСправочника = Прав(ИмяСправочника, СтрДлина(ИмяСправочника)-СтрНайти(ИмяСправочника, "_"));
НайтиВторойЗнак = СтрНайти(ИмяСправочника, "_");
Если НайтиВторойЗнак <> 0 Тогда
ИмяСправочника = Лев(ИмяСправочника, НайтиВторойЗнак - 1);
КонецЕсли;
КонецПроцедуры
&НаСервере
Процедура ЗаполнитьТаблицуДополнительныеРеквизиты()
ДополнительныеРеквизиты.Очистить();
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ДополнительныеРеквизитыИСведения.Ссылка КАК ДополнительныйРеквизит
|ИЗ
| ПланВидовХарактеристик.ДополнительныеРеквизитыИСведения КАК ДополнительныеРеквизитыИСведения
|ГДЕ
| НЕ ДополнительныеРеквизитыИСведения.ЭтоДополнительноеСведение
| И ДополнительныеРеквизитыИСведения.НаборСвойств = &НаборСвойств
|
|УПОРЯДОЧИТЬ ПО
| ДополнительныеРеквизитыИСведения.Имя";
Запрос.УстановитьПараметр("НаборСвойств", НаборСвойств);
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
СтрокаТЗ = ДополнительныеРеквизиты.Добавить();
ЗаполнитьЗначенияСвойств(СтрокаТЗ, ВыборкаДетальныеЗаписи);
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Процедура ВыполнитьКод(Команда)
Продолжаем = ПроверитьДанные();
Если Не Продолжаем Тогда Возврат КонецЕсли;
ВыполнитьОбрабатываниеДанных();
КонецПроцедуры
&НаКлиенте
Процедура Проверить(Команда)
ПроверитьДанные(Ложь);
КонецПроцедуры
&НаСервере
Функция ПроверитьДанные(УдалятьСтроки = Истина)
Попытка
ЭлементСправочника = Справочники[ИмяСправочника].СоздатьЭлемент();
Исключение
Сообщить("Справочник " + ИмяСправочника + " не поддерживается обработкой");
Возврат Ложь;
КонецПопытки;
Для каждого СтрокаТЗ Из ДополнительныеРеквизиты Цикл
Если СтрокаТЗ.ДополнительныйРеквизит.НаборСвойств <> НаборСвойств Тогда
СтрокаТЗ.УдалитьСтроку = Истина;
ИначеЕсли Не ЗначениеЗаполнено(СтрокаТЗ.ОсновнойРеквизит) И СтрокаТЗ.Очистить = Ложь Тогда
СтрокаТЗ.УдалитьСтроку = Истина;
ИначеЕсли ЗначениеЗаполнено(СтрокаТЗ.ОсновнойРеквизит) Тогда
Попытка
РеквизитСправочника = ЭлементСправочника[СтрокаТЗ.ОсновнойРеквизит];
СтрокаТЗ.УдалитьСтроку = Ложь;
Исключение
Сообщить("Реквизит " + СтрокаТЗ.ОсновнойРеквизит + " не найден!");
СтрокаТЗ.УдалитьСтроку = Истина;
КонецПопытки;
Иначе
СтрокаТЗ.УдалитьСтроку = Ложь;
КонецЕсли;
КонецЦикла;
Если УдалятьСтроки Тогда
ТЗКопия = Новый ТаблицаЗначений;
ТЗКопия = ДополнительныеРеквизиты.Выгрузить(Новый Структура("УдалитьСтроку", Ложь));
ДополнительныеРеквизиты.Очистить();
ДополнительныеРеквизиты.Загрузить(ТЗКопия);
КонецЕсли;
Если ДополнительныеРеквизиты.Количество() = 0 Тогда
Сообщить("Не назначенны действия для обработки данных");
Возврат Ложь;
Иначе
Возврат Истина;
КонецЕсли;
КонецФункции
&НаСервере
Процедура ВыполнитьОбрабатываниеДанных()
Запрос = Новый Запрос;
Запрос.Текст = СтрШаблон(
"ВЫБРАТЬ %1
| ДополнительныеРеквизиты.Ссылка КАК Ссылка,
| ДополнительныеРеквизиты.Свойство КАК Свойство,
| ДополнительныеРеквизиты.Значение КАК Значение
|ИЗ
| Справочник.%2.ДополнительныеРеквизиты КАК ДополнительныеРеквизиты
|ГДЕ
| ДополнительныеРеквизиты.Свойство В(&Свойство)
|
|УПОРЯДОЧИТЬ ПО
| ДополнительныеРеквизиты.Ссылка.Наименование
|ИТОГИ ПО
| Ссылка"
,?(ЗначениеЗаполнено(КвоОбработать), "ПЕРВЫЕ " + Формат(КвоОбработать, "ЧГ=0"), ""), ИмяСправочника);
Запрос.УстановитьПараметр("Свойство", ДополнительныеРеквизиты.Выгрузить(,"ДополнительныйРеквизит"));
РезультатЗапроса = Запрос.Выполнить();
ВыборкаСсылка = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
Пока ВыборкаСсылка.Следующий() Цикл
ОбъектРаботы = ВыборкаСсылка.Ссылка.ПолучитьОбъект();
ОбъектМодифицирован = Ложь;
ВыборкаДетальныеЗаписи = ВыборкаСсылка.Выбрать();
Попытка
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
ПараметрОтбора = Новый Структура;
ПараметрОтбора.Вставить("ДополнительныйРеквизит", ВыборкаДетальныеЗаписи.Свойство);
СтрокаТЗ = ДополнительныеРеквизиты.НайтиСтроки(ПараметрОтбора);
ИмяРеквизита = СтрокаТЗ[0].ОсновнойРеквизит;
Если ЗначениеЗаполнено(ИмяРеквизита) Тогда
ЗначениеОсновногоРеквизита = ОбъектРаботы[ИмяРеквизита];
//Здесь можно обработать значение дополнительного реквизита (ВыборкаДетальныеЗаписи.Значение), перед помещением в основной
ОбъектРаботы[ИмяРеквизита] = ВыборкаДетальныеЗаписи.Значение;
Если ОбъектРаботы[ИмяРеквизита] <> ЗначениеОсновногоРеквизита Тогда
Если ПроверятьОсновнойРеквизит Тогда
Если ЗначениеЗаполнено(ОбъектРаботы[ИмяРеквизита]) Тогда
ОбъектМодифицирован = Истина;
Иначе
ТекстОшибки = "После переноса доп. реквизита, основной реквизит стал пустым. Обработка элемента прервана.";
ЗаписьЖурналаРегистрации("Обработка доп. реквизитов", УровеньЖурналаРегистрации.Ошибка, ОбъектРаботы.Метаданные(), ОбъектРаботы.Ссылка, ТекстОшибки);
Если Останаливать Тогда
Сообщить("Обработка прервана по ошибке. Посмотрите журнал регистрации");
Возврат;
Иначе Продолжить КонецЕсли;
КонецЕсли;
Иначе
ОбъектМодифицирован = Истина;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Если СтрокаТЗ[0].Очистить = Истина Тогда
Строка = ОбъектРаботы.ДополнительныеРеквизиты.Найти(ВыборкаДетальныеЗаписи.Свойство, "Свойство");
ОбъектРаботы.ДополнительныеРеквизиты.Удалить(Строка.НомерСтроки - 1);
ОбъектМодифицирован = Истина;
КонецЕсли;
КонецЦикла;
Если ОбъектМодифицирован Тогда
ОбъектРаботы.ОбменДанными.Загрузка = Истина;
ОбъектРаботы.Записать();
КонецЕсли;
Исключение
ТекстОшибки = ОписаниеОшибки();
ЗаписьЖурналаРегистрации("Обработка доп. реквизитов", УровеньЖурналаРегистрации.Ошибка, ОбъектРаботы.Метаданные(), ОбъектРаботы.Ссылка, ТекстОшибки);
Если Останаливать Тогда
Сообщить("Обработка прервана по ошибке. Посмотрите журнал регистрации");
Возврат;
КонецЕсли;
КонецПопытки;
КонецЦикла;
Сообщить("Обработка выполнена успешно");
КонецПроцедуры