1С: использование HTML поля на форме

Сиё может понадобиться, если необходимо ну…например вывести какую-то динамическую информацию на форму, причём со стилями не стандартными для 1С, т.е. штатными средствами 1С не выполнимыми или трудновыполнимыми.

В моём случае, я в это поле просто вывожу динамический список напоминаний. При клике на который открывается соответствующий документ.

Итак, создаём на форме реквизит «Прочие напоминания» с типом строка. Длина -0, т.е. не ограниченная. Затем перетаскиваем реквизит на форму и выбираем вид «Поле HTML документа»:

При открытии формы, заполняем HTML:

&НаСервере
Функция СформироватьСписокНапоминанийНаСервере(Исполнитель)
список_напоминаний=СК_ОбщиеФункции.СформироватьУведомленияОНапоминаемыхДатах(ложь,Исполнитель);
	body="<ul>";
	для каждого стр из список_напоминаний цикл
		body=body+"<li><a href='"+стр.ссылка.номер+"'>"+стр.Пояснение+"</a></li>";
	конеццикла;	
	body=body+"</ul>";
	возврат body;
КонецФункции

&НаКлиенте
Процедура ПриОткрытии(Отказ)
	ПрочиеНапоминания="<html><head></head><body>"+СформироватьСписокНапоминанийНаСервере(Исполнитель)+"</body></html>";	
КонецПроцедуры

Далее отлавливаем клик по полю HTML, и открываем документ:

&НаКлиенте
Процедура ПрочиеНапоминанияПриНажатии(Элемент, ДанныеСобытия, СтандартнаяОбработка)
	если ДанныеСобытия.Свойство("href") тогда
		РазделёныйМассивСсылки=СтрРазделить(ДанныеСобытия.href,"/");		
		НомерДокумента=РазделёныйМассивСсылки[РазделёныйМассивСсылки.Количество()-1];
		ОткрытьЗначение(ПолучитьСсылкуНаДокумент(НомерДокумента));
	конецесли;
	СтандартнаяОбработка=ложь;
КонецПроцедуры

1С: Кнопка печати на управляемой форме

Для того чтобы на форме автоматически появилась кнопка печати, достаточно:

