5 марта 2022 г.

1С УФ вывод на форму ТЗ с генерацией колонок

 Часто надо вывести таблицу значений не зная заранее состав колонок, просто оставлю здесь.

Обязательное условие - наличии на форме пустой ТЗ. Можно ее создать программно.

	
&НаСервере
Процедура ВывестиСписокДокументовНаФорму(ТзВыборкаИзБД)
    //ТзВыборкаИзБД - например выгрузка из БД запросом 
    ИмяТЗ_НаФорме="ТЗ"; //реквизит формы, а не элемент
    //Сначала очищаем ТЗ
    //если есть реквизиты созданные интерактивно, то вылезет ошибка
	УдаляемыеРеквизиты = Новый Массив;
	
	РеквизитыДляУдаления = ПолучитьРеквизиты(ИмяТЗ_НаФорме);
	Для Каждого РеквизитУдаления Из РеквизитыДляУдаления Цикл
        УдаляемыеРеквизиты.Добавить(ИмяТЗ_НаФорме+"."+РеквизитУдаления.Имя);
        Элементы.Удалить(Элементы[ИмяТЗ_НаФорме+РеквизитУдаления.Имя]);
	КонецЦикла;
	
	ДобавляемыеРеквизиты = Новый Массив;
	Для каждого Колонка Из ТзВыборкаИзБД.Колонки Цикл
		ИмяКолонки=Колонка.Имя;
		//пытаемся определить тип значения, иначе при попытке запихать ТЗ в Запрос получим ошибку "тип не может быть выбран в запросе"
        //Также, побочный эффект - это нормальное представление флажка на форме
        ТипЗначенияКолонки=Новый ОписаниеТипов(Строка(ТипЗнч(ТзВыборкаИзБД[0][Колонка.Имя]))); 
        ДобавляемыеРеквизиты.Добавить(Новый РеквизитФормы(ИмяКолонки, ТипЗначенияКолонки,ИмяТЗ_НаФорме, Синонимайзер(ИмяКолонки)));
    КонецЦикла;
    ИзменитьРеквизиты(ДобавляемыеРеквизиты,УдаляемыеРеквизиты);
	
	// Добавление элементов форму
	Для каждого Колонка Из ТзВыборкаИзБД.Колонки Цикл
		ИмяКолонки=СтрЗаменить(Колонка.Имя,"Скрытый","");
        ЭлементРеквизита = Элементы.Добавить(ИмяТЗ_НаФорме + ИмяКолонки, Тип("ПолеФормы"), Элементы[ИмяТЗ_НаФорме]);
        ЭлементРеквизита.ПутьКДанным = ИмяТЗ_НаФорме + "." + ИмяКолонки;
        ЭлементРеквизита.Вид = ВидПоляФормы.ПолеВвода;
		ЭлементРеквизита.Видимость=Не ЭтоСкрытый;
		ЭлементРеквизита.ТолькоПросмотр=Истина;
		ЭлементРеквизита.Заголовок=Синонимайзер(ИмяКолонки);
		//как раз флажок
        Если Колонка.имя="Загрузить" Тогда
			ЭлементРеквизита.ТолькоПросмотр=Ложь;
			ЭлементРеквизита.ПоложениеЗаголовка=ПоложениеЗаголовкаЭлементаФормы.Нет;				
			ЭлементРеквизита.вид=ВидПоляФормы.ПолеФлажка;
			ЭлементРеквизита.ОграничениеТипа=новый ОписаниеТипов("Булево");
		КонецЕсли;
		Колонка.Имя=ИмяКолонки;
    КонецЦикла;
    
    ЗначениеВРеквизитФормы(ТзВыборкаИзБД, ИмяТЗ_НаФорме);
КонецПроцедуры
// Это интересный Синониминайзер за авторством ildarovich https://infostart.ru/1c/articles/306536/
&НаСервере
Функция Синонимайзер(Имя, Ответ = "", Стэйт = 7, б = "") Экспорт
    Для ё = 1 По СтрДлина(Имя) Цикл
        а = Сред(Имя, ё, 1);
        Стэйт = (НРег(а) <> а) * 4 + Цел(Стэйт / 2);
        Ответ = Ответ + ?(Стэйт = 2, НРег(б), ?(ё = 2, ВРег(б), б)) + ?(Стэйт = 4 ИЛИ Стэйт = 5, " ", "");
        б = а
    КонецЦикла;
    Возврат Ответ + б
КонецФункции

    


Варинат с реквизитом объекта (имя элемента (ИмяТЗ) совпадает с именем реквизита объекта). Создаем элемент и связываем с ТЧ объекта

	
&НаСервере
Процедура ВывестиТЗНаФорму(ИмяТЗ)  
	//этот блок нужен только для скрытия уже подгруженной ТЧ
	Если ЭтаФорма.Элементы.Найти(ИмяТЗ)<>Неопределено тогда 
		ЭтаФорма.Элементы[ИмяТЗ].Видимость=не ЭтаФорма.Элементы[ИмяТЗ].Видимость;
		Возврат
	КонецЕсли;
	нЭлемент = ЭтаФорма.Элементы.вставить(ИмяТЗ, Тип("ТаблицаФормы"),Элементы.ГруппаТовары,); 
	нЭлемент.ПутьКДанным = "Объект."+ИмяТЗ;
	ТаблицаЗнач=Объект[ИмяТЗ].Выгрузить();
	Для каждого Колонка Из ТаблицаЗнач.Колонки Цикл
		ИмяКолонки=Колонка.Имя;
		Если ИмяКолонки="ИсходныйНомерСтроки" Тогда
			Продолжить //иначе получаем ошибку
		КонецЕсли;
        ЭлементРеквизита = Элементы.Добавить(ИмяТЗ + ИмяКолонки, Тип("ПолеФормы"), Элементы[ИмяТЗ]);
        ЭлементРеквизита.ПутьКДанным ="Объект."+ИмяТЗ + "." + ИмяКолонки;
        ЭлементРеквизита.Вид = ВидПоляФормы.ПолеВвода;
		ЭлементРеквизита.Заголовок=Синонимайзер(ИмяКолонки);
    КонецЦикла;
    
