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

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

Разработка - Практика программирования

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

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

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

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


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

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

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

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

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

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

См. также

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

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

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

16.03.2021    2782    velemir    30    

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

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

Еще несколько примеров решения задач в СКД.

06.04.2021    3242    Neti    7    

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

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

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

30.03.2021    5139    Neti    18    

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

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

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

25.03.2021    12329    rayastar    45    

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

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

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

28.12.2020    5174    comol    31    

Базовые вещи БСП, которые облегчат жизнь программисту 1С

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

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

30.08.2020    12673    quazare    34    

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

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

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

27.01.2020    43685    ids79    26    

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

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

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

15.01.2020    32746    John_d    22    

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

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

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

10.12.2016    38890    unichkin    74    

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

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

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

30.12.2019    25239    kuzyara    38    

Сходство Джаро - Винклера. Нечеткое сравнение строк

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

В области информатики и статистики сходство Джаро - Винклера представляет собой меру схожести строк для измерения расстояния между двумя последовательностями символов. В публикации рассмотрены некоторые особенности алгоритма, и представлен вариант его реализации на языке 1С.

25.12.2019    7743    brooho    19    

30 задач. Странных и не очень

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

30 задач на знание языка программирования 1С и некоторого поведения платформы. Маленьких. Странных и не очень.

02.12.2019    19691    YPermitin    60    

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

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

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

15.10.2018    32672    tormozit    105    

Как передать IP адрес, который вызвал HTTP запрос в 1C (для веб-сервера Apache)

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

Столкнулся с задачей получения IP адреса, который вызывает http сервис 1С. Итак, решение:

22.11.2019    10259    Sibars    19    

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

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

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

07.10.2019    34337    HostHost    41    

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

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

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

01.10.2019    42868    Yashazz    50    

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

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

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

20.09.2012    79780    tormozit    131    

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

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

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

25.09.2019    26357    YPermitin    41    

СКД не только для отчетов

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

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

18.09.2019    20597    YPermitin    36    

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

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

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

06.09.2019    73249    rpgshnik    70    

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

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

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

11.07.2007    50704    tormozit    49    

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

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

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

05.09.2019    61500    ids79    55    

Регистры бухгалтерии. Общая информация

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

Общая информация о внутреннем устройстве регистров бухгалтерии.

05.09.2019    35009    YPermitin    25    

Три костыля. Сказ про фокусы в коде

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

Три интересных (или странных) костыля в коде, которые могут помочь в повседневных и не очень задачах.

03.09.2019    27607    YPermitin    81    

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

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

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

10.09.2017    47567    tormozit    74    

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

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

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

17.08.2019    38015    ids79    16    

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

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

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

08.08.2019    115441    ids79    69    

Фоновое выполнение кода в 1С - это просто

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

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

02.08.2019    47092    avalakh    26    

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

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

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

25.04.2019    16622    m-rv    2    

Разбираемся с параметрами редактирования СКД

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

Связь по типу, Параметры выбора, Связи параметров выбора

31.07.2019    31546    json    15    

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

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

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

26.07.2019    81833    ids79    14    

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

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

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

17.07.2019    41452    ids79    27    

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

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

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

16.04.2019    21240    m-rv    17    

Регистры сведений. За кулисами

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

Небольшие заметки по внутреннему устройству регистров сведений.

09.07.2019    29384    YPermitin    14    

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

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

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

04.07.2019    20655    SeiOkami    50    

Работа с настройками системы компоновки данных

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

Варианты отчетов, работа с настройками вариантов: структура группировок, поля отчета, отборы, сортировка, условное оформление, другие настройки, настройки отображения диаграмм.

02.07.2019    64031    ids79    17    

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

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

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

01.06.2018    33049    m-rv    22    

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

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

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

25.06.2019    63185    ids79    26    

Многопоточное ускорение однопользовательских нагрузок в 1С + Microsoft SQL Server 2017

Практика программирования Производительность и оптимизация (HighLoad) v8 v8::Запросы Бесплатно (free)

Взаимодействие с Microsoft SQL Server нередко вызывает трудности у 1С-ников, а потому интересны любые моменты, связанные с его использованием. О своем опыте работы с новым SQL Server 2017 участникам конференции Infostart-2018 рассказал директор ООО «Аналитика софт» Дмитрий Дудин.

11.06.2019    27792    dmurk    146    

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

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

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

16.05.2019    52079    YPermitin    30    

Метод формирования движений в типовых регистрах нетиповыми регистраторами Промо

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

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

05.12.2017    29033    itriot11    34    

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

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

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

07.04.2019    38858    ellavs    127    

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

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

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

28.03.2019    29047    ellavs    90    

Трюки с внешними источниками данных

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

Некоторые трюки для преодоления ограничений внешних источников данных.

14.03.2019    35718    YPermitin    53    

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

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

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

27.01.2016    79126    Serginio    113    

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

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

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

07.03.2019    65717    ids79    47    

Разработка и сценарное тестирование с Vanessa-ADD. Отчетность Allure. Автоматизация запуска сценариев

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

Формируем отчетность о результатах выполнения сценариев. Автоматизируем запуск.

26.02.2019    25011    Vladimir Litvinenko    28    

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

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

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

03.02.2019    48872    ids79    11    

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

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

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

10.11.2018    38712    ids79    40