Вывод дерева в табличный документ СКД

Публикация № 1262105 09.07.20

Приемы и методы разработки

Вывод дерева дерево значений СКД программная работа

Вывод содержимого элемента формы "ДанныеФормыДерево" в табличный документ средствами СКД.

Задача возникла потому, что ... в панельке "Вывести список" не оказалось флажка "С подчинёнными". Решать надо было срочно, вдобавок клиент хотел результат со всеми бантиками условного оформления, а это платформа не умеет. В итоге немного обычного программного создания и настройки СКД, и получилась универсальная механика, пригодная к копипасту и немедленному использованию.
Что умеет: выводит дерево из элемента формы, связанного с реквизитом формы или реквизитом объекта формы, точно сохраняя иерархию и условное оформление.
Чего не умеет: сворачивать группировки, как это в элементе формы; и ещё в этой версии я не публикую вывод данных шапки и подвала дерева (хотя можно сделать). Ну и хитрые пути к данным в разыменованных колонках не факт, что все возьмёт (хотя в таких случаях и сам-то элемент формы не всегда корректно отрабатывает).

Чем ещё интересна - пожалуй, программной работой с СКД и, в частности, соединением набора с самим собой, что описано, например, https://start1c.blogspot.com/2017/01/blog-post.html и на ИС тоже встречалось. Таким образом, всё это чуть допиленный баян.
 

 
 Собственно механизм

 



// Вспомогательная для ВывестиДеревоВТабличныйДокумент
&НаСервере
Процедура РекурсивноЗаполнитьКолонкиПоЭлементам(элфРодитель,рПрефиксПути,рИмяРеквизитаДерева,рКолонкиДерева,рКолонкиТаблицы,соотРеквизитовДерева,рЭлементыВыбораСКД)
	// Выводим только видимые колонки
	Для каждого элфЭлемент Из элфРодитель.ПодчиненныеЭлементы Цикл
		Если не элфЭлемент.Видимость Тогда Продолжить КонецЕсли;
		Если ТипЗнч(элфЭлемент)=Тип("ПолеФормы") Тогда
			рПутьКДанным=СтрЗаменить(элфЭлемент.ПутьКДанным,рПрефиксПути,"");
			Если СтрНачинаетсяС(рПутьКДанным,рИмяРеквизитаДерева+".") Тогда // основная колонка или её разыменование
				мИмени=СтрРазделить(рПутьКДанным,".",Ложь);
				рИмя=мИмени.Получить(1);
				Если рИмя="_ParentKey" или рИмя="_BranchKey" Тогда Продолжить КонецЕсли;
				// вносим
				колДерева=рКолонкиДерева.Найти(рИмя);
				рекДерева=соотРеквизитовДерева.Получить(рИмя);
				Если колДерева<>Неопределено и рекДерева<>Неопределено Тогда
					рЗаголовок=элфЭлемент.Заголовок; // он приоритетнее, но если пуст, берём из реквизита
					Если ПустаяСтрока(рЗаголовок) Тогда
						Если мИмени[мИмени.Количество()-1]=рИмя Тогда
							рЗаголовок=рекДерева.Заголовок;
						Иначе
							рЗаголовок=мИмени[мИмени.Количество()-1];
						КонецЕсли;
					КонецЕсли;						
					Если ПустаяСтрока(рЗаголовок) Тогда рЗаголовок=рИмя КонецЕсли;
					//
					Если рКолонкиТаблицы.Найти(рИмя)=Неопределено Тогда
						рТипЗначения=колДерева.ТипЗначения; // так более строго и правильно, особенно для конкретизируемых вроде субконто
						рКолонкиТаблицы.Добавить(рИмя,рТипЗначения,рЗаголовок);
					КонецЕсли;
					//
					рВыбПоле=рЭлементыВыбораСКД.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
					рВыбПоле.Заголовок=рЗаголовок; // а это может быть и поле, и разыменование поля
					рВыбПоле.Поле=Новый ПолеКомпоновкиДанных(СтрЗаменить(рПутьКДанным,рИмяРеквизитаДерева+".",""));
					рВыбПоле.Использование=Истина;
					//
				КонецЕсли;				
			Иначе
				// к счастью, коллекция формы не поддерживает поле, чей путь к данным лежит к чему-то вне этой коллекции
				// а варианты Строка[0] отработаем в другой версии
			КонецЕсли;
			// также, в другой версии:
			//элфЭлемент.ПутьКДаннымКартинкиСтроки,
			//элфЭлемент.ПутьКДаннымПодвала
		ИначеЕсли ТипЗнч(элфЭлемент)=Тип("ГруппаФормы") Тогда
			рВыбГруппа=рЭлементыВыбораСКД.Добавить(Тип("ГруппаВыбранныхПолейКомпоновкиДанных"));
			рВыбГруппа.Заголовок=элфЭлемент.Заголовок;
			Если элфЭлемент.Группировка=ГруппировкаКолонок.Вертикальная Тогда
				рВыбГруппа.Расположение=РасположениеПоляКомпоновкиДанных.Вертикально;
			ИначеЕсли элфЭлемент.Группировка=ГруппировкаКолонок.Горизонтальная Тогда
				рВыбГруппа.Расположение=РасположениеПоляКомпоновкиДанных.Горизонтально;
			ИначеЕсли элфЭлемент.Группировка=ГруппировкаКолонок.ВЯчейке Тогда
				рВыбГруппа.Расположение=РасположениеПоляКомпоновкиДанных.Вместе;
			КонецЕсли;			
			рВыбГруппа.Использование=Истина;
			РекурсивноЗаполнитьКолонкиПоЭлементам(элфЭлемент,рПрефиксПути,рИмяРеквизитаДерева,рКолонкиДерева,рКолонкиТаблицы,соотРеквизитовДерева,рВыбГруппа.Элементы);
		КонецЕсли;
	КонецЦикла;
