Таблица формы 1С: строки, колонки, данные

Дата: 21.09.2026 07:06:43
Управляемые формы
Таблица формы
Табличная часть
Элементы формы
События формы
Таблица значений
Комментарий:
0
Платформа:
8.3
Конфигурация:
Любая
Формы:
Управляемые

Таблица формы 1С — элемент управляемой формы, который выводит коллекцию: табличную часть объекта, реквизит типа ТаблицаЗначений или ДеревоЗначений, динамический список. С ней работает почти любая доработка формы: пересчёт суммы в строке документа, проверка строки, поиск позиции, обработка отмеченных строк, заполнение из запроса. Ниже — как элемент связан с данными, как в платформе 8.3 добавлять, искать и сортировать строки, какие у таблицы есть события и где чаще всего ошибаются.

Как таблица формы 1С связана с данными

На форме всегда две сущности. Реквизит хранит данные, элемент «Таблица» их показывает. Связывает их свойство элемента ПутьКДанным: для табличной части документа это Объект.Товары, для реквизита обработки — просто Товары. Код работает с данными (Объект.Товары), а к элементу (Элементы.Товары) обращается за тем, что видит пользователь: текущей строкой, выделением, активной колонкой.

Данные таблицы формы хранятся не в прикладных типах, а в типах данных формы. Табличная часть и таблица значений становятся ДанныеФормыКоллекция, дерево — ДанныеФормыДерево. Эти типы есть и на клиенте, и на сервере, поэтому обойти строки или поменять значение в ячейке можно без серверного вызова.

Источник данныхТип в формеЧто лежит в ТекущаяСтрока
Табличная часть объектаДанныеФормыКоллекцияидентификатор строки (Число)
Реквизит ТаблицаЗначенийДанныеФормыКоллекцияидентификатор строки (Число)
Реквизит ДеревоЗначенийДанныеФормыДеревоидентификатор строки (Число)
Динамический списокДинамическийСписокключ строки, при основной таблице — ссылка

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

Как добавить реквизит в таблицу формы

Колонку сначала добавляют в данные, потом в элемент. Для табличной части это новый реквизит табличной части в конфигураторе, для обработки — новая колонка реквизита формы на вкладке «Реквизиты». Затем колонку перетаскивают из дерева реквизитов в элемент таблицы: появится поле с именем вида ТоварыСкидка и путём к данным Объект.Товары.Скидка.

С колонками табличной части объекта есть тонкость: колонку, которую не вывели в таблицу и не отметили в дереве реквизитов флажком «Использовать всегда», платформа в данные формы не загружает. Служебную колонку, которую пользователь видеть не должен, отмечают этим флажком или выводят полем с Видимость = Ложь. Создать реквизит и таблицу программно, через ИзменитьРеквизиты и Элементы.Добавить, тоже можно — это разобрано в статье про таблицу значений на форме.

Текущая строка, выделенные строки и идентификатор

У элемента таблицы три свойства, которые нужны постоянно:

  • ТекущиеДанные — сама строка под курсором или Неопределено, если курсора нет. Через неё поля и читают, и меняют.
  • ТекущаяСтрока — идентификатор этой строки.
  • ВыделенныеСтроки — массив идентификаторов выделенных строк. Чтобы можно было выделить больше одной, у таблицы ставят РежимВыделения = «Множественный».

Идентификатор и индекс — разные вещи. Индекс (Объект.Товары.Индекс(Строка)) — позиция с нуля, он меняется после удаления, вставки и сортировки. Идентификатор (Строка.ПолучитьИдентификатор()) закреплён за строкой, пока она существует. По нему строку находят методом НайтиПоИдентификатору, его же передают на сервер вместо самой строки. После Загрузить строки создаются заново, и старые идентификаторы ни на что не указывают.

Пример: команда делит количество текущей строки пополам и вставляет вторую половину сразу под ней.

