Таблицы на управляемых формах: создание, расширение, управление.

Опубликовал Sergey Andreev (starik-2005) в раздел Программирование - Работа с интерфейсом

Как вывести результат запроса в таблицу на управляемую форму, ведь здесь нет метода "СоздатьКолонки()"? Как добавить поле ввода в табличную часть документа, если нет желания менять документ? Разбираемся...

Добрый день!

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

поехали!

Итак, унас есть форма и запрос, результат которого выгружен в таблицу. Например, так:

Запрос = Новый Запрос("ВЫБРАТЬ * ИЗ Справочник.Банки");
Таблица = Запрос.Выполнить().Выгрузить();

Выведем таблицу на управляемую форму

Наша основная задача номер РАЗ - вывести результат запроса на управляемую форму.

Для этого нам нужно:

  1. Создать реквизит типа "ТаблицаЗначений".
  2. Создать реквизиты с типом значения, соответствующим типу колонки таблицы, для каждой колонки, подчиненные таблице.
  3. Создать элемент формы типа "ТаблицаФормы" для таблицы.
  4. Создать элементы формы для колонок типа "ПолеФормы".

Таким образом код у нас будет такой:

	// добавим таблицу: сначала саму таблицу, потом колонку.
	Реквизиты = Новый Массив;
	Реквизиты.Добавить(Новый РеквизитФормы("ТаблицаНаФорме", Новый ОписаниеТипов("ТаблицаЗначений")));
	Для Каждого Ст ИЗ Таблица.Колонки Цикл
		Реквизиты.Добавить(Новый РеквизитФормы(Ст.Имя, Ст.ТипЗначения, "ТаблицаНаФорме"));
	КонецЦикла;

	// добавим реквизиты на форму
	ИзменитьРеквизиты(Реквизиты);

	// добавим элементы формы
	Таб = Элементы.Добавить("ТаблицаНаФорме", Тип("ТаблицаФормы"));
	Таб.ПутьКДанным = "ТаблицаНаФорме";

	// запретим менять положение строк и сами строки, отключим командную панель
	Таб.ИзменятьСоставСтрок = Ложь;
	Таб.ИзменятьПорядокСтрок = Ложь;
	Таб.ПоложениеКоманднойПанели = ПоложениеКоманднойПанелиЭлементаФормы.Нет;

	Для Каждого Ст ИЗ Таблица.Колонки Цикл
		Рек = Элементы.Добавить("Колонка" + Ст.Имя, Тип("ПолеФормы"), Таб);
		Рек.Вид = ВидПоляФормы.ПолеНадписи;
		Рек.ПутьКДанным = "ТаблицаНаФорме" + "." + Ст.Имя;
		Рек.Заголовок = Ст.Имя;
	КонецЦикла;

	// заполним таблицу
	ЗначениеВРеквизитФормы(Таблица, "ТаблицаНаФорме");

Здесь мы создаем реквизиты, содержащие таблицу и колонки таблицы. Далее создаем элементы и прописываем для них путь к реквизитам формы. Т.е. у нас всегда создается и реквизит формы, который хранит значение, и элемент формы, который это значение отображает. В этом вся суть. При этом если Вы хотите создать группу формы, то реквизит формы вам не нужен - достаточно создать элемент формы типа "ГруппаФормы", после чего в поле "Вид" прописать соответствующтий вид элемента (Группа, Закладка, ...).

Данный код выводит на управляемую форму результат запроса. Но если вдруг в результате запроса у Вас будут элементы, типы которых не могут быть выведены на форму, то 1С будет ругаться. К таким элементам относятся хранилища значений, уникальные идентификаторы и, на сколько я знаю, другие таблицы значений (т.е. при выборке табличных частей у нас возникнут проблемы). Это нужно учитывать при создании реквизитов. При этом, если реквизит таблицы имеет тип "ТаблицаЗначений", то для его тоже нужно будет создать колонки. Также следует иметь ввиду, что имена элементов формы должны быть уникальными, при этом имена реквизитов должны быть уникальны внутри своих родителей (т.е. может существовать две разные таблицы с одинаковыми наименованиями колонок, но в пределах одной таблицы имена колонок должны отличаться).

Добавим колонку в таблицу документа

Теперь давайте посмотрим, как можно расширить уже имеющуюся таблицу формы.

Допустим, мы хотим добавить колонку в таблицу выданных авансов авансового отчета как-нибудь так:

