Имя: Пароль:
1C
1C 7.7
v7: Как програмно скопировать элемент справочника?
0 avcherkasov
 
25.03.13
13:56
Собственно сабж. Вычитал, что это можно делать через метаданные, у кого есть часть кода, направте на путь истинный, пожалуйста. Справочник самописный, ему подчинён ещё один справочник, мне необходимо, чтобы по кнопке создавалась его копия с подчинением. Периодических реквизитов нет.
1 Wobland
 
25.03.13
13:58
ввод нового?
2 avcherkasov
 
25.03.13
13:59
(1) да
3 Злопчинский
 
25.03.13
13:59
открываем типовую конфигу ищем что-то типа
СкопироватьРеквизитыШапки()
.
деалаем аналогично
4 avcherkasov
 
25.03.13
14:00
(3) ок, сейчас посмотрю
5 ЧеловекДуши
 
25.03.13
14:00
(0) Через метаданные, единственное, где проблема - периодические реквизиты.
Но и там можно её решить укладыванием значений в какую либо ТЗ :)
6 avcherkasov
 
25.03.13
14:02
(3) у меня конфа комплексная. такой процедуры в глмодуле не нашёл.
(5) можете показать как это делать?
7 M0narch
 
25.03.13
14:13
//копирование документа
Процедура СкопироватьДоговор(Дог)
   
   ВидДокументов1 = "Договор";
   ТЗРекв1=СоздатьОбъект("ТаблицаЗначений");
   ТЗРекв1.НоваяКолонка("Стр","Число",1,0);//0 - если общий или шапка, 1 - если мн.ч.
   ТЗРекв1.НоваяКолонка("НомерВМетаданных","Число",4,0);
   ТЗРекв1.НоваяКолонка("Реквизит", "Строка", 40,0);
   Для Инд=1 По Метаданные.Документ() Цикл
       Если СокрЛП(Метаданные.Документ(Инд).Идентификатор)=ВидДокументов1 Тогда
           Прервать;  
       Иначе    
           продолжить;
       КонецЕсли;    
   КонецЦикла;    
   //На Этом этапе знаем номер, которому соответствует элемент метаданных для нашего документа

   Для НРекв1=1 По Метаданные.ОбщийРеквизитДокумента() Цикл
       ТЗРекв1.НоваяСтрока();
       ТЗРекв1.Стр=0;
       ТЗРекв1.НомерВМетаданных=НРекв1;
       ТЗРекв1.Реквизит=Метаданные.ОбщийРеквизитДокумента(НРекв1).Идентификатор;
   КонецЦикла;    
   ОбщРекв1=НРекв1;
   Для НРекв1=1 По Метаданные.Документ(Инд).РеквизитШапки() Цикл
       ТЗРекв1.НоваяСтрока();
       ТЗРекв1.Стр=0;
       ТЗРекв1.НомерВМетаданных=ОбщРекв1+НРекв1;
       ТЗРекв1.Реквизит=Метаданные.Документ(Инд).РеквизитШапки(НРекв1).Идентификатор;
   КонецЦикла;    
   Для НРекв1=1 По Метаданные.Документ(Инд).РеквизитТабличнойЧасти() Цикл
       ТЗРекв1.НоваяСтрока();
       ТЗРекв1.Стр=1;
       ТЗРекв1.НомерВМетаданных=НРекв1;
       ТЗРекв1.Реквизит=Метаданные.Документ(Инд).РеквизитТабличнойЧасти(НРекв1).Идентификатор;
   КонецЦикла;                                                
   Док1=Дог;
   НовыйДок1=СоздатьОбъект("Документ."+Док1.Вид());
   НовыйДок1.Новый();
   ТЗРекв1.ВыбратьСтроки();
   Пока ТЗРекв1.ПолучитьСтроку()=1 Цикл              
       Если ТЗРекв1.Стр<>0 Тогда
           продолжить;
       Иначе
           НовыйДок1.УстановитьАтрибут(СокрЛП(ТЗРекв1.Реквизит),Док1.ПолучитьАтрибут(СокрЛП(ТЗРекв1.Реквизит)))
       КонецЕсли;
   КонецЦикла;
   Док1.ВыбратьСтроки();
   Пока Док1.ПолучитьСтроку()=1 Цикл
       НовыйДок1.НоваяСтрока();
       ТЗРекв1.ВыбратьСтроки();
       Пока ТЗРекв1.ПолучитьСтроку()=1 Цикл              
           Если ТЗРекв1.Стр=0 Тогда
               продолжить;
           Иначе
               НовыйДок1.УстановитьАтрибут(СокрЛП(ТЗРекв1.Реквизит),Док1.ПолучитьАтрибут(СокрЛП(ТЗРекв1.Реквизит)))
               //Сообщить(""+СокрЛП(ТЗРекв.Реквизит)+" - "+Док.ПолучитьАтрибут(СокрЛП(ТЗРекв.Реквизит)));
           КонецЕсли;
       КонецЦикла;
   КонецЦикла;
   НовыйДок1.Фирма=выбФирма;
   НовыйДок1.УстановитьНовыйНомер(Сокрлп(НовыйДок1.Фирма.ПрефиксНомера)+"-");
   НовыйДок1.Записать();
