Pull to refresh

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

Reading time 5 min
Views 23K
Меня очень часто спрашивают, как добавить таблицу к документу или справочнику?
И действительно, как сделать такую задачу не усложняя дальнейшее обновление конфигурации? И вроде есть доп. реквизиты и доп. сведения, но почему же они не могут принимать тип таблицы значений?


В итоге чаще всего используется 2 варианта:

1. Простой способ. Прямо в объекте добавляется таблица, а затем либо программно либо жестко(вручную) выводится на форму.

Минусы. Обновление конфигурации будет требовать соблюдения изменений и повышенной внимательности, чтобы не потерять эти изменения.
Плюсы. Самый простой вариант для разработки, к таблице значений можно обращаться без танцев с бубном, например через запросы.

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

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

Есть, конечно, еще другие варианты к примеру с хранилищем, но статья не об этом…

Статья, о том, как все-таки хранить таблицу значений в доп. реквизитах, ну или в доп. сведениях.

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

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

Пример продемонстрирую на конфигурации Документооборот 2.1.6.8. Буду использовать дополнительный реквизит, но можно использовать дополнительные сведения. Весь код будет написан в Расширении конфигурации.

Задача:
Сразу говорю задачка больше шуточная для демонстрации метода. Например, нам понадобилось добавить табличную часть «Адекватность контактных лиц», она должна присутствовать в справочнике Контрагенты и содержать колонки: Контактное лицо, Совет (некая рекомендация по общению с контактным лицом), Тип контакта.

1 Добавляем доп. реквизит и называем его к примеру «ТЗ_АдекватностьКонтактныхЛиц».
Я этот реквизит делаю общим для всех видов контрагентов. Тип его будет строка неограниченной длины.



2 Создаем Расширение конфигурации и Дорабатываем форму Контрагентов.
Добавляем реквизиты формы:

— «ДопТЗ» тип ПланВидовХарактеристикСсылка.ДополнительныеРеквизитыИСведения
— ТЗ_АдекватностьКонтактныхЛиц тип ТаблицаЗначений:
КонтактноеЛицо тип СправочникСсылка.КонтактныеЛица
ТипКонтакта тип Строка
Совет тип Строка



Добавляем на форму страницу «ГруппаАдекватностьКонтактныхЛиц» и снимаем видимость.
В данную группу выводим «ТЗ_АдекватностьКонтактныхЛиц»



3 Пишем код.
ПриСозданииНаСервере.
Необходимо считать сам доп реквизит напомню мы его обозвали «ТЗ_АдекватностьКонтактныхЛиц», далее прочитать его значение и построить по его значению таблицу значений.

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

Процедура ДопТЗ_ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
	//Считываем доп реквизит
	//ТЗ_АдекватностьКонтактныхЛиц - В моем примере доп реквизит называется так
	ДопТЗ = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("ТЗ_АдекватностьКонтактныхЛиц");
	
	Если ЗначениеЗаполнено(ДопТЗ) Тогда
		//Если нашли свойство тогда делаем страницу с ТЗ видимой
		Элементы.ГруппаАдекватностьКонтактныхЛиц.Видимость = Истина;

		//Считываем значение доп реквизита
		НайденныеСтроки = Объект.ДополнительныеРеквизиты.НайтиСтроки(Новый Структура("Свойство", ДопТЗ));
		перЗначение = ?(НайденныеСтроки.Количество() = 1, НайденныеСтроки[0].Значение, Неопределено);
		
		//Если значение прочитали пытаемся прочитать из JSON
		Если перЗначение <> Неопределено Тогда
			//Читаем JSON
			ЧтениеJSON = Новый ЧтениеJSON;
			ЧтениеJSON.УстановитьСтроку(перЗначение);
			Попытка
	        	ДопДанные = ПрочитатьJSON(ЧтениеJSON);
			Исключение
				ДопДанные = "";
			КонецПопытки;
			//Если вернулся массив значит JSON прочитали нормально
			//Заполняем ТЗ_АдекватностьКонтактныхЛиц
			Если ТипЗнч(ДопДанные) = Тип("Массив") Тогда
				Для Каждого СтрокаДД из	ДопДанные Цикл 
					СтрАдекватов = ТЗ_АдекватностьКонтактныхЛиц.Добавить();
					//Мы уже зарание знаем какой элемент нужно искать по уникальному идентификатору
					СтрАдекватов.КонтактноеЛицо = ПолучитьСсылкуПоGUIDИВидуОбъекта(СтрокаДД.КонтактноеЛицо,"Справочники.КонтактныеЛица");
					СтрАдекватов.ТипКонтакта    = СтрокаДД.ТипКонтакта;
					СтрАдекватов.Совет          = СтрокаДД.Совет;
			    КонецЦикла;
			КонецЕсли;

		КонецЕсли;
	КонецЕсли;
	
КонецПроцедуры

//Функция возврата Ссылки по уникальному идентификатору и виду объекта
&НаСервере
Функция ПолучитьСсылкуПоGUIDИВидуОбъекта(GUIDВх,ВидОбъектаВх) Экспорт
	Результат=Неопределено;
	Попытка
		Выполнить("Результат = "+ВидОбъектаВх+".ПолучитьСсылку(Новый УникальныйИдентификатор("""+GUIDВх+"""));");
	Исключение
	КонецПопытки;
	Возврат Результат;
КонецФункции


ПриОткрытии. Программно прячем доп. реквизит. Он хранит JSON, поэтому пользователю особо неинтересен.

&НаКлиенте
Процедура ДопТЗ_ПриОткрытии(Отказ)
	Если ЗначениеЗаполнено(ДопТЗ) Тогда
		//Ищем на форме нужный нам доп реквизит
		//Свойства_ОписаниеДополнительныхРеквизитов - В документообороте, в других конфигурациях скорее всего по другому.
		НайденныеСтроки = ЭтаФорма.Свойства_ОписаниеДополнительныхРеквизитов.НайтиСтроки(Новый Структура("Свойство", ДопТЗ));
		//Прячем элемент программно
		Если НайденныеСтроки.Количество() = 1 Тогда 
			Элементы[НайденныеСтроки[0].ИмяРеквизитаЗначение].Видимость = Ложь;
		КонецЕсли;	
	КонецЕсли;
КонецПроцедуры

ПередЗаписьюНаСервере. Если ТЗ изменилась сохраняем ее в виде строки JSON в доп. реквизит.

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

Tags:
Hubs:
+3
Comments 37
Comments Comments 37

Articles