Для этого просто напишем в процедуре ПриСозданииНаСервере такой вот код:

	// добавим реквизит
	МассивРеквизитов = Новый Массив;
	МассивРеквизитов.Добавить(Новый РеквизитФормы("Колонка1", Новый ОписаниеТипов("Строка"), "Объект.ВыданныеАвансы", "Колонка 1", Ложь));
	ИзменитьРеквизиты( МассивРеквизитов );
	
	Элт = Элементы.Добавить("Колонка1", Тип("ПолеФормы"), Элементы.ВыданныеАвансы);
	Элт.Вид = ВидПоляФормы.ПолеВвода;
	Элт.ПутьКДанным = "Объект.ВыданныеАвансы.Колонка1"; 

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

См. также

Добавить вознаграждение
Комментарии
1. Валерий Дегрик (mars207) 20 11.01.17 13:31 Сейчас в теме
Я бы еще добавил динамическое изменение таблицы в процессе работы. Имею в виду проверку наличия реквизита и элемента, возможность удаления лишних колонок. Например, показать движения по месяцам в зависимости от указанного количества месяцев. А то как-то жиденько…
kraynev-navi; +1 Ответить 2
2. Sergey Andreev (starik-2005) 803 11.01.17 14:10 Сейчас в теме
(1) справедливо, но задача была показать, как в принципе это делать. А уж обращать внимание на второй параметр метода "ИзменитьРеквизиты()" - это дело для самостоятельного изучения. Но, как показала практика, лучше полностью сносить таблицу и создавать новую, чем заморачиваться изменениями колонок - пользы чуть, а геморроя - масса.
3. С К (kraynev-navi) 181 12.01.17 13:39 Сейчас в теме
поддерживаю (1). Приведенный код обильно присутствует на всем известных форумах.
Если бы сделали всеобъемлющее руководство, привели нюансы с какими багами предстоит встретиться на разных платформах, про удаление и т.д.
А так... В чем новость?
4. Sergey Andreev (starik-2005) 803 12.01.17 15:19 Сейчас в теме
(3) по поводу "обильности" что-то не замечал, а по поводу изменений - это лишь одна из манипуляций с данными формы. Я в последнее время отказался от создания на форме таблиц - формирую их динамически. Для того, чтобы знать, какие элементы нужно удалить, просто делаю на форме список значений, в который добавляю созданные реквизиты и связанные с ними элементы (идентификаторы). Дальше при необходимости просто удаляю все созданные элементы/реквизиты и создаю заново. Ничего тут "такого" в плане нюансов нет.
5. Fomix (fomix) 19 13.01.17 10:22 Сейчас в теме
Можете пояснить на словах "просто делаю на форме список значений, в который добавляю созданные реквизиты и связанные с ними элементы (идентификаторы). Дальше при необходимости просто удаляю все созданные элементы/реквизиты и создаю заново.".
Желательно с кодом. Заранее спасибо!
6. Sergey Andreev (starik-2005) 803 13.01.17 11:59 Сейчас в теме
(5) а что конкретно непонятно? В вышеуказанный код добавляете "СписокЗанченийСРеквизитами.Добавить(Колонка.Имя, Реквизит.Имя)", а перед этим можете вызвать функцию, которая пробежится по элементам списка, удалит элементы "Элементы.Удалить(Элементы.Найти(ЭлементСписка.Представление))", добавит в массив реквизитов для удаления имя реквизита (именно имя, а не реквизит) и вызовет функцию "ИзменитьРеквизиты(, УдаляемыеРеквизиты)". Все же просто.
7. Fomix (fomix) 19 17.01.17 14:04 Сейчас в теме
(6) Фигня получается, если делать как написали!
Зачем использовать конструкцию "ИзменитьРеквизиты(, УдаляемыеРеквизиты)", если выше элемент с формы уже удален строкой: "Элементы.Удалить(Элементы.Найти(ЭлементСписка.Представление))"?!
Тогда и "СписокЗначенийСРеквизитами" не нужен.
Может не так понял...
8. Sergey Andreev (starik-2005) 803 17.01.17 16:37 Сейчас в теме
(7) понял действительно не так.Не стоит путать реквизиты формы и элементы формы. Через "Элементы.Удалить()" удаляется элемент формы, а через ИзменитьРеквизиты добавляются и удаляются... что?.. правильно - реквизиты формы, которые ни разу не элементы формы.