8 M0narch
 
25.03.13
14:14
(7) думаю по аналогии можно и справочник
9 Kreont
 
25.03.13
14:18
(6) посмотри пример для справочника ТМЦ, процедуру ПриЗаписи()
10 ЧеловекДуши
 
25.03.13
14:25
ЭтоЭлементКопирования = СоздатьОбъект("Справочник.Номенклатура");
   ЭтоЭлементНовый = СоздатьОбъект("Справочник.Номенклатура");
   
   ЭтоЭлементНовый.Новый();
   
   //Реквизиты Код и Наименование придется всегда писать самому в метаданных это предопределенные реквизиты и не учавствуют в перечислении
   ЭтоЭлементНовый.Код = Число(ЭтоЭлементКопирования.Код); //или СокрЛП() для текстового кода
   //Или попросту жделаем так
   ЭтоЭлементНовый.УстановитьНовыйКод("0"); // И наслаждаемся всегда новым кодом
   //
   ЭтоЭлементНовый.Наименование = СокрЛП(ЭтоЭлементКопирования.Наименование);
   
   ЧтоЗаСправочник = "Номенклатура";
   Для шш1 = 1 По Метаданные.Справочник(ЧтоЗаСправочник).Реквизит() Цикл
       МетаРеквизит = Метаданные.Справочник(ЧтоЗаСправочник).Реквизит(шш1);
       
       Если МетаРеквизит.Периодический = 1 Тогда
           //И тут ты реквизит разбираешь, как периодический
       Иначе
           ЗначСправ = ЭтоЭлементКопирования.ПолучитьАтрибут(МетаРеквизит.Идентификатор);
       КонецЕсли;
       
   КонецЦикла;
   
   ЭтоЭлементНовый.Записать();
11 ЧеловекДуши
 
25.03.13
14:26
+(6) Так же Родитель и Владелец прописывается отдельно :)
12 Пронькин
 
25.03.13
14:42
В Комплексной, в Форме списка справочника Номенклатура есть процедура ПоКнопкеКопировать() - копирует элемент справочника с подчиненными...
13 avcherkasov
 
25.03.13
15:03
(12) у себя не нашёл такую, можете скинуть код?
14 Пронькин
 