&НаКлиенте
Процедура РазделитьСтроку(Команда)

	СтрокаТаблицы = Элементы.Товары.ТекущиеДанные;
	Если СтрокаТаблицы = Неопределено Или СтрокаТаблицы.Количество < 2 Тогда
		Возврат;
	КонецЕсли;

	// Новая строка сразу под текущей
	Индекс = Объект.Товары.Индекс(СтрокаТаблицы);
	НоваяСтрока = Объект.Товары.Вставить(Индекс + 1);
	ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаТаблицы, "Номенклатура, Цена");

	НоваяСтрока.Количество = Цел(СтрокаТаблицы.Количество / 2);
	СтрокаТаблицы.Количество = СтрокаТаблицы.Количество - НоваяСтрока.Количество;
	НоваяСтрока.Сумма = НоваяСтрока.Количество * НоваяСтрока.Цена;
	СтрокаТаблицы.Сумма = СтрокаТаблицы.Количество * СтрокаТаблицы.Цена;

	// Курсор ставится идентификатором, а не индексом
	Элементы.Товары.ТекущаяСтрока = НоваяСтрока.ПолучитьИдентификатор();
	Модифицированность = Истина;

КонецПроцедуры

Добавить строку и заполнить таблицу формы

На клиенте у коллекции работают Добавить, Вставить, Удалить, Очистить, Количество, Индекс, НайтиСтроки и НайтиПоИдентификатору. Выгрузить и Загрузить возвращают и принимают ТаблицаЗначений, а на тонком клиенте такого типа нет, поэтому эти методы вызывают на сервере.

Строку добавляют двумя способами. Объект.Товары.Добавить() создаёт её молча: события таблицы не вызываются, редактирование не начинается. Элементы.Товары.ДобавитьСтроку() повторяет кнопку «Добавить»: срабатывают ПередНачаломДобавления и ПриНачалеРедактирования, курсор уходит в новую строку. Первый вариант подходит для заполнения, второй — когда значение должен сразу ввести пользователь.

Заполнить таблицу формы из запроса проще всего на сервере, одной строкой через Загрузить. Пример для обработки:

// Форма обработки. Реквизит Товары: ТаблицаЗначений,
// колонки Выбран (Булево) и Номенклатура (СправочникСсылка.Номенклатура).

&НаКлиенте
Процедура Заполнить(Команда)

	ЗаполнитьНаСервере();

КонецПроцедуры

&НаСервере
Процедура ЗаполнитьНаСервере()

	Запрос = Новый Запрос;
	Запрос.Текст =
	"ВЫБРАТЬ РАЗРЕШЕННЫЕ ПЕРВЫЕ 100
	|	Спр.Ссылка КАК Номенклатура
	|ИЗ
	|	Справочник.Номенклатура КАК Спр
	|ГДЕ
	|	НЕ Спр.ПометкаУдаления
	|	И НЕ Спр.ЭтоГруппа
	|
	|УПОРЯДОЧИТЬ ПО
	|	Спр.Наименование";
	// Условие ЭтоГруппа нужно, если справочник с иерархией групп и элементов

	// Колонки сопоставляются по именам, Выбран получит Ложь
	Товары.Загрузить(Запрос.Выполнить().Выгрузить());

КонецПроцедуры

Псевдонимы полей в запросе должны совпадать с именами колонок реквизита. Колонки Выбран в запросе нет, и она получит значение по умолчанию. Если таблицу нужно обработать средствами ТаблицаЗначений (свернуть, найти дубли), используют пару РеквизитФормыВЗначение("Товары") и ЗначениеВРеквизитФормы(Таблица, "Товары"). Для табличной части объекта то же дают Объект.Товары.Выгрузить() и Загрузить.

Поиск и сортировка строк

Поиск по значениям колонок делает НайтиСтроки: на вход структура «колонка — значение», на выходе массив строк. Метод работает на клиенте. Чтобы показать найденную строку, присвойте её идентификатор свойству ТекущаяСтрока и переведите фокус на таблицу — так устроена команда НайтиСтроку в примере ниже.

Сортировать("Сумма Убыв") принимает строку с колонками и направлениями, как у таблицы значений. Метод доступен и на клиенте, но при таком вызове платформа всё равно обращается к серверу. Если на сервер и так нужно идти, сортируйте в той же серверной процедуре: лишнего вызова не будет. Идентификатор текущей строки запоминают до вызова и возвращают после, тогда курсор остаётся на той же позиции товара.

