Удмуртская Республика, г. Ижевск
Поиск
Войти
Заказать звонок

ЗаполнитьЗначенияСвойств() в 1С:Предприятии 7.7

19 июл 2017
#Программирование
Приемы и хитрости для того, чтобы заполнять сложные объекты с помощью одной строки программного кода.

Если вы занимаетесь разработкой в системе 1С:Предприятие 8, то наверняка знаете про функцию ЗаполнитьЗначенияСвойств(), с помощью которой можно очень быстро заполнить достаточно большие объекты. Причем объекты самые разные - структуры, таблицы и деревья значений, справочники, документы и др.

При параллельной разработке в предыдущей версии - 1С:Предприятии 7.7, когда приходится писать большие объемы программного кода, остро приходит понятие - какой же удобной функции не хватает.

Попробуем это исправить!

Итак, сценарий следующий - нужно заставить работать функцию ЗаполнитьЗначенияСвойств() в правилах конвертации, которые можно разработать с помощью 1С:Конвертация данных, ред. 2.1. Оговоримся - источником должна быть конфигурация на платформе 1С:Предприятие 7.7. Важно знать, что алгоритмы, которые разрабатываются с помощью конвертации, реализованы в виде функций, которые затем будут перенесены в обработку выгрузки. Исходя из этого, приступим.

Создаем алгоритмы

РазложитьСтрокуВМассивПодстрок

Свойства, которые нужно будет заполнить, или наоборот - исключить из заполнения будут передаваться с помощью строки с разделителями. Разделитель - запятая. С помощью этого алгоритма строка будет раскладываться в список значений.

РазложитьСтрокуВМассивПодстрок

Стр		= ИсходящиеДанные;
Разделитель	= ?(ЗначениеЗаполнено(ВходящиеДанные) = 1, ВходящиеДанные, ",");

Результат = СоздатьОбъект("СписокЗначений");

Если ПустаяСтрока(ИсходящиеДанные) = 1 Тогда 
	
	Возврат Результат;
	
ИначеЕсли Найти(ИсходящиеДанные, Разделитель) = 0 Тогда
	
	Результат.ДобавитьЗначение(ИсходящиеДанные);
	
	Возврат Результат;
	
КонецЕсли;                                  

Если Разделитель = " " Тогда
	
	Стр = СокрЛП(Стр);
	
	Пока 1=1 Цикл
		
		Поз = Найти(Стр, Разделитель);
		
		Если Поз=0 Тогда
			
			Результат.ДобавитьЗначение(СокрЛП(Стр));
			Возврат Результат;
			
		КонецЕсли;
		
		Результат.ДобавитьЗначение(СокрЛП(Лев(Стр, Поз-1)));
		Стр = СокрЛ(Сред(Стр, Поз));
		
	КонецЦикла;
	
Иначе
	
	ДлинаРазделителя = СтрДлина(Разделитель);
	
	Пока 1=1 Цикл
		
		Поз = Найти(Стр, Разделитель);
		
		Если Поз=0 Тогда
			
			Результат.ДобавитьЗначение(СокрЛП(Стр));
			Возврат Результат;
			
		КонецЕсли;
		
		Результат.ДобавитьЗначение(СокрЛП(Лев(Стр, Поз-1)));
		Стр = Сред(Стр,Поз+ДлинаРазделителя);
		
	КонецЦикла;
	
КонецЕсли;

Возврат Результат;

ЗаполнитьЗначенияСвойств

Рабочий алгоритм. Синтаксис - тот же, что и в 1С:Предприятии 8, позволяет заполнять справочники, документы, списки и таблицы значений.

ЗаполнитьЗначенияСвойств.png

// Выполняет заполнение приемника по данным источника.
//
//	Параметры:
//		ДанныеПриемник - Произвольный, справочник, документ, список значений, индексированная таблица или таблица значений.
//		ДанныеИсточник - Произвольный, справочник, документ, список значений, индексированная таблица или таблица значений.
//		СписокСвойствСтрока - Строка, список свойств, разделенных запятыми.
//		ИсключаяСвойстваСтрока - Строка, список исключаемых свойств, разделенных запятыми.
//
//	Возвращаемое значение:
//		Число, 1 - если заполнение выполнено успешно, 0 - не удалось выполнить заполнение.

ДанныеПриемник			= ИсходящиеДанные;
ДанныеИсточник			= ВходящиеДанные;
СписокСвойствСтрока		= Источник;
ИсключаяСвойстваСтрока	= Приемник;

ТипКоллекцииПриемник = ТипЗначенияСтр(ДанныеПриемник);
ТипКоллекцииИсточник = ТипЗначенияСтр(ДанныеИсточник);

///////////////////////////////////////////////////////////////////////////////
// Список свойств коллекции

Если ТипКоллекцииПриемник = "СписокЗначений" Тогда
	
	КоллекцияПоставщикСвойств = ДанныеИсточник;
	
ИначеЕсли (ТипКоллекцииПриемник = "ТаблицаЗначений")
	ИЛИ (ТипКоллекцииПриемник = "ИндексированнаяТаблица") Тогда
	
	Если ДанныеПриемник.КоличествоСтрок() = 0 Тогда
		
		Возврат 0;
		
	КонецЕсли;
	
	КоллекцияПоставщикСвойств = ДанныеПриемник;
	