25.03.13
15:22
Это есть в типовой, под рукой 518 релиз, из него...
//******************************************************************************
// СкопироватьЭлемент()
//
// Параметры:
//  
//
// Возвращаемое значение:
//  Нет
//
// Описание:
//  ТекстОписания
//
Процедура ПоКнопкеКопировать()
   Перем СписЕдиниц;
   
   ТекЭлемент    = ТекущийЭлемент();
   
   Если ПустоеЗначение(ТекЭлемент) = 1 Тогда
       Предупреждение("Не выбрана номенклатура для копирования!", 60);
   Иначе
       Если ТекЭлемент.ЭтоГруппа() = 1 Тогда
           Предупреждение("Выберите элемент, а не группу!", 60);
       Иначе
           СпрНоменклатура    = СоздатьОбъект("Справочник.Номенклатура");
           СпрНоменклатура.ИспользоватьРодителя(ТекЭлемент.Родитель);
           СпрНоменклатура.Новый();
           
           // копируем реквизиты
           СпрНоменклатура.Наименование        = ТекЭлемент.Наименование;
           СпрНоменклатура.Артикул                = ТекЭлемент.Артикул;
           СпрНоменклатура.Весовой                = ТекЭлемент.Весовой;
           СпрНоменклатура.ВидНоменклатуры        = ТекЭлемент.ВидНоменклатуры;
           СпрНоменклатура.Комментарий            = ТекЭлемент.Комментарий;
           СпрНоменклатура.МинОстаток            = ТекЭлемент.МинОстаток;
           СпрНоменклатура.НеВключатьВпрайс    = ТекЭлемент.НеВключатьВпрайс;
           СпрНоменклатура.НомерГТД            = ТекЭлемент.НомерГТД;
           СпрНоменклатура.ПолнНаименование    = ТекЭлемент.ПолнНаименование;
           СпрНоменклатура.СтавкаНДС            = ТекЭлемент.СтавкаНДС;
           СпрНоменклатура.СтавкаНП            = ТекЭлемент.СтавкаНП;
           СпрНоменклатура.СтранаПроисхождения    = ТекЭлемент.СтранаПроисхождения;
           
           НачатьТранзакцию();
           
               Попытка
                   СпрНоменклатура.Записать();
                   
                   СкопироватьЕдиницы(ТекЭлемент, СпрНоменклатура, СписЕдиниц);
                   СкопироватьЦены(ТекЭлемент, СпрНоменклатура, СписЕдиниц);
                   СкопироватьСвойства(ТекЭлемент, СпрНоменклатура);
                   СкопироватьАналоги(ТекЭлемент, СпрНоменклатура);
                   СкопироватьКомплектующие(ТекЭлемент, СпрНоменклатура);
                   
                   // запишем элемент после заполнения реквизитов
                   // БазоваяЕдиница, ОсновнаяЕдиница и ОсновноеСвойство
                   СпрНоменклатура.Записать();
               Исключение
                   ОтменитьТранзакцию();
                   Предупреждение(ОписаниеОшибки(), 60);
                   Возврат;
               КонецПопытки;
           
           ЗафиксироватьТранзакцию();
           
           АктивизироватьОбъект(СпрНоменклатура.ТекущийЭлемент());
           
           // откроем форму созданного элемента
           ОткрытьФорму(СпрНоменклатура.ТекущийЭлемент());
               
       КонецЕсли;
   КонецЕсли;
   
КонецПроцедуры // СкопироватьЭлемент()
15 Пронькин
 