КонецПроцедуры

1С Кастомная функция сообщений

 Частенько требуется выводить тот или иной уровень сообщений при работе программы или ее отладке. Обычно добавляется реквизит Отладка (булево) и каждый раз, при необходимости, проверяешь ее и делаешь вывод сообщения. 

Первый раз мне такая мысль пришла в расширении для Фреша, т.к. есть ошибки проявляющиеся только там (например в БП какое-то время не работали твои ПодпискиНаСобытия). А каждое изменение требует аудита, представь, отправлять повторно на аудит из-за отключения вывода?


// Процедура - Сообщения отладки
//
// Параметры:
//  Сообщение	 - Строка - Текст сообщения
//  Отладка		 - Булево - Истина - выводит все сообщения. Ложь - только ошибки 
//  Уровень		 - Число - Числовое определение уровня ошибки
//							0 - INFO	- информационные сообщения - значение по-умолчанию
//                          1 - DEBUG	- сообщения отладки
//                          2 - ERROR	- сообщения ошибки, выводятся всегда
//  Поле		 - ЭлементФормы, строка - используется, если есть связка сообщения и элемента формы
//  ОбъектДанных - Объект - используется для определения объекта, вызвавшего процедуру 
//
&НаСервере
Процедура СообщенияОтладки(Сообщение="",Отладка=Неопределено,Уровень=0,Поле="",ОбъектДанных=Неопределено) Экспорт	
	Если Отладка=Неопределено Тогда
		Если РеквизитФормыВЗначение("Объект").метаданные().Реквизиты.Найти("Отладка") Тогда 
			Отладка=ЭтотОбъект.Отладка;
		Иначе
			Отладка=Ложь;
		КонецЕсли;
	КонецЕсли;
			
	Если Отладка ИЛИ Уровень=2 Или Поле="Отладка" Тогда
		Если Уровень=1 Тогда
			УровеньТекст="INFO";
		ИначеЕсли Уровень=2 Тогда
			УровеньТекст="ERROR";
		Иначе
			УровеньТекст="DEBUG";
		КонецЕсли;
		нСообщение = Новый СообщениеПользователю;
		ЗнакТабуляции=Символы.Таб;
		нСообщение.Текст = СтрШаблон("%1 %2 %3 %4 %5 %6 %7",ТекущаяДата(),ЗнакТабуляции,УровеньТекст,ЗнакТабуляции,Сообщение,ЗнакТабуляции,Поле);
		
		Если Уровень=2 тогда
			нСообщение.Поле = Поле;
		КонецЕсли;
		Если ОбъектДанных <> Неопределено Тогда
			нСообщение.УстановитьДанные(ОбъектДанных);
		КонецЕсли;
		нСообщение.Сообщить(); 		
	КонецЕсли;
КонецПроцедуры




1 марта 2022 г.

1С Своя формула в подвале ТЧ

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

В таких случаях можно сделать финтушами, посчитать отдельно и вывести значение в "ТекстПодвала", а так как это число, то и прижать вправо


нЭлемент = ЭтаФорма.Элементы.вставить("МаржаПроцент", Тип("ПолеФормы"), Элементы.Товары); 
нЭлемент.Вид = ВидПоляФормы.ПолеВвода; 
нЭлемент.ПутьКДанным = "Объект.Товары.МаржаПроцент"; 	
нЭлемент.ТолькоПросмотр=Истина;	
нЭлемент.ОтображатьВПодвале=Истина;
нЭлемент.ТекстПодвала=Формат((Объект.Товары.Итог("Сумма")-Объект.Товары.Итог("СуммаЗакупки"))/Объект.Товары.Итог("Сумма"),"ЧЦ=4; ЧДЦ=2");
нЭлемент.ГоризонтальноеПоложениеВПодвале=ГоризонтальноеПоложениеЭлемента.Право;



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

 Здесь я не буду прикладывать код, а только дам направление и интересные наблюдения.

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

Первый вариант - программное создание реквизита и меняем длину по потребности.

Второй вариант - воспользоваться маской поля ввода для реквизита объекта, и менять по потребности маску. Т.е. длину реквизита объекта ставим в 11 символов (длина большинства номеров документов в 1С), потом устанавливаем маску, для длины 11 символов это будет одиннадцать собак (@) или другой спецсимвол. Допустим я вижу что префикс >0, тогда я вывожу маску длинной равной разнице длины реквизита и префикса, это делается на раз обычным циклом. Но в этом варианте также нужно добавить обработчик обрезающий значение реквизита, иначе это все фикция


Печальное наблюдение, в УНФ прямо несоразмерное количество вызов процедур и функций обрабатывающих отображение номеров (расходные накладные и счета фактуры). Один и тот же код вызывается по нескольку раз на объект, не только при печати, но и при открытии формы объекта и, замечу, формы списка!