Копирование группы номенклатуры с иерархией вложенных элементов

0. dreamwaver_dz 27.02.17 13:50 Сейчас в теме
Рекурсивное копирование группы номенклатуры с иерархией вложенных элементов.
Описание всех процедур и изменений, статья подойдёт даже новичкам.

Перейти к публикации

Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. rus128 2 01.03.17 11:40 Сейчас в теме
Все хорошо, только опечатка "втавляем" (3 раза).
2. japopov 60 01.03.17 11:54 Сейчас в теме
По-первых, у Вас - под обычные формы, хорошо бы предупредить. Под управляемое приложение придётся переписывать.
Во-вторых, плохая реализация. Рекурсия отрабатывает очень медленно, нагружает машину (в Вашем случае - клиента) и чревата переполнением стека для многоуровневых справочников.
Тем более, что Вы делаете запрос по копируемым объектам. Что мешает обойтись вообще без рекурсии? Немного подумать - и сделать простым построчным обходом таблицы. Сработает в разы быстрее, и разница будет тем больше, чем большее число уровней вложенности.
3. DrAku1a 1315 02.03.17 02:58 Сейчас в теме
Копирование без рекурсии
Запрос = Новый Запрос("ВЫБРАТЬ
	|	Номенклатура.Ссылка,
	|	Номенклатура.ЭтоГруппа,
	|	Номенклатура.Родитель
	|ИЗ
	|	Справочник.Номенклатура КАК Номенклатура
	|ГДЕ
	|	Номенклатура.Ссылка В ИЕРАРХИИ(&Группа)
	|
	|УПОРЯДОЧИТЬ ПО
	|	Номенклатура.Ссылка ИЕРАРХИЯ");
Запрос.УстановитьПараметр("Группа", Элемент.ТекущаяСтрока);

РезультатЗапроса = Запрос.Выполнить();
Если РезультатЗапроса.Пустой() Тогда
	Возврат;
КонецЕсли;

Предок = ?(Строка.ЭтоГруппа, Строка, Справочники.Номенклатура.ПустаяСсылка()); //Если перетащили не на группу, то кидаем всё дерево в корень
мСоответствиеГрупп = новый Соответствие;
мСоответствиеГрупп.Вставить(Элемент.ТекущаяСтрока.Родитель, Предок);

Выборка = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.Прямой);
Пока Выборка.Следующий() Цикл
      ТекСпр = Выборка.Ссылка.ПолучитьОбъект();
      элементСправочника = ТекСпр.Скопировать();
      элементСправочника.Родитель = мСоответствиеГрупп[Выборка.Родитель];

      // ** Если мы хотим запомнить откуда была скопирована номенклатура - нужно            **
      // ** предварительно добавить реквизит ОбразецНоменклатуры в справочник Номенклатура  **  
      // ** типа "СправочникСсылка.Номенклатура" а затем раскомментировать следующую строку **
      //элементСправочника.ОбразецНоменклатуры=ТекСпр.Ссылка;

      // При желании здесь можно создавать подчинённые справочники вроде "единицы измерения" 
      // и сюда записывать все необходимые ссылки

      элементСправочника.Записать();

      Если Выборка.ЭтоГруппа Тогда //Когда встречаем группу, то запоминаем её
          мСоответствиеГрупп.Вставить(Выборка.Ссылка, элементСправочника.Ссылка);
      КонецЕсли;	