События таблицы формы

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

СобытиеКогда вызываетсяЗачем обычно нужно
ПриАктивизацииСтрокикурсор перешёл на другую строкуобновить данные, связанные со строкой
Выбордвойной щелчок или Enter по строке, когда ячейка не редактируетсяоткрыть документ или элемент из строки
ПередНачаломДобавленияперед добавлением или копированием строкизапретить добавление через Отказ
ПриНачалеРедактированиястрока перешла в режим ввода, у новой НоваяСтрока = Истиназаполнить значения по умолчанию
ПередОкончаниемРедактированияпользователь завершает ввод строкипроверить строку, Отказ оставляет её в редактировании
ПриОкончанииРедактированияввод строки завершён или отменёнпересчитать итоги
ПередУдалением, ПослеУдалениядо и после удаления строкзапретить удаление, пересчитать итоги
ПриИзменениипользователь изменил данные таблицыобщий пересчёт по таблице

С ПриАктивизацииСтроки осторожнее: событие приходит на каждое нажатие стрелки. Если обработчик ходит на сервер, прокрутка тормозит. Серверную часть откладывают обработчиком ожидания:

// Реквизит формы Подсказка (Строка) выведен надписью под таблицей.

&НаКлиенте
Процедура ТоварыПриАктивизацииСтроки(Элемент)

	// Пока пользователь листает стрелками, сервер не вызываем
	ОтключитьОбработчикОжидания("ОбработатьАктивизациюСтроки");
	ПодключитьОбработчикОжидания("ОбработатьАктивизациюСтроки", 0.2, Истина);

КонецПроцедуры

&НаКлиенте
Процедура ОбработатьАктивизациюСтроки()

	СтрокаТаблицы = Элементы.Товары.ТекущиеДанные;
	Если СтрокаТаблицы = Неопределено Тогда
		Подсказка = "";
		Возврат;
	КонецЕсли;

	// На сервер уходит значение из строки, а не сама строка
	Подсказка = ТекстПодсказки(СтрокаТаблицы.Номенклатура);

КонецПроцедуры

&НаСервереБезКонтекста
Функция ТекстПодсказки(Номенклатура)

	// Здесь обычно запрос остатков или цен по позиции
	Если ЗначениеЗаполнено(Номенклатура) И Номенклатура.ПометкаУдаления Тогда
		Возврат "Позиция помечена на удаление";
	КонецЕсли;
	Возврат "";

КонецФункции

Пример: табличная часть «Товары» в форме документа

Модуль формы документа с табличной частью Товары. Код пересчитывает сумму строки, не даёт закончить ввод строки с нулевым количеством, держит итог в реквизите формы, ищет строку по номенклатуре, округляет цены в выделенных строках, сортирует, удаляет пустые строки и сворачивает дубли. Команды создаются на вкладке «Команды» редактора формы, подробнее — в статье о командах формы.

// Модуль формы документа. Управляемая форма, платформа 8.3.
// Табличная часть документа Товары:
//   Номенклатура (СправочникСсылка.Номенклатура), Количество (Число 15,3),
//   Цена (Число 15,2), Сумма (Число 15,2).
// Реквизиты формы: ИтогСумма (Число 15,2),
//   НоменклатураДляПоиска (СправочникСсылка.Номенклатура).
// Элемент Товары: ПутьКДанным = "Объект.Товары", РежимВыделения = Множественный.
// Колонки: ТоварыНоменклатура, ТоварыКоличество, ТоварыЦена, ТоварыСумма.
// Команды: НайтиСтроку, ОкруглитьЦены, СортироватьПоСумме, УдалитьПустые, СвернутьДубли.
// Обработчики событий назначаются в палитре свойств таблицы и колонок.

#Область ОбработчикиСобытийФормы

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

	ПересчитатьИтог(ЭтотОбъект);

КонецПроцедуры

#КонецОбласти

#Область ОбработчикиСобытийЭлементовТаблицыФормыТовары