ИначеЕсли (ТипКоллекцииПриемник = "Справочник")
	ИЛИ (ТипКоллекцииПриемник = "Документ") Тогда
	
	КоллекцияПоставщикСвойств = ДанныеПриемник;
	
Иначе
	
	Возврат 0;
	
КонецЕсли;

ТипКоллекцииПоставщик = ТипЗначенияСтр(КоллекцияПоставщикСвойств);

ПоляКоллекции = СоздатьОбъект("СписокЗначений");

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

///////////////////////////////////////////////////////////////////////////////
// Заполнение источника данными приемника

Для НомерСвойства = 1 По ПоляКоллекции.РазмерСписка() Цикл
	
	ИмяСвойства = ПоляКоллекции.ПолучитьЗначение(НомерСвойства);
	
	ЗначениеСвойства = "";
	
	Если ТипКоллекцииИсточник = "СписокЗначений" Тогда
		
		ЗначениеСвойства = ДанныеИсточник.Получить(ИмяСвойства);
		
	ИначеЕсли (ТипКоллекцииИсточник = "ТаблицаЗначений")
		ИЛИ (ТипКоллекцииИсточник = "ИндексированнаяТаблица") Тогда
		
		Если ЕстьКолонкаТаблицыЗначений(ДанныеИсточник, ИмяСвойства) = 0 Тогда 
			
			Продолжить;
			
		КонецЕсли;
		
		ЗначениеСвойства = ДанныеИсточник.ПолучитьЗначение(ДанныеИсточник.НомерСтроки, ИмяСвойства);
		
	ИначеЕсли ТипКоллекцииИсточник = "Справочник" Тогда
		
		Если ЕстьРеквизит(ИмяСвойства, ДанныеИсточник.Вид()) = 1 Тогда 		
			
			ЗначениеСвойства = ДанныеИсточник.ПолучитьАтрибут(ИмяСвойства); 
			
		КонецЕсли;	
		
	ИначеЕсли ТипКоллекцииИсточник = "Документ" Тогда
		
		Если ЕстьРеквизитШапки(ИмяСвойства, ДанныеИсточник.Вид()) = 1 Тогда 		
			
			ЗначениеСвойства = ДанныеИсточник.ПолучитьАтрибут(ИмяСвойства); 
			
		КонецЕсли;			
		
	КонецЕсли;
	
	Если ТипЗначенияСтр(ЗначениеСвойства) = "Строка" Тогда
		
		ЗначениеСвойства = СокрЛП(ЗначениеСвойства);
		
	КонецЕсли;		
	
	Если ТипКоллекцииПриемник = "СписокЗначений" Тогда
		
		ДанныеПриемник.Установить(ИмяСвойства, ЗначениеСвойства);
		
	ИначеЕсли (ТипКоллекцииПриемник = "ТаблицаЗначений")
		ИЛИ (ТипКоллекцииПриемник = "ИндексированнаяТаблица") Тогда
		
		Если ЕстьКолонкаТаблицыЗначений(ДанныеПриемник, ИмяСвойства) = 1 Тогда 
			
			ДанныеПриемник.УстановитьЗначение(ДанныеПриемник.НомерСтроки, ИмяСвойства, ЗначениеСвойства);
			
		КонецЕсли;
		
	ИначеЕсли ТипКоллекцииПриемник = "Справочник" Тогда
		
		Если ЕстьРеквизит(ИмяСвойства, ДанныеПриемник.Вид()) = 1 Тогда 
			
			ДанныеПриемник.УстановитьАтрибут(ИмяСвойства, ЗначениеСвойства);
			
		КонецЕсли;	
		
	ИначеЕсли ТипКоллекцииПриемник = "Документ" Тогда
		
		Если ЕстьРеквизитШапки(ИмяСвойства, ДанныеПриемник.Вид()) = 1 Тогда 
			
			ДанныеПриемник.УстановитьАтрибут(ИмяСвойства, ЗначениеСвойства);
			
		КонецЕсли;	
		
	КонецЕсли;
	
КонецЦикла;

Возврат 1;

Пример

Вот и все. Теперь метод ЗаполнитьЗначенияСвойств() будет доступен в любых обработчиках разрабатываемых правил.

ТаблицаИсточник = СоздатьОбъект("ТаблицаЗначений");
ТаблицаИсточник.НоваяКолонка("Контрагент");
ТаблицаИсточник.НоваяКолонка("Договор");
ТаблицаИсточник.НоваяКолонка("Сумма");

ТаблицаИсточник.НоваяСтрока();

ТаблицаИсточник.Контрагент = "Иванов";
ТаблицаИсточник.Договор = "Договор №1 от 01.02.2014";
ТаблицаИсточник.Сумма = 1000;

ТаблицаПриемник = СоздатьОбъект("ТаблицаЗначений");
ТаблицаПриемник.НоваяКолонка("Контрагент");
ТаблицаПриемник.НоваяКолонка("Договор");
ТаблицаПриемник.НоваяКолонка("Сумма");
ТаблицаПриемник.НоваяКолонка("Задолженность");

ТаблицаПриемник.НоваяСтрока();
ЗаполнитьЗначенияСвойств(ТаблицаПриемник, ТаблицаИсточник,, "Сумма,Договор");