Суть задачи:
Бывают случаи, когда у нескольких элементов справочника необходимо создать идентичную историю изменения периодических реквизитов.
Например: история цен, наценок, норм упаковки и др. для нескольких товаров, отличающихся только цветом - или размером, или иным бухгалтерски не значимым параметром.
Или история всякоразных условий работы для нескольких ипостасей одного и того же контрагента.
В общем, я с этой задачей сталкивался неоднократно, так что, наверное, не одинок
Излагаю на примере справочника "Номенклатура". В данном случае в каждом элементе в поле ГлавныйЛист хранится ссылка на "эталонный" элемент, из которого нужно брать соответствующие реквизиты.
Фрагменты модуля формы списка номенклатурника.
Поехали....
Перем ИмяВрТаб; //Здесь будем хранить ID реквизитов, подлежащих синхронизации
Перем лЗапросПолн; //Единожды создадим параметрический запрос для многократного юзания
//****
Процедура ПриОткрытии()
//..............
//Подготовим все для запроса
СписокМета=СоздатьОбъект("ТаблицаЗначений");
СписокМета.НоваяКолонка("ID","Число");
ИмяВрТаб=глУникальность(); //...ну, это по вкусу - кто как создает имена врем.таблиц.
лЗапрос=СоздатьОбъект("ODBCRecordSet");
лЗапрос.Выполнить("IF EXISTS (SELECT * FROM tempdb..sysobjects WHERE ID=OBJECT_ID('tempdb.."+ИмяВрТаб+"') AND sysstat & 0xf = 3 )
|DROP TABLE "+ИмяВрТаб);
лЗапрос.Выполнить("CREATE TABLE "+ИмяВрТаб+"( ID INT, PRIMARY KEY CLUSTERED (ID) )");
КолРекв=Метаданные.Справочник("Номенклатура").Реквизит();
Для ъ=1 По КолРекв Цикл //Собираем все периодические реквизиты
ТекРекв=Метаданные.Справочник("Номенклатура").Реквизит(ъ);
Если ТекРекв.Периодический=0 Тогда
Продолжить;
КонецЕсли;
//а здесь, при необходимости, можно исключить из обработки некоторые из реквизитов (Если...Продолжить)
СписокМета.НоваяСтрока();
СписокМета.ID = Число(гМета.ИДОбъекта(ТекРекв));
КонецЦикла;
лЗапрос.Подготовить("Insert into "+ИмяВрТаб+" Values (?)");
лЗапрос.ВыполнитьSQL_ИзТЗ(СписокМета); //Готовим временную таблицу
лЗапросПолн=СоздатьОбъект("ODBCRecordSet"); //Готовим запрос
лЗапросПолн.Подготовить("
|set nocount on
|
|DECLARE @ТоварФильтр char(9)
|
|SET @ТоварФильтр = ?
|
|BEGIN TRANSACTION
//Потенциально деструктивная операция - без транзакции никак
|
//Тут у меня было еще размножение непериодических реквизитов через UPDATE - долго и очевидно, выкинул нафик
|
|DECLARE @vu TABLE ( objid CHAR(9), PRIMARY KEY CLUSTERED (objid) )
|
|INSERT INTO @vu
|SELECT ID FROM
|$Справочник.Номенклатура (NOLOCK)
|WHERE
|$Справочник.Номенклатура.ГлавныйЛист = @ТоварФильтр
|AND
|ID <> @ТоварФильтр
|AND
|isfolder<>1
//Подготовили список элементов, подлежащих обработке
//Характерно, что дальше код универсален и вообще не зависит от вида справочника
|
|exec _1sp__1SCONST_TLockX
// на всякий случай заблокировали константы
|
|delete from _1sconst
|where
|id in (select id from "+ИмяВрТаб+")
|and
|objid in (select * from @vu)
|and docid = ' 0 '
// удалили предыдущую историю согласно расстрельных списков НКВД
|
|
|insert into _1sconst
|(id, objid, date, value, docid, time, actno,lineno_,tvalue)
|select seed.id as id, tlist.objid as objid, seed.date as date, seed.value as value, seed.docid as docid, seed.time as time, seed.actno as actno, seed.lineno_ as lineno_, seed.tvalue as tvalue
|from
|(select * from _1sconst
|where
|id in (select id from "+ИмяВрТаб+")
|and
|objid = @ТоварФильтр
|and docid = ' 0 '
|) seed
|cross join
|@vu
|tlist
// ну и, наконец, записали новую историю. А то раньше я часто задумывался, зачем придумали cross join :)
|
|COMMIT TRANSACTION
|"
);
лЗапросПолн.ДобПараметр(1,14,9,0);
//Вот теперь все действительно готово_
//********************
КонецПроцедуры
//Теперь, по мере надобности многократно используем.запрос по назначению - в данном случае размножаем реквизиты элемента "Ста"
лЗапросПолн.УстПараметр(1,гМета.ЗначениеВСтрокуБД(Ста));
лЗапросПолн.Выполнить();