Некоторые картинки не загружаются из РФ и РК, используйте VPN.

суббота, 18 июня 2022 г.

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

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


Процедура ОбработкаПолученияПредставления(Данные, Представление, СтандартнаяОбработка)
   СтандартнаяОбработка = Ложь;
   ДокСсыл=Данные.Ссылка;
   Брак=?(ЗначениеЗаполнено(ДокСсыл.БракЗаданияВРаботу),"Брак: ","");
   Представление = СтрШаблон("%1%2 №%3 от %4 (%5)",
                              Брак,ДокСсыл.Метаданные().Синоним,
                              Число(ДокСсыл.Номер),
                              формат(ДокСсыл.Дата,"ДФ=dd.MM.yyyy"),
                              ДокСсыл.ВидОперации);
КонецПроцедуры




понедельник, 23 мая 2022 г.

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

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

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

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

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

вторник, 10 мая 2022 г.

четверг, 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С УФ вывод на форму ТЗ с генерацией колонок

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

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

	
&НаСервере
Процедура ВывестиСписокДокументовНаФорму(ТзВыборкаИзБД)
    //ТзВыборкаИзБД - например выгрузка из БД запросом 
    ИмяТЗ_НаФорме="ТЗ"; //реквизит формы, а не элемент
    //Сначала очищаем ТЗ
    //если есть реквизиты созданные интерактивно, то вылезет ошибка
	УдаляемыеРеквизиты = Новый Массив;
	
	РеквизитыДляУдаления = ПолучитьРеквизиты(ИмяТЗ_НаФорме);
	Для Каждого РеквизитУдаления Из РеквизитыДляУдаления Цикл
        УдаляемыеРеквизиты.Добавить(ИмяТЗ_НаФорме+"."+РеквизитУдаления.Имя);
        Элементы.Удалить(Элементы[ИмяТЗ_НаФорме+РеквизитУдаления.Имя]);
	КонецЦикла;
	
	ДобавляемыеРеквизиты = Новый Массив;
	Для каждого Колонка Из ТзВыборкаИзБД.Колонки Цикл
		ИмяКолонки=Колонка.Имя;
		// пытаемся определить тип значения, иначе при попытке запихать ТЗ в Запрос получим ошибку "тип не может быть выбран в запросе"
		// Также, побочный эффект - это нормальное представление флажка на форме
		// Также прошу обратиться внимание на тот факт, что в первой строке в какой либо из колонок может быть NULL,
		// что привидет к неправильному определению типа всей колонки, поэтому в запросе необходимо заблаговременно
		//ИмяТипа=Строка(ТипЗнч(ТЗ[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 тогда
			нСообщение.Поле = Поле;
		КонецЕсли;
		Если ОбъектДанных <> Неопределено Тогда
			нСообщение.УстановитьДанные(ОбъектДанных);
		КонецЕсли;
		нСообщение.Сообщить(); 		
	КонецЕсли;
КонецПроцедуры




среда, 2 марта 2022 г.

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

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

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


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



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

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

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

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

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


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

пятница, 21 января 2022 г.

1СОшибка Для объекта метаданных "Документ.ЗаявкаНаРасходованиеСредств" не найден идентификатор в справочнике "Идентификаторы объектов метаданных"

В справочнике ИдентификаторыОбъектовМетаданных некоторые элементы имеют знаки вопроса в реквизитах и помечены на удаление. Может выскакивать ошибка "{ОбщийМодуль.ОбщегоНазначения.Модуль(2646)}: Ошибка при выполнении функции ОбщегоНазначения.ИдентификаторОбъектаМетаданных(). Для объекта метаданных "Документ.ЗаявкаНаРасходованиеСредств" не найден идентификатор в справочнике "Идентификаторы объектов метаданных"."

Рекомендации простые:

  1. открыть через меню "Все функции" справочник "Идентификаторы объектов метаданных", нажать кнопку "Обновить данные справочника"; 
  2. если указанной кнопки нет - выполнить программный код: Справочники.ИдентификаторыОбъектовМетаданных.ОбновитьДанныеСправочника(); 
  3. либо запустить программу с параметром командной строки 1С:Предприятия 8 "/С ЗапуститьОбновлениеИнформационнойБазы"; 
  4. либо увеличить номер версии конфигурации, чтобы при очередном запуске выполнились процедуры обновления данных информационной базы.
На УНФ не прокатило, пришлось садится и разбираться. В итоге пришел к решению - удалить помеченные элементы справочника ИдентификаторыОбъектовМетаданных, но для этого нужно разорвать связи. Кстати удаление возможно только через Стандартные=>Удаление помеченных.

понедельник, 10 января 2022 г.

1СЗапрос Выбрать дубли по основному полю

Изначально в справочнике не должно было быть повторений по двум реквизитам, ни вместе, ни по отдельности, но при случайной проверке были выявлены события когда два элемента имеют одинаковый Реквизит1 и различный Реквизит2, для выявления такого казуса можно использовать запрос, в котором соединяем справочник на себя где Реквизит1=Реквизит1, а Реквизит2<>Реквизит2. Вроде все, но нет, т.к. выдача будет двойной, а т.к. нам не важно какой элемент будет выбран, то добавляем еще одно сравнение - Ссылка>Ссылка. Прошу обратить внимание, данное решение работает только на одном дубле, если их больше, то ситуация будет другой.


ВЫБРАТЬ

	Участники.НомерКарты КАК НомерКарты,

	Участники.НомерТелефона КАК НомерТелефона,

	Участники1.НомерТелефона КАК НомерТелефона1

ИЗ

	Справочник.Участники КАК Участники

		ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Участники КАК Участники1

		ПО Участники.НомерКарты = Участники1.НомерКарты

			И Участники.НомерТелефона <> Участники1.НомерТелефона

			И Участники.Ссылка > Участники1.Ссылка

УПОРЯДОЧИТЬ ПО

	НомерКарты