23 мая 2022 г.

1C УдалитьПустыеСтрокиТЧ()

Удивительно, но некоторые пользователи не обращают внимание на пустую строку, оставленную в документе. Для одного документа процедура решается перебором перед записью, но у меня народ косячит исправно в большинстве ТЧ, поэтому было решено описать более-менее универсальную процедуру:

1С ПустаяСсылка() по типу значения

Мне нужно было получить пустую ссылку не знаю заранее тип значения реквизита колонки ТЗ. Нам известно что есть строки в ТЧ (ТЧДок),  имя реквизита передано строкой в переменной ИмяРеквизита.

МояПустаяСсылка=Новый(типзнч(ТЧДок[0][ИмяРеквизита]))

14 апреля 2022 г.

1С функция ДобавитьКоманду()

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



//Пример использвания в расширении (форма документа ПТиУ)
&НаСервере
Процедура Расш1_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)
эГруппаКоманд=ЭтаФорма.Элементы.вставить("ЭГруппаКоманд",тип("ГруппаФормы"), Элементы.Товары.КоманднаяПанель, Элементы.ТоварыКнопкиКоманднойПанели);
	эГруппаКоманд.Вид=ВидГруппыФормы.ГруппаКнопок;
	эГруппаКоманд.Отображение=ОтображениеГруппыКнопок.Компактное;
    
ДобавитьКоманду("ОтобразитьШтрихкоды",
					ОтображениеКнопки.Картинка,БиблиотекаКартинок.ТабличныйДокументТолькоПросмотр,
					Ложь,
					Тип("КнопкаФормы"),
					Элементы.ЭГруппаКоманд,
					Объект.ШтрихкодыУпаковок.Количество()>0);  

КонецПроцедуры    
// Функция - Добавить команду
//
// Параметры:
//  ИмяКомандыПроцедуры		 - Строка - Имя процедуры и команды будут совпадать, при помощи Синониминайзера, Выдернув "Команда", будет создан заголовок и подсказка
//  Отображение		 - ОтображениеКнопки -  Например: ОтображениеКнопки.Картинка
//  Картинка		 - БиблиотекаКартинок - Например: БиблиотекаКартинок.ТабличныйДокументТолькоПросмотр
//	ИзменяетСохраняемыеДанные - Булево - 
//  ТипЭлемента		 - Тип - Тип элемента ФОРМЫ, например: Тип("КнопкаФормы")
//  РодительЭлемента - ЭлементФормы - Например ГруппаКнопок
//  Доступность		 - Булево -
//
&НаСервере
Функция ДобавитьКоманду(ИмяКомандыПроцедуры, Отображение=Неопределено,Картинка=Неопределено,ИзменяетСохраняемыеДанные=Ложь,ТипЭлемента,РодительЭлемента=Неопределено,Доступность=Истина)
	ИмяКоманды="Команда"+ИмяКомандыПроцедуры;
	ИмяПроцедуры=ИмяКоманды;
	Заголовок=Синонимайзер(ИмяКомандыПроцедуры);
	Подсказка=Заголовок;
	
	Если Команды.Найти(ИмяКоманды) <> Неопределено Тогда
		Сообщить(СтрШаблон("Команда ""%1"" существует, пропуск",ИмяКоманды));
		Возврат
	КонецЕсли;
	
	НоваяКоманда= Команды.Добавить(ИмяКоманды);
	НоваяКоманда.Действие = ИмяПроцедуры;//Имя процедуры
	НоваяКоманда.Заголовок = Заголовок;
	НоваяКоманда.Подсказка = Подсказка;
	НоваяКоманда.ИзменяетСохраняемыеДанные=ИзменяетСохраняемыеДанные;
	Если Отображение<>Неопределено  Тогда
		НоваяКоманда.Отображение=Отображение;
	КонецЕсли;
	Если Картинка<>Неопределено  Тогда
		НоваяКоманда.Картинка=Картинка;
	КонецЕсли;
	
	ИмяЭлемента="Элемент"+ИмяКоманды;
	Если ЭтаФорма.Элементы.Найти(ИмяЭлемента)<>Неопределено Тогда  
		Сообщить(СтрШаблон("Элемент ""%1"" существует, пропуск",ИмяЭлемента));
		Возврат
	КонецЕсли;
	
	эНоваяКоманда = ЭтаФорма.Элементы.вставить(ИмяЭлемента, ТипЭлемента,?(РодительЭлемента=Неопределено,"",РодительЭлемента)); 
	эНоваяКоманда.ИмяКоманды=НоваяКоманда.Имя; 
	эНоваяКоманда.Доступность=Доступность;
КонецФункции

&НаСервере
Функция Синонимайзер(Имя, Ответ = "", Стэйт = 7, б = "")
    Для ё = 1 По СтрДлина(Имя) Цикл
        а = Сред(Имя, ё, 1);
        Стэйт = (НРег(а) <> а) * 4 + Цел(Стэйт / 2);
        Ответ = Ответ + ?(Стэйт = 2, НРег(б), ?(ё = 2, ВРег(б), б)) + ?(Стэйт = 4 ИЛИ Стэйт = 5, " ", "");
        б = а
    КонецЦикла;
    Возврат Ответ + б
КонецФункции


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

2 апреля 2022 г.

1СОшибка ГруппаКоманд.Отображение=ОтображениеГруппыКнопок.Компактное Не соответствие типов

 Создаю программно группу кнопок, хочу компактный вид и пишу:


эГруппаКоманд=ЭтаФорма.Элементы.вставить("ЭГруппаКоманд",тип("ГруппаФормы"), Элементы.Товары.КоманднаяПанель, Элементы.ТоварыКнопкиКоманднойПанели);
эГруппаКоманд.Вид=ВидГруппыФормы.ГруппаКнопок;
эГруппаКоманд.Отображение=ОтображениеГруппыКнопок.Компактное;

При открытии система выдает ошибку "Несоответствие типов" по строке номер два
Отладчиком проверяю и вижу что тип данного реквизита не группа, а кнопка....WTF????
Меняю местами вторую и третью строчку и проблема решена.

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");
нЭлемент.ГоризонтальноеПоложениеВПодвале=ГоризонтальноеПоложениеЭлемента.Право;