25.03.13
15:25
еще вызываются процедуры:
Процедура СкопироватьЕдиницы(ЭлементИсточник, ЭлементПриемник, СписЕдиниц)
   СписЕдиниц    = СоздатьОбъект("ТаблицаЗначений");
   
   СписЕдиниц.НоваяКолонка("Единица"    , "Справочник.Единицы");
   СписЕдиниц.НоваяКолонка("ОКЕИ"        , "Справочник.ОКЕИ");
   
   СпрЕдиницы    = СоздатьОбъект("Справочник.Единицы");
   СпрЕдиницы.ИспользоватьВладельца(ЭлементПриемник.ТекущийЭлемент());
   
   СпрЕдИст    = СоздатьОбъект("Справочник.Единицы");
   СпрЕдИст.ИспользоватьВладельца(ЭлементИсточник);
   СпрЕдИст.ВыбратьЭлементы();
   Пока СпрЕдИст.ПолучитьЭлемент() = 1 Цикл
       СпрЕдиницы.Новый();
       
       СпрЕдиницы.ОКЕИ            = СпрЕдИст.ОКЕИ;
       СпрЕдиницы.Вес            = СпрЕдИст.Вес;
       СпрЕдиницы.Коэффициент    = СпрЕдИст.Коэффициент;
       
       // Сформируем новый штрихкод, если он был задан в источнике
       Если ПустоеЗначение(СпрЕдИст.ШтрихКод) = 0 Тогда
           СпрЕдиницы.ШтрихКод = СформироватьШтрихкод(ЭлементПриемник.Весовой, ЭлементПриемник.Код);
       КонецЕсли;
       
       СпрЕдиницы.Записать();
       
       СписЕдиниц.НоваяСтрока();
       ТекЕдиница            = СпрЕдиницы.ТекущийЭлемент();
       СписЕдиниц.Единица    = ТекЕдиница;
       СписЕдиниц.ОКЕИ        = ТекЕдиница.ОКЕИ;
       
       // устанавливаем базовую единицу
       Если СпрЕдиницы.ОКЕИ = ЭлементИсточник.БазоваяЕдиница.ОКЕИ Тогда
           ЭлементПриемник.БазоваяЕдиница    = СпрЕдиницы.ТекущийЭлемент();
       КонецЕсли;
       
       // устанавливаем основную единицу
       Если СпрЕдиницы.ОКЕИ = ЭлементИсточник.ОсновнаяЕдиница.ОКЕИ Тогда
           ЭлементПриемник.ОсновнаяЕдиница    = СпрЕдиницы.ТекущийЭлемент();
       КонецЕсли;
   КонецЦикла;
   
КонецПроцедуры // СкопироватьЕдиницы()


Процедура СкопироватьЦены(ЭлементИсточник, ЭлементПриемник, СписЕдиниц)
   
   СпрЦены    = СоздатьОбъект("Справочник.Цены");
   СпрЦены.ИспользоватьВладельца(ЭлементПриемник.ТекущийЭлемент());
   СпрЦены.ИспользоватьДату('01.01.1980');
   
   СпрЦеныИст    = СоздатьОбъект("Справочник.Цены");
   СпрЦеныИст.ИспользоватьВладельца(ЭлементИсточник);
   СпрЦеныИст.ИспользоватьДату(РабочаяДата());
   СпрЦеныИст.ВыбратьЭлементы();
   Пока СпрЦеныИст.ПолучитьЭлемент() = 1 Цикл
       СпрЦены.Новый();
       СпрЦены.ТипЦен    = СпрЦеныИст.ТипЦен;
       СпрЦены.Цена    = СпрЦеныИст.Цена;
       СпрЦены.Валюта    = СпрЦеныИст.Валюта;
       СпрЦены.Процент    = СпрЦеныИст.Процент;
       
       // в цене источнике указана единица другого товара
       // найдем нужную единицу текущего товара по ОКЕИ
       Поз    = 0;
       Если СписЕдиниц.НайтиЗначение(СпрЦеныИст.Единица.ОКЕИ, Поз, "ОКЕИ") =1 Тогда
           СпрЦены.Единица    = СписЕдиниц.ПолучитьЗначение(Поз, "Единица");
           СпрЦены.Записать();
       КонецЕсли;
   КонецЦикла;
   
КонецПроцедуры // СкопироватьЦены()


Процедура СкопироватьСвойства(ЭлементИсточник, ЭлементПриемник)
   
   ОснСвойство    = ЭлементИсточник.ОсновноеСвойство;

   СпрСвойства    = СоздатьОбъект("Справочник.СвойстваНоменклатуры");
   СпрСвойства.ИспользоватьВладельца(ЭлементПриемник.ТекущийЭлемент());
   
   СпрСвойстваИст    = СоздатьОбъект("Справочник.СвойстваНоменклатуры");
   СпрСвойстваИст.ИспользоватьВладельца(ЭлементИсточник);
   
   СпрСвойстваИст.ВыбратьЭлементы();
   Пока СпрСвойстваИст.ПолучитьЭлемент() = 1 Цикл
       СпрСвойства.Новый();
       
       СпрСвойства.ВидСвойства            = СпрСвойстваИст.ВидСвойства;
       СпрСвойства.ЗначениеСвойства    = СпрСвойстваИст.ЗначениеСвойства;
       
       СпрСвойства.Записать();
       
       Если (ОснСвойство.ВидСвойства = СпрСвойства.ВидСвойства) И (ОснСвойство.ЗначениеСвойства = СпрСвойства.ЗначениеСвойства) Тогда
           ЭлементПриемник.ОсновноеСвойство    = СпрСвойства.ТекущийЭлемент();
       КонецЕсли;
   КонецЦикла;
   