КонецЦикла;
Показать
Поручик; +1 Ответить
6. Поручик 4429 17.09.18 08:53 Сейчас в теме
7. elian 83 19.02.19 21:21 Сейчас в теме
Действительно хорошая задумка!
8. user705522_constantin_h 28 26.06.19 11:25 Сейчас в теме
Для управляемых форм:
&НаКлиенте
Процедура СписокПеретаскивание(Элемент, ПараметрыПеретаскивания, СтандартнаяОбработка, Строка, Поле)

    // Для Левой клавиши мышки происходит простое перетаскивание и тут нам ничего не нужно делать
    // Если же оператор потянул группу товаров правой клавишей...

    Если ПараметрыПеретаскивания.Действие = ДействиеПеретаскивания.Выбор Тогда
        СтандартнаяОбработка = Ложь;

        //Готовим список действий для нашего контекстного меню
        Действия = Новый СписокЗначений;
        Действия.Добавить("Переместить","Переместить");
        Действия.Добавить("Копировать","Копировать");
        Действия.Добавить("Отмена","Отмена");

		ДополнительныеПараметры = Новый Структура;
		ДополнительныеПараметры.Вставить("ПараметрыПеретаскивания", ПараметрыПеретаскивания);
		ДополнительныеПараметры.Вставить("Элемент", Элемент);
		ДополнительныеПараметры.Вставить("Строка", Строка);
		
        //Выводим меню рядом с нашим элементом и ждём ответа пользователя
		ОповещениеПослеВыбораЭлемента = Новый ОписаниеОповещения("СообщитьРезультат", ЭтотОбъект, ДополнительныеПараметры);
		Действия.ПоказатьВыборЭлемента(ОповещениеПослеВыбораЭлемента, "Выберите действие");

    КонецЕсли;    
КонецПроцедуры

&НаКлиенте
Процедура СообщитьРезультат(Элемент, Параметры) Экспорт
		Если Элемент.Значение = "Переместить" Тогда //Передаём обработку стандартному механизму перетаскивания

            Параметры.ПараметрыПеретаскивания.Действие = ДействиеПеретаскивания.Перемещение;
            СтандартнаяОбработка=Истина;

        ИначеЕсли Элемент.Значение = "Копировать" Тогда //Собственно выбираем элементы (ветку) для дальнейшей обработки

			ВыполнитьКопирование(Параметры.Элемент.ТекущаяСтрока, Параметры.Строка);
        КонецЕсли;
КонецПроцедуры


&НаСервере
Процедура ВыполнитьКопирование(ТекущаяГруппа, Строка)
	Запрос = Новый Запрос("ВЫБРАТЬ
	|    Номенклатура.Ссылка,
	|    Номенклатура.ЭтоГруппа,
	|    Номенклатура.Родитель
	|ИЗ
	|    Справочник.Номенклатура КАК Номенклатура
	|ГДЕ
	|    Номенклатура.Ссылка В ИЕРАРХИИ(&Группа)
	|
	|УПОРЯДОЧИТЬ ПО
	|    Номенклатура.Ссылка ИЕРАРХИЯ");
	Запрос.УстановитьПараметр("Группа", ТекущаяГруппа);
	
	РезультатЗапроса = Запрос.Выполнить();
	Если РезультатЗапроса.Пустой() Тогда
		Возврат;
	КонецЕсли;
	
	Предок = ?(Строка.ЭтоГруппа, Строка, Справочники.Номенклатура.ПустаяСсылка()); //Если перетащили не на группу, то кидаем всё дерево в корень
	мСоответствиеГрупп = новый Соответствие;
	мСоответствиеГрупп.Вставить(ТекущаяГруппа.Родитель, Предок);
	
	Выборка = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.Прямой);
	Пока Выборка.Следующий() Цикл
		ТекСпр = Выборка.Ссылка.ПолучитьОбъект();
		элементСправочника = ТекСпр.Скопировать();
		элементСправочника.Родитель = мСоответствиеГрупп[Выборка.Родитель];
		
		// ** Если мы хотим запомнить откуда была скопирована номенклатура - нужно            **
		// ** предварительно добавить реквизит ОбразецНоменклатуры в справочник Номенклатура  **  
		// ** типа "СправочникСсылка.Номенклатура" а затем раскомментировать следующую строку **
		//элементСправочника.ОбразецНоменклатуры=ТекСпр.Ссылка;
		
		// При желании здесь можно создавать подчинённые справочники вроде "единицы измерения" 
		// и сюда записывать все необходимые ссылки
		
		элементСправочника.Записать();
		
		Если Выборка.ЭтоГруппа Тогда //Когда встречаем группу, то запоминаем её
			мСоответствиеГрупп.Вставить(Выборка.Ссылка, элементСправочника.Ссылка);
		КонецЕсли;    
	КонецЦикла;
КонецПроцедуры
Показать
Оставьте свое сообщение
Вопросы с вознаграждением