КонецПроцедуры

// Вспомогательная для ВывестиДеревоВТабличныйДокумент
&НаСервере
Процедура РекурсивноЗаполнитьТаблицуПоДереву(рВетка,тДанных,рКлючРодителя=0)
	Для каждого рПодветка Из рВетка.Строки Цикл
		стро=тДанных.Добавить();
		ЗаполнитьЗначенияСвойств(стро,рПодветка);
		стро._ParentKey=рКлючРодителя;
		стро._BranchKey=тДанных.Количество();
		РекурсивноЗаполнитьТаблицуПоДереву(рПодветка,тДанных,стро._BranchKey);
	КонецЦикла;
КонецПроцедуры

// Выводит содержимое дерева значений, размещённого на форме (т.е. коллекцию ДанныеФормыДерево) в табличный документ; возвращает табличный документ.
// При ошибке возвращает пустой таб.документ.
// Содержит внутри себя упакованную рекурсию для заполнения служебной промежуточной таблицы значений.
//
// Параметры:
//    ИмяЭлементаФормы - обязательный, строка; имя элемента формы, являющегося выводимым деревом значений;
//    ИмяВладельца - необязательный, строка; имя родительского реквизита формы, дочерним к которому может являться дерево значений
//        применяется для случаев, когда дерево является реквизитом не формы, а объекта, связанного с формой (и не обязательно основного);
//    рВетка, тДанных, рКлюРодителя - служебные параметры для рекурсии, указывать их при вызове функции НЕ следует.
//
&НаСервере
Функция ВывестиДеревоВТабличныйДокумент(ИмяЭлементаФормы, ИмяВладельца="")
Попытка
	// собственно основной механизм		
	т=Новый ТабличныйДокумент;
	
	элфВсёДерево=Элементы.Найти(ИмяЭлементаФормы);
	Если элфВсёДерево=Неопределено Тогда 
		Сообщить("Элемент формы с именем """+ИмяЭлементаФормы+""" не найден!");
		Возврат т;
	КонецЕсли;
	
	#Область ПолучениеРабочихОбъектовДерева
	Если СтрНачинаетсяС(элфВсёДерево.ПутьКДанным,ИмяВладельца+".") Тогда
		рПрефиксПути=ИмяВладельца+".";
		рИмяРеквизитаДерева=СтрЗаменить(элфВсёДерево.ПутьКДанным,рПрефиксПути,"");
		знчВсёДерево=Объект[рИмяРеквизитаДерева];			
	Иначе
		рПрефиксПути="";
		рИмяРеквизитаДерева="";
		мРеквизитовФормы=ЭтотОбъект.ПолучитьРеквизиты();
		Для каждого рекФормы Из мРеквизитовФормы Цикл
			Если рекФормы.Имя=элфВсёДерево.ПутьКДанным Тогда рИмяРеквизитаДерева=рекФормы.Имя; Прервать КонецЕсли;
		КонецЦикла;
		Если ПустаяСтрока(рИмяРеквизитаДерева) Тогда
			Сообщить("Реквизит, соответствующий элементу формы с именем """+ИмяЭлементаФормы+""", не найден!");
			Возврат т;
		КонецЕсли;
		знчВсёДерево=ЭтотОбъект[рИмяРеквизитаДерева];
	КонецЕсли;
	
	Если ТипЗнч(знчВсёДерево)<>Тип("ДанныеФормыДерево") Тогда
		Сообщить("Реквизит, соответствующий элементу формы с именем """+ИмяЭлементаФормы+""", имеет неверный тип (не ""ДанныеФормыДерево"")!");
		Возврат т;
	КонецЕсли;
	
	рДерево=ДанныеФормыВЗначение(знчВсёДерево,Тип("ДеревоЗначений"));
	
	мРеквизитовДерева=ЭтотОбъект.ПолучитьРеквизиты(элфВсёДерево.ПутьКДанным);
	соотРеквизитовДерева=Новый Соответствие;
	Для каждого рекДерева Из мРеквизитовДерева Цикл
		соотРеквизитовДерева.Вставить(рекДерева.Имя,Новый Структура("Заголовок,Путь,ТипЗначения",рекДерева.Заголовок,рекДерева.Путь,рекДерева.ТипЗначения));
	КонецЦикла;		
	#КонецОбласти
	
	#Область ПервичнаяПодготовка
	тДанных=Новый ТаблицаЗначений;
	тДанных.Колонки.Добавить("_ParentKey",Новый ОписаниеТипов("Число",Новый КвалификаторыЧисла(10,0,ДопустимыйЗнак.Любой)));
	тДанных.Колонки.Добавить("_BranchKey",Новый ОписаниеТипов("Число",Новый КвалификаторыЧисла(10,0,ДопустимыйЗнак.Любой)));
	
	рСКД=Новый СхемаКомпоновкиДанных;
	//
	рИсточникДанных=рСКД.ИсточникиДанных.Добавить();
	рИсточникДанных.Имя="ОсновнойИсточник";
	рИсточникДанных.ТипИсточникаДанных="Local"; // вариант External для кубов и других БД не делаем
	//
	рНабор=рСКД.НаборыДанных.Добавить(Тип("НаборДанныхОбъектСхемыКомпоновкиДанных"));
	рНабор.Имя="ОсновнойНабор";
	рНабор.ИмяОбъекта="ТаблицаИсточник";
	рНабор.ИсточникДанных=рИсточникДанных.Имя;
	//
	рНастройка=рСКД.НастройкиПоУмолчанию;
	#КонецОбласти
	
	Для каждого колДерева из рДерево.Колонки Цикл
		рекДерева=соотРеквизитовДерева.Получить(колДерева.Имя);
		рЗаголовок=рекДерева.Заголовок;
		//
		Если тДанных.Колонки.Найти(колДерева.Имя)=Неопределено Тогда
			рТипЗначения=колДерева.ТипЗначения; // так более строго и правильно, особенно для конкретизируемых вроде субконто
			тДанных.Колонки.Добавить(колДерева.Имя,рТипЗначения,рЗаголовок);
		КонецЕсли;
	КонецЦикла;
	
	// Заполнение колонок таблицы и настроек СКД по элементам формы и дереву
	РекурсивноЗаполнитьКолонкиПоЭлементам(элфВсёДерево,рПрефиксПути,рИмяРеквизитаДерева,рДерево.Колонки,тДанных.Колонки,соотРеквизитовДерева,рНастройка.Выбор.Элементы);
	
	// Заполнение строк таблицы по дереву
	РекурсивноЗаполнитьТаблицуПоДереву(рДерево,тДанных);
	
	// Заполнение полей набора СКД
	Для каждого колТаблицы Из тДанных.Колонки Цикл
		рПолеНаб=рНабор.Поля.Добавить(Тип("ПолеНабораДанныхСхемыКомпоновкиДанных"));
		рПолеНаб.Заголовок=колТаблицы.Заголовок;
		рПолеНаб.Поле=колТаблицы.Имя;
		рПолеНаб.ПутьКДанным=колТаблицы.Имя;
		// фильтруем "пустые" типы
		рОписТипов=колТаблицы.ТипЗначения;
		мТипов=Новый Массив;
		Для каждого рТип Из рОписТипов.Типы() Цикл
			Если рТип=Тип("Неопределено") или рТип=Тип("NULL") или рТип=Неопределено или рТип=Null Тогда Продолжить КонецЕсли;
			мТипов.Добавить(рТип);
		КонецЦикла;		
		рПолеНаб.ТипЗначения=Новый ОписаниеТипов(мТипов,рОписТипов.КвалификаторыЧисла,рОписТипов.КвалификаторыСтроки,рОписТипов.КвалификаторыДаты);
	КонецЦикла;
	
	// Организация иерархического показа
	рСвязь=рСКД.СвязиНаборовДанных.Добавить();
	рСвязь.НаборДанныхИсточник=рНабор.Имя;
	рСвязь.НаборДанныхПриемник=рНабор.Имя;
	рСвязь.ВыражениеИсточник="_BranchKey";
	рСвязь.ВыражениеПриемник="_ParentKey";
	рСвязь.НачальноеВыражение="0"; // это должно быть вычисляемое значение, результат вычисления - число
	рСвязь.УсловиеСвязи="";
	
	// Автовыбранные поля, структура простейшая
	рГруппировкаКД=рСКД.НастройкиПоУмолчанию.Структура.Добавить(Тип("ГруппировкаКомпоновкиДанных"));
	рГруппировкаКД.Использование=Истина;	
	рВыбПолеГр=рГруппировкаКД.Выбор.Элементы.Добавить(Тип("АвтоВыбранноеПолеКомпоновкиДанных"));
	рВыбПолеГр.Использование=Истина;
	
	#Область НастройкаУсловногоОформления
	скдУО=рСКД.НастройкиПоУмолчанию.УсловноеОформление;
	Для каждого элУО ИЗ ЭтотОбъект.УсловноеОформление.Элементы Цикл
		мПутейПолей=Новый Массив;
		Для каждого элПоле Из элУО.Поля.Элементы Цикл
			рПутьИмя=Строка(элПоле.Поле);
			Если не элПоле.Использование или не СтрНачинаетсяС(рПутьИмя,рИмяРеквизитаДерева) Тогда Продолжить КонецЕсли;
			рПутьИмя=СтрЗаменить(рПутьИмя,рИмяРеквизитаДерева,"");
			Если ПустаяСтрока(рПутьИмя) Тогда // вносим все поля
				Для каждого рВыбПоле Из рСКД.НастройкиПоУмолчанию.Выбор.Элементы Цикл
					мПутейПолей.Добавить(Строка(рВыбПоле.Поле));
				КонецЦикла;
			Иначе
				Если мПутейПолей.Найти(рПутьИмя)=Неопределено Тогда
					мПутейПолей.Добавить(рПутьИмя);
				КонецЕсли;
			КонецЕсли;			
		КонецЦикла;
		Если мПутейПолей.Количество()=0 Тогда Продолжить КонецЕсли;
		//
		элСкдУО=скдУО.Элементы.Добавить();
		//
		// поля (если некое поле касается всего дерева, то вносим для всех полей)
		Для каждого рПутьИмя Из мПутейПолей Цикл
			элСкдПоле=элСкдУО.Поля.Элементы.Добавить();
			элСкдПоле.Поле=Новый ПолеКомпоновкиДанных(рПутьИмя);
			элСкдПоле.Использование=Истина;
		КонецЦикла;
		//
		// само УО
		Для каждого рОформление Из элУО.Оформление.Элементы Цикл
			Если не рОформление.Использование Тогда Продолжить КонецЕсли;
			элСкдУО.Оформление.УстановитьЗначениеПараметра(рОформление.Параметр,рОформление.Значение);
		КонецЦикла;
		//		
		// отборы
		Для каждого элОтбор Из элУО.Отбор.Элементы Цикл
			Если не элОтбор.Использование Тогда Продолжить КонецЕсли;
			рПутьКДанным=СтрЗаменить(Строка(элОтбор.ЛевоеЗначение),рПрефиксПути+рИмяРеквизитаДерева+".","");
			//
			Если ТипЗнч(элОтбор.ПравоеЗначение)=Тип("ПолеКомпоновкиДанных") Тогда
				рПравоеЗначениеСкдОтбораУО=Неопределено;
				Попытка рПравоеЗначениеСкдОтбораУО=Вычислить(элОтбор.ПравоеЗначение) Исключение КонецПопытки; // на момент вывода дерева
				Если рПравоеЗначениеСкдОтбораУО=Неопределено Тогда Продолжить КонецЕсли;
			Иначе
				рПравоеЗначениеСкдОтбораУО=элОтбор.ПравоеЗначение;
			КонецЕсли;
			//
			элСкдОтбор=элСкдУО.Отбор.Элементы.Добавить(ТипЗнч(элОтбор));
			элСкдОтбор.ЛевоеЗначение=Новый ПолеКомпоновкиДанных(рПутьКДанным);
			элСкдОтбор.ВидСравнения=элОтбор.ВидСравнения;
			элСкдОтбор.ПравоеЗначение=рПравоеЗначениеСкдОтбораУО;
			элСкдОтбор.Использование=Истина;
		КонецЦикла;
		//
		ЗаполнитьЗначенияСвойств(элСкдУО,элУО); // общие настройки (в первую очередь области использования)
	КонецЦикла;
	
	рСКД.НастройкиПоУмолчанию.ПараметрыВывода.УстановитьЗначениеПараметра("РасположениеРеквизитов",РасположениеРеквизитовКомпоновкиДанных.Отдельно);
	#КонецОбласти
	
	#Область ВыводВТабДокумент
	компМакета=Новый КомпоновщикМакетаКомпоновкиДанных;
	рМакетКомпоновки=компМакета.Выполнить(рСКД,рСКД.НастройкиПоУмолчанию,,,Тип("ГенераторМакетаКомпоновкиДанных"));
	//
	рПроцессорКД=Новый ПроцессорКомпоновкиДанных;
	рПроцессорКД.Инициализировать(рМакетКомпоновки,Новый Структура(рНабор.ИмяОбъекта,тДанных)); // разумеется без внешних функций
	//
	рПроцессорВывода=Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
	рПроцессорВывода.УстановитьДокумент(т);
	т=рПроцессорВывода.Вывести(рПроцессорКД,Истина);
	#КонецОбласти	
	
	Возврат т;
	
Исключение
	Сообщить("ВывестиДеревоВТабличныйДокумент, общая ошибка: "+ОписаниеОшибки());
	Возврат Новый ТабличныйДокумент;
КонецПопытки;
КонецФункции

 

 

Соответственно, вызов:

табДок=ВывестиДеревоВТабличныйДокумент("МоеДерево","Объект"); // если оно Объект.МоеДерево
табДок=ВывестиДеревоВТабличныйДокумент("МоеДерево"); // если оно реквизит формы

Кому пригодится - хорошо. Тестировалось на 8.3.16.1224, но должно работать и на более ранних. А сама проблема, породившая задачу, наблюдалась на 8.3.17-м релизе. Может, баг, и потом поправят...
Кто наткнётся на косяки - пишите, постараюсь оперативно исправить.

Специальные предложения

Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. dkoder 4 09.07.20 10:31 Сейчас в теме
Отличная работа! Только на больших деревьях лучше делать псевдо рекурсию внутри процедуры, особенно, когда рекурсивно вызываются запросы. Производительность возрастает до порядка

Псевдо рекурсия делается, примерно, так
Процедура ВнутренняяРекурсия(Дерево)
                МассивСтрок = Новый Массив;
                Для Каждого СтрДерева Из Дерево.Строки Цикл
                               МассивСтрок.Добавить(СтрДерева);
                КонецЦикла;

                Пока МассивСтрок.Количество() > 0 Цикл
                               // тут можно вызвать общий запрос для всего уровня дерева... 

                               МассивСтрокНовый = Новый Массив;
                               Для Каждого СтрДерева Из МассивСтрок Цикл
                                               // обработка данных элемента дерева ....

                                               // Тут делаем псевдо рекурсию
                                               Для Каждого СтрДереваНовый Из СтрДерева.Строки Цикл
                                                               МассивСтрокНовый.Добавить(СтрДереваНовый);
                                               КонецЦикла;
                               КонецЦикла;

                               МассивСтрок = Новый Массив;
                               Для Каждого СтрДерева Из МассивСтрокНовый Цикл
                                               МассивСтрок.Добавить(СтрДерева);
                               КонецЦикла;
                КонецЦикла;
КонецПроцедуры 
Показать
3. Yashazz 4107 09.07.20 12:58 Сейчас в теме
(1) да знаю) можно ещё всяко циклом поизвращаться.
2. Yashazz 4107 09.07.20 12:57 Сейчас в теме
Ахтунг! Замечена недоработка: если в дереве как в элементе формы есть группы колонок, то лажа, т.к. внутрь этих групп не заходит и колонки не добавляет. Допилю - обновлю.
4. Yashazz 4107 14.07.20 09:09 Сейчас в теме
Сделал всё-таки без рекурсии. Заодно допилил вывод групп колонок, вывод реквизитов, ещё кое-что по мелочи.
5. mihanov 9 23.10.20 10:44 Сейчас в теме
Обнаружилась проблемка:
Не учтен случай когда в отборах "условного оформления" формы есть группы условий (И/ИЛИ...).
6. Yashazz 4107 23.10.20 11:39 Сейчас в теме
(5) А у меня это вроде учтено в более поздних доработках. Возможно, себе допилил, а сюда не выложил... Посмотрю.
7. mity1982 24.11.20 02:34 Сейчас в теме
Обход дерева без рекурсии:
Надо понимать что, если алгоритм предполагает формирование результата "от листьев к корню" то нужна рекурсия.
Если это последовательный вывод то можно так. Можно использовать для всяких интерактивно-асинхронных задач.


Процедура Обход()
.....
Текущий = Дерево;
Пока ДеревоСледующий(Текущий) Цикл
       .......  
КонецЦикла;
......
КонецПроцедуры;

Функция ДеревоСледующий(Текущий)
	
	Перем УзелНиже;
	
 	УзелНиже = ДеревоНиже(Текущий);	
	Если НЕ УзелНиже = Неопределено Тогда
		Текущий = УзелНиже;
		Возврат Истина;
	ИначеЕсли УзелНиже = Неопределено И ДеревоВыше(Текущий) = Неопределено Тогда
		Возврат Ложь;
	КонецЕсли;	 

	Если НЕ ДеревоПравее(Текущий) = Неопределено Тогда
		Текущий = ДеревоПравее(Текущий);
		Возврат Истина;		
	КонецЕсли;
			
	//нет ни ниже ни правее
	Пока Истина Цикл
				
		Если ДеревоВыше(Текущий) = Неопределено Тогда Возврат Ложь; КонецЕсли;
		
		Текущий = ДеревоВыше(Текущий);
						
		Если НЕ ДеревоПравее(Текущий) = Неопределено И НЕ ДеревоВыше(Текущий) = Неопределено Тогда Прервать;КонецЕсли;
		
	КонецЦикла;
	
	Текущий = ДеревоПравее(Текущий);
	
	Возврат Истина;
	
КонецФункции

Функция ДеревоВыше(Знач Текущий)
	Если ТипЗнч(Текущий) = Тип("ДеревоЗначений") Тогда
		Возврат Неопределено;
	КонецЕсли;
	Если Текущий.Родитель = Неопределено Тогда
		Возврат Текущий.Владелец();
	КонецЕсли; 
	Возврат Текущий.Родитель; 
КонецФункции

Функция ДеревоНиже(Знач Текущий)
	Если Текущий.Строки.Количество() > 0 Тогда
		Возврат Текущий.Строки[0];
	КонецЕсли; 	
КонецФункции

Функция ДеревоПравее(Знач Текущий)
	Если ТипЗнч(Текущий) = Тип("ДеревоЗначений") Тогда
		Возврат Неопределено;
	КонецЕсли;
	Выше = Текущий.Родитель;
	Если Выше = Неопределено Тогда Выше = Текущий.Владелец(); КонецЕсли; 
	инд = Выше.Строки.Индекс(Текущий);
	Если инд < Выше.Строки.Количество() - 1 Тогда
		Возврат Выше.Строки[инд+1];
	КонецЕсли; 
КонецФункции
Показать
Оставьте свое сообщение

См. также

Аналог PIVOT в запросе 1С (как выполнить транспонирование таблицы в запросе 1С) Промо

Практика программирования v8 Бесплатно (free)

В статье показывается простой метод реализации аналога оператора PIVOT в запросе 1С без использования соединений.

12.12.2020    4617    Eugen-S    23    

Обзор полезных методов БСП 3.1.4. Часть 2

БСП (Библиотека стандартных подсистем) v8 Бесплатно (free)

Библиотека стандартных подсистем (далее - БСП) является частью любой типовой конфигурации, поэтому умение применять готовые процедуры и функции повышает качество разработки и избавляет от написания лишнего кода. К сожалению, не у всех есть время и упорство овладеть всей документацией, поэтому я собрал воедино наиболее популярный функционал.

27.04.2021    16437    rayastar    7    

Полезные примеры СКД, ч.1

Практика программирования v8::СКД Бесплатно (free)

Подборка видео по решению различных задач в отчетах на СКД.

30.03.2021    13669    Neti    21    

Обзор полезных методов БСП 3.1.4

БСП (Библиотека стандартных подсистем) Практика программирования v8 1cv8.cf Бесплатно (free)

Библиотека стандартных подсистем (далее - БСП) является частью любой типовой конфигурации, поэтому умение применять готовые процедуры и функции повышает качество разработки и избавляет от написания лишнего кода. К сожалению, не у всех есть время и упорство овладеть всей документацией, поэтому я собрал воедино наиболее популярный функционал.

25.03.2021    41986    rayastar    51    

Использование классов .Net в 1С для новичков Промо

Разработка внешних компонент Универсальные функции Практика программирования v7.7 v8 Бесплатно (free)

Руководство для новичков. Написав статью http://infostart.ru/public/238584/, я понял, что многие не понимают того, что написано. Поэтому в этой статье постараюсь более подробно остановиться на азах и без кода на вражеском языке (C#)

27.01.2016    85917    Serginio    116    

Звуковое управление в 1С 8.3

Практика программирования v8 1cv8.cf Бесплатно (free)

В данной статье описано создание библиотеки для звукового управления (выполнение команд голосом) для платформы 1С 8.3. Задача была поставлена так, чтобы модуль функционировал непосредственно на клиенте 1С, осуществляя управление формами, и взаимодействовал с интерфейсом.

16.03.2021    7274    velemir    33    

Serverless (Faas) в 1С. Создание и вызов Yandex Cloud Functions

Универсальные функции Практика программирования v8 Бесплатно (free)

"Я не могу просто взять и скопировать код с гитхаба", "у нас 1С микросервисами окружена", "возможностей мало" - частые фразы 1С разработчиков. которым не хватает возможностей платформы в современном мире. Faas, конечно, история не новая, но нас сдерживало 152ФЗ и задержки по пингам. Для того, чтобы действительно использовать в 1С код, к примеру, на Python, надо было приложить усилия. Теперь всё намного проще - берём и используем.

28.12.2020    9008    comol    31    

Программная работа с настройками СКД

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

Нюансы программной работы с настройками системы компоновки данных в отчетах и динамических списках. Обзор всех видов настроек компоновки. Что в каких случаях правильно применять. В качестве примера рассмотрена работа с отборами и группировками.

27.01.2020    66552    ids79    26    

Как я начал администрировать сервер 1С: Предприятие 8.3 с телефона Промо

Инструменты администратора БД Мобильная разработка v8 Бесплатно (free)

Развитие инструментов управления кластером серверов 1С:Предприятие 8.3.

14.04.2017    67726    user700211_a.straltsou    30    

[СКД] Программное создание схемы компоновки данных

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

Сделаем отчет на СКД полностью программно, без использования макета "схема компоновки данных".

15.01.2020    44091    John_d    22    

Последовательности событий при проведении документа 1С. Шпаргалка + про формы + про расширения

Практика программирования v8 Россия Бесплатно (free)

Собрал информацию о событиях/подписках/расширениях в одном месте.

30.12.2019    35807    kuzyara    38    

Шпаргалка (БСП). Добавление в новый документ механизма печати дополнительных печатных форм

Печатные формы БСП (Библиотека стандартных подсистем) v8 1cv8.cf Бесплатно (free)

Постоянно приходится вспоминать, как добавить механизм печати (БСП) в новый документ. Поэтому решил написать шпаргалку.

10.10.2019    30786    John_d    21    

Использование программных перечислений, ч.1: строковые константы Промо

Практика программирования v8 1cv8.cf Бесплатно (free)

Часто ли у вас возникает необходимость в коде выполнять сравнение на строку?

10.12.2016    41183    unichkin    74    

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

Универсальные функции v8 1cv8.cf Россия Бесплатно (free)

Все мы пишем программный код и часто используем процедуры, облегчающие его написание. Ниже приведена выборка таких полезных процедур и функций.

07.10.2019    39956    HostHost    41    

Таблица значений. Нюансы

Практика программирования v8 Бесплатно (free)

Обзор некоторых аспектов использования общеизвестного инструмента 1С.

01.10.2019    53541    Yashazz    56    

СКД. Отчеты с картинками

Работа с интерфейсом Практика программирования v8::СКД 1cv8.cf Бесплатно (free)

Решение популярных кейсов с картинками в отчетах на СКД.

25.09.2019    33342    YPermitin    58    

Вспомогательные инструкции в коде 1С Промо

Практика программирования v8 1cv8.cf Бесплатно (free)

Помогаем редактору кода 1С помогать нам писать и анализировать код.

15.10.2018    36243    tormozit    106    

[Шпаргалка] Программное создание элементов формы

Работа с интерфейсом Практика программирования v8 1cv8.cf Бесплатно (free)

Программное создание практически всех популярных элементов формы.

06.09.2019    103935    rpgshnik    77    

Агрегатные функции СКД, о которых мало кто знает

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

Пользуетесь ли Вы всеми возможными агрегатными функциями, которые предоставляет система компоновки данных? Если Вы используете только: СУММА, КОЛИЧЕСТВО, МИНИМУМ, МАКСИМУМ, СРЕДНЕЕ, то эта статья для Вас.

05.09.2019    78460    ids79    56    

Отслеживание выполнения фонового задания

Универсальные функции Инструментарий разработчика Практика программирования v8 1cv8.cf Бесплатно (free)

Запуск фонового задания из модуля внешней обработки. Отслеживание выполнения задания в виде прогресса, расположенного на форме.

17.08.2019    45453    ids79    22    

Оформление и рефакторинг сложных логических выражений Промо

Практика программирования v8 Россия Бесплатно (free)

В сложных логических выражениях нередко самому автору спустя какое-то время тяжело разобраться, не говоря уже о других программистах. Предлагаемая методика позволяет повысить наглядность таких выражений путем оформления в виде И-ИЛИ дерева и одновременно выполнять их рефакторинг.

20.09.2012    82937    tormozit    131    

Функции СКД: ВычислитьВыражение, ВычислитьВыражениеСГруппировкойМассив

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

Подробное описание и использование внутренних функций системы компоновки данных: Вычислить, ВычислитьВыражение, ВычислитьВыражениеСГруппировкойМассив, ВычислитьВыражениеСГруппировкойТаблицаЗначений.

08.08.2019    154080    ids79    75    

СКД - наборы данных и связи между ними, создание собственной иерархии, вложенные отчеты

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

Набор данных объект. Использование в схеме компоновки нескольких наборов данных. Различные варианты связи наборов: объединение, соединение. Использование иерархии в отчетах на СКД. Создание собственной иерархии, иерархия детальных записей. Использование вложенных схем в отчетах на СКД.

26.07.2019    106697    ids79    17    

Обработчики событий при записи объектов. Зачем и что за чем?

Математика и алгоритмы v8 Бесплатно (free)

Программисту, имеющему немного опыта на платформе 1С 8.3, бывает сложно разобраться: ПередЗаписью, ПриЗаписи, ПослеЗаписи, на сервере, на клиенте, в модуле формы, в модуле объекта.... Эта шпаргалка была создана в процессе обучения и реального опыта с целью разложить всё по полочкам, чтобы было четкое понимание в каком случае какой обработчик нужно использовать и в какой последовательности они запускаются при записи и проведении документов. Данная статья будет полезна в большей степени начинающим разработчикам. Но и опытным позволит освежить информацию, упорядочить её.

25.07.2019    114129    AlbinaAAA    49    

Запись значения в поле ввода/формы со срабатыванием события ПриИзменении Промо

Практика программирования v8 1cv8.cf Россия Бесплатно (free)

Иногда возникает необходимость после записи значения в какое либо поле ввода/формы вызвать для него обработчик события ПриИзменении, а о вызове самого события приходится только мечтать. В этой статье приводится программный способ вызова этого события.

11.07.2007    54565    tormozit    51    

СКД - использование расширений языка запросов, секция ХАРАКТЕРИСТИКИ

Инструментарий разработчика Практика программирования v8 v8::СКД Бесплатно (free)

Автоматическое и не автоматическое заполнение полей компоновки данных. Использование расширений языка запросов для СКД «{…}», секция ВЫБРАТЬ, секция ГДЕ, параметры виртуальных таблиц. Автоматизированное использование дополнительных данных в запросе: секция ХАРАКТЕРИСТИКИ.

17.07.2019    48790    ids79    27    

"Меньше копипаста!", или как Вася универсальную процедуру писал

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

Программист Вася разбирает подход создания универсальных методов на примере программного вывода СКД.

04.07.2019    22616    SeiOkami    53    

Создание отчетов с помощью СКД - основные понятия и элементы

Математика и алгоритмы v8 v8::СКД Бесплатно (free)

Основные принципы работы СКД. Понятия схемы компоновки и макета компоновки. Описание основных элементов схемы компоновки: наборы данных, поля, вычисляемые поля, ресурсы, параметры.

25.06.2019    76842    ids79    28    

Как сделать из &НаКлиентеНаСервереБезКонтекста почти &НаКлиентеНаСервере Промо

Практика программирования v8 1cv8.cf Россия Бесплатно (free)

Как сделать метод формы, доступный на клиенте и на сервере одновременно, и сохранить при этом удобство разработки

10.09.2017    51351    tormozit    74    

Подсистема "Варианты отчетов". Используете ли Вы ее правильно?

Работа с интерфейсом БСП (Библиотека стандартных подсистем) v8 1cv8.cf Бесплатно (free)

Небольшая история про использование подсистемы "Варианты отчетов" из БСП. Используете ли Вы ее правильно?

04.06.2019    56621    YPermitin    55    

Регистры накопления. Структура хранения в базе данных

Инструментарий разработчика Практика программирования v8 1cv8.cf Бесплатно (free)

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

16.05.2019    64445    YPermitin    31    

Выгрузка документа по условию

Инструментарий разработчика Практика программирования v8 Бесплатно (free)

Что делать, если документы нужно выгружать не все подряд, а по какому-то фильтру: статусу, дате, набору условий... А что если он соответствовал этим условиям, а потом перестал? А если потом опять начал? Такие ситуации заставили попотеть не одного программиста.

25.04.2019    18069    m-rv    3    

Как сделать запрос на изменение данных Промо

Практика программирования v8 v8::Запросы 1cv8.cf Бесплатно (free)

В статье приведены особенности внутренней архитектуры и примеры работы с расширением языка запросов 1С.

01.06.2018    37133    m-rv    23    

Как прикрутить ГУИД к регистру сведений

Перенос данных из 1C8 в 1C8 Инструментарий разработчика Практика программирования v8 Бесплатно (free)

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

16.04.2019    23401    m-rv    18    

О расширениях замолвите слово...

Инструментарий разработчика Практика программирования v8 Бесплатно (free)

О чём стоит задуматься при принятии решения о создании расширения конфигурации…

07.04.2019    42854    ellavs    131    

Git-репозитории для 1С-кода (опыт использования при небольших проектах)

Практика программирования v8 Бесплатно (free)

Инструкции по взаимодействию с Git-репозиторием, которые писались для тех наших программистов, которые вообще никогда не работали с Git (руководства в духе "Как получить код из git-репозитория?", "Как отправить код в git-репозиторий")...

28.03.2019    32144    ellavs    90    

Добавление отчетов в типовые конфигурации 1С

Универсальные функции БСП (Библиотека стандартных подсистем) v8::УФ v8::СКД 1cv8.cf Бесплатно (free)

Описание различных способов добавления общих и контекстных отчетов в конфигурации 1С, построенные на базе БСП. Основные моменты и нюансы.

07.03.2019    78999    ids79    49    

Возможности типовых шаблонов ограничения доступа на уровне записей (RLS)

БСП (Библиотека стандартных подсистем) Роли и права Практика программирования v8 v8::Права Бесплатно (free)

Краткий обзор применения типовых шаблонов ограничения доступа на уровне записей в конфигурациях, созданных на базе БСП: #ПоЗначениям, #ПоНаборамЗначений, #ПоЗначениямРасширенный, #ПоЗначениямИНаборамРасширенный

03.02.2019    66035    ids79    11    

Универсальные функции ЗУП 3.1 / ЗКГУ 3.1, которые помогут в разработке

Универсальные функции Зарплата Управление персоналом (HRM) Зарплата Кадровый учет v8 v8::СПР ЗКГУ3.0 ЗУП3.x БУ Бесплатно (free)

В статье размещен список стандартных процедур и функций с примерами, которые могут помочь при разработке (доработке) конфигураций Зарплата и управление персоналом ред. 3.1 и Зарплата и кадры государственного учреждения 3.1. Иногда бывает довольно сложно правильно получить данные или долго, поэтому лучшим вариантом будет использование стандартных процедур. Буду очень признателен, если Вы поделитесь своим опытом и предложите свои варианты стандартных процедур которые помогают в работе. Или предложите, как дополнить имеющиеся процедуры.

14.11.2018    148096    GeterX    135    

Автоматические и управляемые блокировки применительно к типовым конфигурациям 1С

Математика и алгоритмы Практика программирования v8 v8::blocking 1cv8.cf Бесплатно (free)

Основные принципы работы с режимами автоматических и управляемых блокировок в 1С Предприятие 8. Теория и применение в типовых конфигурациях: БП, УТ, ЕРП

10.11.2018    45113    ids79    46    

Git + 1С. Часть 1. Как подключиться к команде разработки и начать использовать Git

Инструментарий разработчика Методология v8 1cv8.cf Бесплатно (free)

Первая статья из цикла инструкций по работе с Git в 1С-разработке. Рассмотрим, как настроить рабочее место, как получить свою "копию" проекта для разработки и приступить к полезным действиям. Все примеры будут изложены в рамках трёх практических кейсов: 1. Моя команда дорабатывает типовую конфигурацию, использует приватный репозиторий на BitBucket, в котором версионируются внешние отчеты/обработки, расширения конфигураций и правила обмена; 2. Я участвую в стартап-команде, которая разрабатывает свою конфигурацию с использованием Git и GitLab; 3. Я принимаю участие в развитии OpenSource-продукта на GitHub как заинтересованный разработчик (контрибьютор).

18.10.2018    93751    stas_ganiev    86    

Приемы работы с СКД: делаем за 5 минут то, на что у других уйдет час

Инструментарий разработчика Практика программирования v8::СКД Бесплатно (free)

Сергей Наумов делится опытом нестандартного использования системы компоновки данных. Он рассказывает о построении сложных отчетов с помощью функций СКД, описывает преимущества использования компоновки в коде для значительного сокращения строк кода и времени на решение задач, а также рассказывает про отладку компоновки и возможности оптимизации ее работы.

03.09.2018    50491    SergeyN    28    

Тестер: частые вопросы

Практика программирования v8 Бесплатно (free)

Ошибкам бой - тесты норма жизни!

25.07.2018    31614    grumagargler    31    

[Шпаргалка] Свой заголовок отчету на СКД с параметрами, картинками (без программирования)

Работа с интерфейсом v8::СКД 1cv8.cf Бесплатно (free)

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

23.07.2018    73251    rpgshnik    64    

Повышаем эффективность разработки правил обмена

Практика программирования v8 КД Бесплатно (free)

Как повысить скорость и качество разработки правил обмена? Как вести групповую разработку правил обмена? Как облегчить сопровождение правил обмена после передачи в эксплуатацию? Об этом и многом другом вы можете узнать из этой статьи.

25.06.2018    30287    olegtymko    48    

Введение в механизм представлений в ЗУП ред. 3

Практика программирования v8 v8::СПР ЗУП3.x Бесплатно (free)

В нашей организации на первом же телефонном собеседовании на должность разработчика по ЗУП ред. 3 вас обязательно спросят о том, что такое "Представления".

04.06.2018    47648    xrrg    95