&НаКлиенте
Процедура ТоварыКоличествоПриИзменении(Элемент)

	ПересчитатьСуммуСтроки(Элементы.Товары.ТекущиеДанные);

КонецПроцедуры

&НаКлиенте
Процедура ТоварыЦенаПриИзменении(Элемент)

	ПересчитатьСуммуСтроки(Элементы.Товары.ТекущиеДанные);

КонецПроцедуры

&НаКлиенте
Процедура ТоварыПередОкончаниемРедактирования(Элемент, НоваяСтрока, ОтменаРедактирования, Отказ)

	// Esc: пользователь отказался от ввода, проверять нечего
	Если ОтменаРедактирования Тогда
		Возврат;
	КонецЕсли;

	СтрокаТаблицы = Элемент.ТекущиеДанные;
	Если СтрокаТаблицы = Неопределено Или СтрокаТаблицы.Количество > 0 Тогда
		Возврат;
	КонецЕсли;

	Индекс = Объект.Товары.Индекс(СтрокаТаблицы);

	Сообщение = Новый СообщениеПользователю;
	Сообщение.Текст = "Количество должно быть больше нуля";
	Сообщение.Поле = "Товары[" + Формат(Индекс, "ЧН=0; ЧГ=0") + "].Количество";
	Сообщение.ПутьКДанным = "Объект";
	Сообщение.Сообщить();

	// Строка остаётся в режиме редактирования
	Отказ = Истина;

КонецПроцедуры

&НаКлиенте
Процедура ТоварыПриОкончанииРедактирования(Элемент, НоваяСтрока, ОтменаРедактирования)

	ПересчитатьИтог(ЭтотОбъект);

КонецПроцедуры

&НаКлиенте
Процедура ТоварыПослеУдаления(Элемент)

	ПересчитатьИтог(ЭтотОбъект);

КонецПроцедуры

#КонецОбласти

#Область ОбработчикиКомандФормы

&НаКлиенте
Процедура НайтиСтроку(Команда)

	Если Не ЗначениеЗаполнено(НоменклатураДляПоиска) Тогда
		ПоказатьПредупреждение(, "Выберите номенклатуру для поиска");
		Возврат;
	КонецЕсли;

	Найденные = Объект.Товары.НайтиСтроки(
		Новый Структура("Номенклатура", НоменклатураДляПоиска));
	Если Найденные.Количество() = 0 Тогда
		ПоказатьПредупреждение(, "В таблице нет такой позиции");
		Возврат;
	КонецЕсли;

	// Где стоит курсор: повторный поиск идёт к следующему совпадению
	ТекущийИндекс = -1;
	Если Элементы.Товары.ТекущаяСтрока <> Неопределено Тогда
		ТекущаяСтрокаТаблицы = Объект.Товары.НайтиПоИдентификатору(Элементы.Товары.ТекущаяСтрока);
		Если ТекущаяСтрокаТаблицы <> Неопределено Тогда
			ТекущийИндекс = Объект.Товары.Индекс(ТекущаяСтрокаТаблицы);
		КонецЕсли;
	КонецЕсли;

	НужнаяСтрока = Найденные[0]; // после последнего совпадения - снова первое
	Для Каждого СтрокаТаблицы Из Найденные Цикл
		Если Объект.Товары.Индекс(СтрокаТаблицы) > ТекущийИндекс Тогда
			НужнаяСтрока = СтрокаТаблицы;
			Прервать;
		КонецЕсли;
	КонецЦикла;

	Элементы.Товары.ТекущаяСтрока = НужнаяСтрока.ПолучитьИдентификатор();
	ТекущийЭлемент = Элементы.Товары;

КонецПроцедуры

&НаКлиенте
Процедура ОкруглитьЦены(Команда)

	Выделенные = Элементы.Товары.ВыделенныеСтроки;
	Если Выделенные.Количество() = 0 Тогда
		ПоказатьПредупреждение(, "Выделите строки");
		Возврат;
	КонецЕсли;

	// В массиве идентификаторы, а не сами строки
	Для Каждого Идентификатор Из Выделенные Цикл
		СтрокаТаблицы = Объект.Товары.НайтиПоИдентификатору(Идентификатор);
		СтрокаТаблицы.Цена = Окр(СтрокаТаблицы.Цена, 0);
		ПересчитатьСуммуСтроки(СтрокаТаблицы);
	КонецЦикла;

	ПересчитатьИтог(ЭтотОбъект);
	Модифицированность = Истина;