КонецПроцедуры // СкопироватьСвойства()


Процедура СкопироватьАналоги(ЭлементИсточник, ЭлементПриемник)
   
   СпрАналоги    = СоздатьОбъект("Справочник.Аналоги");
   СпрАналоги.ИспользоватьВладельца(ЭлементПриемник.ТекущийЭлемент());
   
   СпрАналогиИст    = СоздатьОбъект("Справочник.Аналоги");
   СпрАналогиИст.ИспользоватьВладельца(ЭлементИсточник);
   
   СпрАналогиИст.ВыбратьЭлементы();
   Пока СпрАналогиИст.ПолучитьЭлемент() = 1 Цикл
       СпрАналоги.Новый();
       
       СпрАналоги.Наименование                = СпрАналогиИст.Наименование;
       СпрАналоги.Каталог                    = СпрАналогиИст.Каталог;
       СпрАналоги.ИдентификаторВКаталоге    = СпрАналогиИст.ИдентификаторВКаталоге;
       
       СпрАналоги.Записать();
   КонецЦикла;

КонецПроцедуры // СкопироватьАналоги()


Процедура СкопироватьКомплектующие(ЭлементИсточник, ЭлементПриемник)
   
   СпрКомплектация    = СоздатьОбъект("Справочник.Комплектация");
   СпрКомплектация.ИспользоватьВладельца(ЭлементПриемник.ТекущийЭлемент());
   
   СпрКомплектацияИст    = СоздатьОбъект("Справочник.Комплектация");
   СпрКомплектацияИст.ИспользоватьВладельца(ЭлементИсточник);
   
   СпрКомплектацияИст.ВыбратьЭлементы();
   Пока СпрКомплектацияИст.ПолучитьЭлемент() = 1 Цикл
       СпрКомплектация.Новый();
       
       СпрКомплектация.Номенклатура    = СпрКомплектацияИст.Номенклатура;
       СпрКомплектация.Количество        = СпрКомплектацияИст.Количество;
       СпрКомплектация.ЦеновойКоэфф    = СпрКомплектацияИст.ЦеновойКоэфф;
       
       СпрКомплектация.Записать();
   КонецЦикла;
   
КонецПроцедуры // СкопироватьКомплектующие()


Уффф., всё вроде...
16 avcherkasov
 
25.03.13
15:38
(15) спасибо, буду глядеть. У себя не нашёл такое, т.к. у меня комплексная для Украины, а 518 - наверное Россия ))
17 Пронькин
 
25.03.13
15:45
Да, Российская!
18 AntiBuh
 
25.03.13
16:19
В комплексной глЗаполнитьШапку()
19 Kreont
 
25.03.13
16:48
(16) как раз для комплексной написал где смотреть : (9)
20 Franchiser
 
гуру
25.03.13
16:52
21 avcherkasov
 
26.03.13
11:38
Сделал не используя метаданные. Вот конечная процедура, может идея кому-то ещё пригодится. Всем большое спасибо, кто помогал советами.

