Создание и заполнение документа основания программно из модуля формы

Программирование - Практика программирования

Работа с модулями форм документов УФ

Это очередная публикация, можно судить строго.

Как-то раз, юзая наши сетевые информационные пространства, взбрела в голову мысль создавать и заполнять на основании одного документа другой, причем программно, командой в командной панели на форме. 

Надеюсь этой статьей помочь таким же, как и я в свое время (Таковых много, я смотрел на различных форумах аналогичные безответные запросы);

В моем случае необходимо было создать документ "Расходная накладная" на основании документа "Заказ покупателя" с проверкой на проведенность и с изменением реквизита в основном документе после проведения и самое главное баз открытия создаваемого документа.

Использовались самые стандартные и на мой взгляд самые рабочие методы исполнения из формы документа. Если есть круче с удовольствием прочту в комментариях.

Практика.

1. Методом несложных манипуляций создаем кнопку на командной панели списка документов "Заказы покупателей" с именем "СоздатьРасходнуюНакладную".

2. В модуле формы основного документа прописываем Функцию на Сервере и процедуру на Клиенте.

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

//При повторном создании документа количество запасов в ТЧ запасы = 0 Заведомо запрещаем дальнейшие действия(ТАКОВ ПОДХОД)	
	Если Док1.Запасы.Количество()=0 тогда
				Сообщить("Вы уже создали ВАШ_ДОКУМЕНТ!");
		Возврат Ложь;
	КонецЕсли;	

//Проверяем документ на заполненность, если созданный на основании документ заполнен, то проводим и оповещаем пользователя 	
	    Если Док1.Запасы.Количество()>0 Тогда
		Док1.Записать(Режимзаписидокумента.Проведение);
		Сообщить("Создан документ "+Док1);

//Проверяем если документ проведен, то устанавливаем реквизит документа основания в определенное состояние		
		Если Док1.Проведен тогда
		Объект.СостояниеЗаказа=Справочники.СостоянияЗаказовПокупателей.НайтиПоКоду("ВАШ_КОД");
			Возврат Истина;
		КонецЕсли;
	Иначе
//Если эта операция была проделана ранее то выдаем сообщение пользователю 		
		Сообщить("Вы уже создали ВАШ_ДОКУМЕНТ!");
		Возврат Ложь;

	    КонецЕсли;
КонецФункции

//Команду с кнопкой мы поместили на командной панели нашего документа основания и указываем нашу процедуру
//
&НаКлиенте
Процедура СоздатьРасходнуюНакладную(Команда)	
//Определяем наш Док1 и выполняем команду и закрываем форму оновного документа;
Док1=СоздатьРасходнуюНакладнуюНаСервере();
Если Док1 тогда
	Записать();
Конецесли;
//Закрывем форму
Закрыть();
КонецПроцедуры

Вот таким путем мы создали на основании документ с заполнением всех необходимых нам  данных, с проведением документов и без открытия формы созданного документа!

End;

См. также

Комментарии
1. Михаил Кузнецов (mvk4d) 03.05.18 07:54 Сейчас в теме
"Закрыть" - это метод.
На ИТС есть микро статья про это: https://its.1c.ru/db/metod8dev/content/2484/hdoc
2. Шаман Бубновый (DENSKR) 5 04.05.18 19:45 Сейчас в теме
(1)
"Закрыть"
Закрываем текущую форму а не форму созданного дока
3. Михаил (MVK80) 04.05.18 20:38 Сейчас в теме
(2) Так, а что это меняет? Нет такого свойства "Закрыть", есть только метод "Закрыть()". Скобок не хватает. Проверка модуля ругается.
4. Шаман Бубновый (DENSKR) 5 04.05.18 20:59 Сейчас в теме
(3)Точно) Не заметил) Спасибо.
5. Бубузяка (Бубузяка) 62 10.05.18 11:52 Сейчас в теме
Я себе позволил изменить немного код автора. Правки отмечены "NB".