КонецПроцедуры

&НаКлиенте
Процедура СортироватьПоСумме(Команда)

	// Идентификатор строки переживает сортировку, индекс - нет
	ИдентификаторТекущей = Элементы.Товары.ТекущаяСтрока;

	// Метод доступен на клиенте, сервер платформа вызывает сама
	Объект.Товары.Сортировать("Сумма Убыв");

	Если ИдентификаторТекущей <> Неопределено Тогда
		Элементы.Товары.ТекущаяСтрока = ИдентификаторТекущей;
	КонецЕсли;
	Модифицированность = Истина;

КонецПроцедуры

&НаКлиенте
Процедура УдалитьПустые(Команда)

	// Идём с конца: после удаления следующие строки сдвигаются вверх
	Индекс = Объект.Товары.Количество() - 1;
	Пока Индекс >= 0 Цикл
		СтрокаТаблицы = Объект.Товары[Индекс];
		Если Не ЗначениеЗаполнено(СтрокаТаблицы.Номенклатура)
			Или СтрокаТаблицы.Количество = 0 Тогда
			Объект.Товары.Удалить(Индекс);
			Модифицированность = Истина;
		КонецЕсли;
		Индекс = Индекс - 1;
	КонецЦикла;

	ПересчитатьИтог(ЭтотОбъект);

КонецПроцедуры

&НаКлиенте
Процедура СвернутьДубли(Команда)

	СвернутьДублиНаСервере();
	Модифицированность = Истина;

КонецПроцедуры

#КонецОбласти

#Область СлужебныеПроцедурыИФункции

&НаСервере
Процедура СвернутьДублиНаСервере()

	// Выгрузить и Загрузить работают только на сервере
	Таблица = Объект.Товары.Выгрузить();
	Таблица.Свернуть("Номенклатура, Цена", "Количество, Сумма");
	Объект.Товары.Загрузить(Таблица);

	ПересчитатьИтог(ЭтотОбъект);

КонецПроцедуры

&НаКлиенте
Процедура ПересчитатьСуммуСтроки(СтрокаТаблицы)

	Если СтрокаТаблицы = Неопределено Тогда
		Возврат;
	КонецЕсли;
	СтрокаТаблицы.Сумма = СтрокаТаблицы.Количество * СтрокаТаблицы.Цена;

КонецПроцедуры

&НаКлиентеНаСервереБезКонтекста
Процедура ПересчитатьИтог(Форма)

	Итог = 0;
	Для Каждого СтрокаТаблицы Из Форма.Объект.Товары Цикл
		Итог = Итог + СтрокаТаблицы.Сумма;
	КонецЦикла;
	Форма.ИтогСумма = Итог;

КонецПроцедуры

#КонецОбласти

Разбор ключевых строк

  • ПересчитатьИтог(ЭтотОбъект) — процедура &НаКлиентеНаСервереБезКонтекста получает форму параметром и вызывается и на сервере, и на клиенте без лишнего серверного вызова.
  • В ТоварыПередОкончаниемРедактирования первым делом проверяется ОтменаРедактирования. Пользователь нажал Esc — проверять нечего, а Отказ не дал бы ему выйти из строки.
  • Сообщение.Поле вида Товары[0].Количество вместе с ПутьКДанным = "Объект" привязывает сообщение к ячейке. В скобках индекс с нуля, а не НомерСтроки. Формат(Индекс, "ЧН=0; ЧГ=0"): без ЧН=0 ноль превратится в пустую строку, без ЧГ=0 индекс 1000 получит разделитель групп.
  • СвернутьДублиНаСервере: Выгрузить даёт настоящую таблицу значений с методом Свернуть. В его параметрах перечислите все колонки, которые нужно сохранить, остальные пропадут.
  • Модифицированность = Истина: программное изменение данных форму изменённой не помечает, и без этой строки платформа при закрытии не спросит о записи.