Процедура ВсеМагазины()        //создаём копии набора для всех магазинов    
   Ответ = Вопрос("Вы уверены, что необходимо создать этот набор для всех магазинов?",3);
   Если (Ответ = 2) или (Ответ = 7)  Тогда
       // нажали кнопку Отмена или Нет
       Возврат;
   Иначе    //нажали кнопку Да        
       ЭтоЭлементКопирования = ТекущийЭлемент();        
       СпрНаборы = СоздатьОбъект("Справочник.Наборы");
       СпрНаборы.ВыбратьЭлементы();        
       ЭтоЭлементНовый = СоздатьОбъект("Справочник.Наборы");
       
       Пока СпрНаборы.ПолучитьЭлемент() = 1 Цикл
           Если СпрНаборы.ЭтоГруппа() = 1 Тогда
               Если СпрНаборы.Склад <> ЭтоЭлементКопирования.Склад Тогда    //копируем все элементы, кроме выбранного                
                   ЭтоЭлементНовый.Новый();        
                   // копируем реквизиты набора
                   ЭтоЭлементНовый.УстановитьНовыйКод("0");
                   ЭтоЭлементНовый.Наименование = СокрЛП(ЭтоЭлементКопирования.Наименование);
                   ЭтоЭлементНовый.Склад = СпрНаборы.ТекущийЭлемент().Склад;    
                   ЭтоЭлементНовый.Родитель = СпрНаборы.ТекущийЭлемент();    //создаём копии наборов магазинов в их папках                    
                   ЭтоЭлементНовый.СкидкаНал = ЭтоЭлементКопирования.СкидкаНал;
                   ЭтоЭлементНовый.СкидкаБонус = ЭтоЭлементКопирования.СкидкаБонус;
                   ЭтоЭлементНовый.флСкидкаНал = ЭтоЭлементКопирования.флСкидкаНал;
                   ЭтоЭлементНовый.флСкидкаБонус = ЭтоЭлементКопирования.флСкидкаБонус;                    
                   Сообщить("Создаю копию набора для магазина " + ЭтоЭлементНовый.Склад);                    
                   ЭтоЭлементНовый.Записать();        
                   
                   СпрСоставНабораИст = СоздатьОбъект("Справочник.СоставНабора");                
                   СпрСоставНабораИст.ИспользоватьВладельца(ЭтоЭлементКопирования);        
                   СпрСоставНабораИст.ВыбратьЭлементы();
                   ЭтоЭлементНовыйСоставНабора = СоздатьОбъект("Справочник.СоставНабора");
                   
                   Пока СпрСоставНабораИст.ПолучитьЭлемент() = 1 Цикл                                    
                       //копируем состав набора                        
                       ЭтоЭлементНовыйСоставНабора.Новый();                
                       ЭтоЭлементНовыйСоставНабора.Владелец = ЭтоЭлементНовый.ТекущийЭлемент();
                       ЭтоЭлементНовыйСоставНабора.УстановитьНовыйКод("0");    //устанавливаем новый код, т.к. Код (уникальный), а КодНабора - нет                                        
                       ЭтоЭлементНовыйСоставНабора.КодНабора = ЭтоЭлементНовый.Код;                        
                       ЭтоЭлементНовыйСоставНабора.Товар = СпрСоставНабораИст.Товар;                    
                       ЭтоЭлементНовыйСоставНабора.Кво = СпрСоставНабораИст.Кво;                    
                       ЭтоЭлементНовыйСоставНабора.Записать();                                    
                   КонецЦикла;
               КонецЕсли;                
           КонецЕсли;
       КонецЦикла;            
   КонецЕсли;
КонецПроцедуры // ВсеМагазины
22 Franchiser
 
гуру
26.03.13
14:04
Поспрашивал и решил задачу в лоб...
23 Franchiser
 
гуру
26.03.13
14:08
Недостаток твоей процедуры в том что если добавятся новые реквизиты, придется ее переписывать, или что-то не будет заполнятся и ты не сразу о ней вспомнишь.
24 avcherkasov
 
28.03.13
19:05
(23) Основная задача была с копированием элемента справочника с подчинёнными элементами, а в той книге, что вы скидывали написано: "В процедуре есть несколько изъянов: не копируются периодические реквизиты и не создаются подчиненные справочники." Так какой смысл всё равно огород городить?
Программист всегда исправляет последнюю ошибку.