&НаСервере
Функция СоздатьРасходнуюНакладнуюНаСервере()
	
	// ++ NB 
	//ЭтотДокумент = РеквизитФормыВЗначение("Объект");
	//ЭтотДокумент.Записать(РежимЗаписиДокумента.Проведение);
	//ЗначениеВРеквизитФормы(ЭтотДокумент, "Объект");
	// -- NB
	
	Док1=Документы.РасходнаяНакладная.СоздатьДокумент();
	Док1.Заполнить(Объект.ссылка);
	Док1.Дата=ТекущаяДата();
	Док1.Ответственный=Объект.Ответственный;
	Док1.Подразделение=Объект.СтруктурнаяЕдиницаПродажи;
	Док1.Автор=Объект.Автор;
	Док1.Комментарий=Объект.Комментарий;
	
	//При повторном создании документа количество запасов в ТЧ запасы = 0 Заведомо запрещаем дальнейшие действия(ТАКОВ ПОДХОД)	
	Если Док1.Запасы.Количество()=0 тогда
		Сообщить("Вы уже создали ВАШ_ДОКУМЕНТ!");
		Возврат Ложь;
	КонецЕсли;	
	
	//Проверяем документ на заполненность, если созданный на основании документ заполнен, то проводим и оповещаем пользователя 	
	Если Док1.Запасы.Количество()>0 Тогда
		// ++ NB 
		Попытка
			Док1.Записать(Режимзаписидокумента.Проведение);
		Исключение
			// Сново что-то пошло не так. :(
			Сообщить(КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
			Возврат Ложь;
		КонецПопытки;
		// -- NB 
		
		Сообщить("Создан документ "+Док1);
		
		// ++ NB: "Док1.Проведен" Зачем проверять проведен или нет? Мы же его проводим. 
		
		//Проверяем если документ проведен, то устанавливаем реквизит документа основания в определенное состояние		
		Если Док1.Проведен тогда
			
			// ++ NB: Не очень хорошая идея модифицировать текущй объект в функции создания другого объекта.
			//		  Это нарушет логику модуля. Поясню. По коду понятно, что происходит.
			//		  События: - запись текущего документа,
			//				   - заполнение и проведение нового документа,	
			//			       - изменение состояния текущего документа,
			//				   - завершение работы с текущим документом (закрыли форму).
			//        Поэтому, изменение состояние лучше вынести в обработчик команды, ибо - это
			//		  результат ввода на основании. Стороннему разработчику и автору (год спустя)
			//		  легче уловить цепт событий.
			// -- NB 
			Объект.СостояниеЗаказа=Справочники.СостоянияЗаказовПокупателей.НайтиПоКоду("ВАШ_КОД");
			Возврат Истина;
		КонецЕсли;
	Иначе
		//Если эта операция была проделана ранее то выдаем сообщение пользователю 		
		Сообщить("Вы уже создали ВАШ_ДОКУМЕНТ!");
		Возврат Ложь;
	КонецЕсли;
	
КонецФункции

//Команду с кнопкой мы поместили на командной панели нашего документа основания и указываем нашу процедуру
//
&НаКлиенте
Процедура СоздатьРасходнуюНакладную(Команда)
	
	// ++ NB 
	// "Безопасная" запись и проведение.
	Если НЕ ПроверитьЗаполнение() Тогда
		// Текущий документ не готов к проведению.
		Возврат;
	КонецЕсли; 
	
	ПараметрыЗаписи = Новый Структура("РежимЗаписи", РежимЗаписиДокумента.Проведение); 
	Если НЕ Записать(ПараметрыЗаписи) Тогда
		// Что-то пошло не так и документ не удалось провести.
		Возврат;
	КонецЕсли; 
	// -- NB

	//Определяем наш Док1 и выполняем команду и закрываем форму оновного документа;
	Док1=СоздатьРасходнуюНакладнуюНаСервере();
	Если Док1 тогда
		Записать();
	Конецесли;
	//Закрывем форму
	Закрыть();
КонецПроцедуры
Показать
7. Шаман Бубновый (DENSKR) 5 11.05.18 10:09 Сейчас в теме
(5)
(6) Хорошие замечания, возьму к вооружению.
6. Павел Кузнецов (user596590_pavel.kuznecov) 17 10.05.18 12:37 Сейчас в теме
//Команду с кнопкой мы поместили на командной панели нашего документа основания и указываем нашу процедуру

Про дополнительные обработки и БСП не слышали? Все это можно оформить без изменения конфигурации, создав и подключив дополнительную внешнюю обработку. В модуле обработке должна присутствовать экспортная функция "СведенияОВнешнейОбработке":
Функция СведенияОВнешнейОбработке() Экспорт
    ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке("2.2.2.1");
    ПараметрыРегистрации.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиСозданиеСвязанныхОбъектов();
    ПараметрыРегистрации.Версия = "1.0.0.1";
    Команда = ПараметрыРегистрации.Команды.Добавить();
    Команда.Представление = НСтр("ru = '<Пишем наше представление команды>'");
    Команда.Идентификатор = "<Пишем наше имя команды>";
    Команда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовСерверногоМетода();
    Команда.ПоказыватьОповещение = Ложь;
    Возврат ПараметрыРегистрации; 
КонецФункции
Показать


Здесь же в модуле обработки создаете экспортную функцию ВыполнитьКоманду() :
 Процедура ВыполнитьКоманду(ИдентификаторКоманды, ОбъектыНазначения, СозданныеОбъекты, ПараметрыВыполнения) Экспорт
       	// Реализация логики команды.
       КонецПроцедуры

ОбъектыНазначения - Массив ссылок на документы-основания. Почему массив: для обеспечения возможности создания связанных объектов из формы списка множественным выделением. То есть выделили произвольно документы, нажали кнопку, и для всех выделенных документов будут созданы связанные объекты. Идентификатор команды нужен когда в одной обработке несколько команд, в вашем случае игнорируйте. Остальные параметры тоже Вам не понадобятся. Описание команд и их параметров можно посмотреть в комментарии к функции "ТипКомандыВызовСерверногоМетода".
cepera1575; 1cccc; DENSKR; +3 Ответить
8. Игорь Герман (German_Tagil) 6 12.05.18 15:17 Сейчас в теме
Оставьте свое сообщение