Типичные ошибки

  • «Значение не является значением объектного типа (Количество)». Код читает Элементы.Товары.ТекущиеДанные.Количество, а текущей строки нет: таблица пустая или курсор не стоит на строке. Сначала проверяйте ТекущиеДанные = Неопределено.
  • «Метод объекта не обнаружен (Выгрузить)», «Тип не определен (ТаблицаЗначений)», «Тип не определен (Запрос)». Серверные вещи попали в клиентскую процедуру. Выгрузку, загрузку, работу с ТаблицаЗначений и запросы переносите в процедуру с &НаСервере.
  • «Поле объекта не обнаружено (Скидка)». Код читает ТекущиеДанные.Скидка, а колонки нет в данных формы: её не вывели в таблицу и не отметили флажком «Использовать всегда». Выведите колонку, хотя бы невидимой, или поставьте флажок.
  • На сервер передают саму строку. Серверный метод с директивой &НаСервере и так получает данные формы: передайте ему ТекущаяСтрока и найдите строку через НайтиПоИдентификатору, изменения вернутся в форму. Если нужно только значение из строки, передайте его в метод &НаСервереБезКонтекста.
  • Удаление в цикле «Для Каждого». Платформа ошибку не выдаст, но после удаления следующая строка встаёт на место удалённой, и цикл её пропускает: из двух пустых строк подряд одна останется. Удаляйте с конца по индексу или сначала соберите строки через НайтиСтроки.
  • В ТекущаяСтрока записан индекс. Ошибки нет, идентификатор ведь тоже число, но курсор встаёт на чужую строку или никуда. Для коллекций нужен ПолучитьИдентификатор(), для динамического списка — ключ строки.
  • Итог не пересчитался. События таблицы и колонок вызываются на действия пользователя. После изменения строк кодом пересчёт запускайте сами.

Частые вопросы

Как добавить строку в таблицу формы программно?

Для заполнения — Объект.Товары.Добавить() или Вставить(Индекс). Если строку должен дозаполнить пользователь, вызовите Элементы.Товары.ДобавитьСтроку(): это то же, что кнопка «Добавить».

Как скрыть колонку или запретить её редактирование?

Колонка — это элемент формы: Элементы.ТоварыЦена.Видимость = Ложь или Элементы.ТоварыЦена.ТолькоПросмотр = Истина. Если закрыть ячейки нужно не во всей колонке, а в отдельных строках, используют условное оформление формы, а не код в ПриАктивизацииСтроки.

Как вывести итог колонки в подвал таблицы?

Включите у таблицы свойство «Подвал», а у колонки заполните ПутьКДаннымПодвала. Для числовой колонки табличной части подходит путь вида Объект.Товары.ИтогСумма, итог платформа считает сама. Можно указать и обычный реквизит формы, как ИтогСумма в примере, — тогда пересчёт на вашей стороне.

Чем таблица формы отличается от таблицы значений?

ТаблицаЗначений — объект встроенного языка, на тонком клиенте его нет. Таблица формы — элемент, который показывает коллекцию данных формы. Реквизит типа ТаблицаЗначений хранится в форме как ДанныеФормыКоллекция, полноценную таблицу значений из него получают на сервере через РеквизитФормыВЗначение. Подробнее — в статье «Таблица значений на форме 1С».

Когда проще заказать

Если нужно доработать таблицу в форме типового документа — добавить колонки, пересчёты, проверки строк, подбор — и при этом не снимать конфигурацию с поддержки, такие правки делают расширением. Опишите, что должно происходить в таблице, и разместите задачу — оценка бесплатная, ответ в течение рабочего дня. Все направления работ — на странице услуг по доработке 1С.

По теме

Не хотите разбираться сами?

Адаптируем это решение под вашу базу. Оценка бесплатно.

Оставить задачу

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


1С, 1С:Предприятие — товарные знаки ООО «1С». Сайт не является официальным представительством фирмы «1С» и не аффилирован с ней.