1.Создать команду, с именем надписи которая будет в выпадающей кнопке печати

    2. В модуле команды разместить код вывода печатной формы. Примерно что-то в этом духе:

    Функция КомпонентаФормированияQRКода()
    	
    	QRCodeGenerator = Неопределено;
    	
    	Попытка
    		Если ПодключитьВнешнююКомпоненту("ОбщийМакет.КомпонентаПечатиQRКода24", "QR") Тогда
    			QRCodeGenerator = Новый("AddIn.QR.QRCodeExtension");
    		Иначе
    			Возврат Неопределено;
    		КонецЕсли;
    	Исключение
    		сообщить(ОписаниеОшибки());
    		Возврат Неопределено;
    	КонецПопытки;
    	
    	Возврат QRCodeGenerator;
    	
    КонецФункции
    
    
    &НаКлиенте
    Процедура ОбработкаКоманды(ПараметрКоманды, ПараметрыВыполненияКоманды)
    
    	СК_ЖурналДействийПользователей.ЗарегистрироватьДействие(
    		"ВызовКоманды",
    		ПараметрыВыполненияКоманды.НавигационнаяСсылка,
    		ПараметрКоманды
    	);
    	
    
    	ТабДок = ПолучитьТабДок(ПараметрКоманды);
    	ТабДок.Показать();
    	
    КонецПроцедуры
    
    &НаСервере
    Функция ПолучитьТабДок(ДокСсылка)
    	
    	ТабДок = Новый ТабличныйДокумент;
    	ТабДок.АвтоМасштаб			= Истина;
    	ТабДок.ОриентацияСтраницы	= ОриентацияСтраницы.Ландшафт;
    	ТабДок.КлючПараметровПечати	= "ПАРАМЕТРЫ_ПЕЧАТИ_СК_ГР_РеестрУведомленныхПотребителей";
    	
    	QRCodeGenerator = КомпонентаФормированияQRКода();
    	
    	Макет = Документы.СК_ГР_РеестрУведомленныхПотребителей.ПолучитьМакет("Квитанция");
    	КоличествоКвитанций=0;
    	для каждого стр из  ДокСсылка цикл
    		КоличествоКвитанций =КоличествоКвитанций + 1; 
    		ОбластьШапка  = Макет.ПолучитьОбласть("Шапка");	
    		
    		ОбластьШапка.Параметры.Адрес 			= стр.АдресПотребителя;
    		если ТипЗнч(стр.лс)=Тип("Строка") тогда
    			лицсч=стр.лс;			
    		иначе	
    			лицсч=стр.лс.код;
    		конецесли;	
    		ОбластьШапка.Параметры.ЛС= "9" + Строка(лицсч);
    		ОбластьШапка.Параметры.ФИО 	= стр.ФИО_потребителя;
    		ОбластьШапка.Параметры.СуммаРуб 	=Цел(стр.ПолнаяОплатаЗадолженостиСумма);
    		ОбластьШапка.Параметры.СуммаКоп 	= Прав(Формат(стр.ПолнаяОплатаЗадолженостиСумма,"ЧДЦ=2"),2);
    	
    		ИмяQRКода = "ШтрихКод";
    		
    		Попытка
    			УровеньКоррекции = 0;
    			Размер = 120;
    			ДанныеВШК = "ST00012|Name=ООО Сукацукая|PersonalAcc=234к234к34к|BankName=ПАО СБЕРБАНК|BIC=044525225|CorrespAcc=епукепк|Category=екпукеп|PayeeINN=4543е345е|Purpose=ОТКЛЮЧЕНИЕ/ПОДКЛЮЧЕНИЕ|PersAcc="+"9" + Строка(лицсч)+"|PayerAddress="+стр.АдресПотребителя+"|Sum="+формат(Цел(стр.ПолнаяОплатаЗадолженостиСумма*100),"ЧГ=")+"";
    			ДанныеQRКода = QRCodeGenerator.GenerateQRCode(ДанныеВШК, УровеньКоррекции, Размер);
    		Исключение  
    		сообщить(описаниеОшибки());	
    		КонецПопытки;
    		
    		Если ДанныеQRКода <> Неопределено Тогда 
    			ОбластьШапка.Рисунки[ИмяQRКода].Картинка = Новый Картинка(ДанныеQRКода);
    		КонецЕсли;
    		Если КоличествоКвитанций = 2 Тогда
    			ТабДок.ВывестиГоризонтальныйРазделительСтраниц();
    			КоличествоКвитанций = 0;
    		КонецЕСли;
    	
    	
    	ТабДок.Вывести(ОбластьШапка);
    	конеццикла;
    	
    	ТабДок.ТолькоПросмотр = истина;
    	ТабДок.АвтоМасштаб = истина;
    	
    	
    	Возврат ТабДок;
    	
    КонецФункции

    3. В модуле менеджера документа разместить функцию:

    Процедура Печать(МассивОбъектов, ПараметрыПечати, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
    	ПараметрыВывода.ДоступнаПечатьПоКомплектно = Истина;		
    КонецПроцедуры

    И всё. Теперь на форме документа и форме списка появится кнопка «Печать» с выпадающим списком.

    1с: Еще раз о сортировке массива структур

    Уже не однократно поднимал в своём блоге вопрос о методе сортировки массива структур по какому то ключу. В конце концов остановился на самом медленном, но зато самом менее трудоёмком методе. Для нескольких тысяч записей пойдет. Для нескольких десятков тысяч записей уже нет, ибо памяти не хватит. Общая методика такова:

    1. Преобразуем массив структур в таблицу значений
    2. Отсортируем штатными средствами таблицу значений по ключевому полю
    3. Далее используем еже не массив структур, а именно таблицу значений, чтобы уменьшить накладные расходы на обратные преобразования
    Функция ПреобразованиеМассивВТаблицуЗначений(Массив) экспорт
       ТЗ = Новый ТаблицаЗначений;
       Для Каждого СтрокаМассива Из Массив Цикл
           Если ТЗ.Колонки.Количество() = 0 Тогда
               Для Каждого ЭлементМассива Из СтрокаМассива Цикл
                   ТЗ.Колонки.Добавить(ЭлементМассива.Ключ);
               КонецЦикла;
           КонецЕсли;
    
           НоваяСтрока = ТЗ.Добавить();
           Для Каждого ЭлементМассива Из СтрокаМассива Цикл
               НоваяСтрока[ЭлементМассива.Ключ] = ЭлементМассива.Значение;
           КонецЦикла;
       КонецЦикла;
       Возврат ТЗ;
    КонецФункции

    Использование:

    ТЗ_ЛС=ПреобразованиеМассивВТаблицуЗначений(список_лс.result.responseObject);
    ТЗ_ЛС.Сортировать("room Возр");
    ...
    для каждого стр из ТЗ_ЛС цикл
    ....
    конеццикла

    1С: Фоновые задания внутри фоновых заданий

    Задача: распаралелить медленную вставку записей в БД 1С, при чтении файла Excel

    Как ни странно, но такая возможность есть и работает начиная с версии платформы 8.3.8. Т.е. можно запустить фоновое задание внутри фонового задания….ну например по вставке в БД большого количества записей, которая выполняется весьма медленно. Полноценно этот процесс распаралелить можно например как-то так:

    Функция СделатьЗаписьвБДПДЗФоново(парам) экспорт
    	...
        // делаем медленную запись в БД
    	...
    конецфункции	
    
    // Просматриваем массив с идентификаторами фоновых заданий и удаляем те которые завершились
    Функция ПочиститьМассивОтЗавершенныхЗаданий(МассивФоновыхЗаданий) экспорт
    		для каждого ФЗМ из МассивФоновыхЗаданий цикл
    			ФЗ = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(ФЗМ);
    			если ФЗ.Состояние<>СостояниеФоновогоЗадания.Активно тогда
    				МассивФоновыхЗаданий.Удалить(МассивФоновыхЗаданий.Найти(ФЗМ));
    			конецесли;	
    		конеццикла;		
    	возврат МассивФоновыхЗаданий;
    конецфункции		
    
    // выполняем загрузку построчно файла Excel, запуская запись данных в БД
    // отдельным потоком. Количество потоков ограничивам 10 штуками
    Функция ВыполнитьЗагрузку(парам) экспорт
    	МассивФоновыхЗаданий=Новый Массив();
    	МаксимумЗаданий=10;
    ...
        Для	 нСтрокаТФ = 2 ПО КолВоСтрокФайла Цикл  
            ....
    			МассивПараметров = Новый Массив;
    			Параметры=Новый Структура("aa,bb,cc",
    				1,
    				2,
    				3,
                );
    			МассивПараметров.Добавить(Параметры);
    			ФЗ = ФоновыеЗадания.Выполнить("ДлительныеОперации.СделатьЗаписьвБДПДЗФоново",МассивПараметров);	
    			МассивФоновыхЗаданий.Добавить(ФЗ.УникальныйИдентификатор);											
    			МассивФоновыхЗаданий=ПочиститьМассивОтЗавершенныхЗаданий(МассивФоновыхЗаданий);
    			// ждём пока завершаться запущеные потоки, если их больше 10
    			пока МассивФоновыхЗаданий.Количество()>МаксимумЗаданий цикл
    				МассивФоновыхЗаданий=ПочиститьМассивОтЗавершенныхЗаданий(МассивФоновыхЗаданий);
    			конеццикла;	        
            ....
       конеццикла;
    конецфункции	   

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

    Сложение с null в запросе

    Иногда удаётся найти подводные камни там, где совсем не ждешь от 1С. Оказывается в запросах 1С, сложение столбцов а+б даёт в сумме null, если одно из значений равно null. даже если чётко укажешь преобразовать значение в строку, например так:

    строка(geo_coors_public_regions.name)+строка(geo_coors_public_areas.name)

    Не прокатывает (с). Приходится городить код вида:

    ВЫБОР
    		КОГДА geo_coors_public_regions.name ЕСТЬ NULL
    			ТОГДА ""
    		ИНАЧЕ geo_coors_public_regions.name
    	КОНЕЦ + "," + ВЫБОР
    		КОГДА geo_coors_public_areas.name ЕСТЬ NULL
    			ТОГДА ""
    		ИНАЧЕ geo_coors_public_areas.name
    	КОНЕЦ + "," + ВЫБОР
    		КОГДА geo_coors_public_cities.name ЕСТЬ NULL
    			ТОГДА ""
    		ИНАЧЕ geo_coors_public_cities.name
    	КОНЕЦ + "," + ВЫБОР
    		КОГДА geo_coors_public_settlers.name ЕСТЬ NULL
    			ТОГДА ""
    		ИНАЧЕ geo_coors_public_settlers.name
    	КОНЕЦ
    ИЗ
    ...

    1 3 4 5 6 7 37