Разработчики, переходящие на платформу 1С 7.7 с более современных версий (например, 1С 8.3), часто сталкиваются с серьезным архитектурным ограничением: справочники в 1С 7.7 не поддерживают табличные части на уровне метаданных. Нативно табличные части в этой версии платформы существуют только у документов.
Тем не менее, задача хранить списки связанных данных (например, список оказываемых услуг для контрагента, перечень контактных лиц, спецификации номенклатуры) возникает регулярно. В рамках данной статьи мы подробно разберем все существующие и проверенные временем методы обхода этого ограничения. Мы рассмотрим как стандартные возможности платформы, так и профессиональные решения с использованием внешних компонент.
Это самый популярный, надежный и архитектурно правильный способ, который используется в большинстве типовых конфигураций (например, связка справочников «Контрагенты» и «Договоры» в «1С:Бухгалтерии 7.7»).
Суть метода заключается в создании дополнительного справочника, который в метаданных объявляется подчиненным основному справочнику. Для удобства пользователя данные этого подчиненного справочника выводятся прямо на форму элемента основного справочника с помощью элемента диалога Таблица Значений (ТЗ).
Разберем по шагам, как это реализовать:
УслугиКонтрагентов).Контрагенты).Услуга с типом «Справочник.Номенклатура», Цена, Количество, Сумма).ТЗ_Услуги.Нам необходимо написать код, который при открытии элемента справочника выберет все подчиненные элементы и загрузит их в нашу таблицу на форме. Для этого в модуле формы элемента основного справочника пишем процедуру:
Процедура ЗаполнитьТабличнуюЧасть()
// Очищаем ТЗ перед заполнением
ТЗ_Услуги.Очистить();
// Создаем колонки в нашей таблице на форме
ТЗ_Услуги.НоваяКолонка("Услуга", "Справочник.Номенклатура");
ТЗ_Услуги.НоваяКолонка("Количество", "Число");
ТЗ_Услуги.НоваяКолонка("Цена", "Число");
ТЗ_Услуги.НоваяКолонка("Сумма", "Число");
// Скрытая колонка для хранения ссылки на сам подчиненный элемент
ТЗ_Услуги.НоваяКолонка("ЭлементСсылка", "Справочник.УслугиКонтрагентов");
// Проверяем, записан ли текущий элемент (у нового элемента не может быть подчиненных)
Если Выбран() = 0 Тогда
Возврат;
КонецЕсли;
// Создаем объект подчиненного справочника
СпрПодч = СоздатьОбъект("Справочник.УслугиКонтрагентов");
// Устанавливаем фильтр по владельцу
СпрПодч.ИспользоватьВладельца(ТекущийЭлемент());
СпрПодч.ВыбратьЭлементы();
// Заполняем ТЗ данными
Пока СпрПодч.ПолучитьЭлемент() = 1 Цикл
ТЗ_Услуги.НоваяСтрока();
ТЗ_Услуги.Услуга = СпрПодч.Услуга;
ТЗ_Услуги.Количество = СпрПодч.Количество;
ТЗ_Услуги.Цена = СпрПодч.Цена;
ТЗ_Услуги.Сумма = СпрПодч.Сумма;
ТЗ_Услуги.ЭлементСсылка = СпрПодч.ТекущийЭлемент();
КонецЦикла;
КонецПроцедуры
Добавляем вызов нашей процедуры в предопределенный обработчик событий формы:
Процедура ПриОткрытии()
ЗаполнитьТабличнуюЧасть();
КонецПроцедуры
Стандартная Таблица Значений в 1С 7.7 не позволяет пользователю напрямую редактировать ячейки «на месте» так же легко, как в 1С 8. Чтобы организовать редактирование, мы можем использовать двойной клик по строке ТЗ для открытия формы подчиненного элемента:
Процедура ПриВыбореСтрокиТЗ()
// Проверяем, что кликнули по заполненной строке
Если ТЗ_Услуги.ТекущаяСтрока() > 0 Тогда
// Открываем форму подчиненного элемента для редактирования
ОткрытьФорму(ТЗ_Услуги.ЭлементСсылка);
// После закрытия формы редактирования обновляем данные на форме
ЗаполнитьТабличнуюЧасть();
КонецЕсли;
КонецПроцедуры
Чтобы связать эту процедуру с двойным кликом по таблице, в свойствах элемента диалога ТЗ_Услуги в поле «Формула» пишем имя нашей процедуры: ПриВыбореСтрокиТЗ().
Это оригинальный и очень удобный метод, упомянутый опытными разработчиками на форуме. Он позволяет использовать полноценную встроенную табличную часть документа, полностью избавив программиста от ручного проектирования интерфейса ТЗ на форме.
Суть схемы: Мы создаем подчиненный справочник. Единственным важным реквизитом этого справочника является ссылка на документ (например, документ ОказанныеУслуги, у которого есть штатная табличная часть). При попытке открыть или создать элемент подчиненного справочника система перехватывает это событие, программно открывает связанный документ, а открытие самого справочника отменяет.
Рассмотрим детальную реализацию этого алгоритма:
ОказанныеУслуги. Оформляем в нем табличную часть со всеми необходимыми реквизитами (услуга, количество, цена, сумма и т.д.). В шапке документа делаем реквизит Контрагент.СвязанныеДокументы, подчиненный справочнику Контрагенты. Добавляем в него реквизит ДокументСсылка (тип «Документ.ОказанныеУслуги»).СвязанныеДокументы пишем следующий код в процедуре ПриОткрытии():
Процедура ПриОткрытии()
// Если это новый элемент справочника, которого еще нет в базе
Если Выбран() = 0 Тогда
// Создаем новый документ программно
ДокОбъект = СоздатьОбъект("Документ.ОказанныеУслуги");
ДокОбъект.Новый();
ДокОбъект.Контрагент = Владелец; // Передаем владельца-контрагента в документ
// Записываем документ, чтобы получить на него ссылку
ДокОбъект.Записать();
// Записываем ссылку на документ в наш подчиненный справочник
ДокументСсылка = ДокОбъект.ТекущийДокумент();
Записать();
КонецЕсли;
// Открываем форму связанного документа для редактирования его ТЧ
ОткрытьФорму(ДокументСсылка);
// Отменяем открытие формы самого элемента подчиненного справочника!
СтатусВозврата(0);
КонецПроцедуры
При таком подходе пользователь видит привычную форму документа со всеми возможностями авторасчета сумм, подбора номенклатуры и проведения, при этом вся цепочка данных жестко привязана к конкретному контрагенту через подчиненный справочник.
Если вам не требуется строить отчеты по элементам этой «табличной части» с помощью прямых запросов или стандартных отчетов, а данные нужны только для просмотра внутри конкретного элемента справочника, можно применить метод сериализации.
Для этого в структуре основного справочника создается всего один реквизит, например, ХранилищеТЧ с типом Строка (неограниченной длины). На форме элемента размещается визуальная Таблица Значений ТЗ_Экран.
Проанализируем программную реализацию этого механизма:
// Процедура восстанавливает ТЗ из текстовой строки при открытии элемента
Процедура ПриОткрытии()
ТЗ = СоздатьОбъект("ТаблицаЗначений");
Если ПустаяСтрока(ХранилищеТЧ) = 0 Тогда
// Десериализация строки во внутренний объект 1С
ТЗ = ЗначениеИзСтрокиВнутр(ХранилищеТЧ);
Иначе
// Инициализируем структуру, если данных еще нет
ТЗ.НоваяКолонка("Услуга", "Справочник.Номенклатура");
ТЗ.НоваяКолонка("Количество", "Число");
ТЗ.НоваяКолонка("Цена", "Число");
КонецЕсли;
// Выгружаем восстановленную таблицу на форму для отображения пользователю
ТЗ.Выгрузить(ТЗ_Экран);
КонецПроцедуры
// Процедура сохраняет данные ТЗ обратно в текстовый реквизит перед записью элемента
Процедура ПриЗаписи()
ТЗ = СоздатьОбъект("ТаблицаЗначений");
// Забираем текущие данные с экрана
ТЗ_Экран.Выгрузить(ТЗ);
// Сериализуем объект ТЗ в системную строку 1С и пишем в реквизит справочника
ХранилищеТЧ = ЗначениеВСтрокуВнутр(ТЗ);
КонецПроцедуры
Преимущества метода: Высочайшая скорость разработки. Нет необходимости создавать новые справочники и забивать метаданные конфигурации. Данные всегда перемещаются и копируются вместе с элементом справочника.
Недостатки: Информация хранится в закодированном текстовом виде внутри системного формата 1С. Получить к ней доступ через SQL-запросы или стандартные отчеты без предварительного открытия каждого элемента невозможно.
Если вы хотите сделать работу пользователя с имитацией табличной части максимально комфортной, стандартных средств 1С 7.7 может не хватить. Для этого профессиональные разработчики используют внешние компоненты, которые существенно расширяют возможности платформы.
Позволяет осуществлять интерактивное редактирование ячеек Таблицы Значений прямо на форме, без открытия дополнительных модальных окон. С ее помощью вы можете раскрашивать строки (например, выделять просроченные услуги красным цветом), динамически управлять доступностью колонок для редактирования, а также отслеживать нажатия клавиш клавиатуры прямо в ТЗ.
Предоставляет мощнейший механизм под названием «Поставщик данных». Если в подчиненном справочнике содержатся десятки тысяч строк, стандартный перебор элементов через ВыбратьЭлементы() будет тормозить систему. С помощью класса ПоставщикДанных и механизма прямых SQL-запросов данные подчиненного справочника загружаются в экранную ТЗ мгновенно, минуя объектную модель 1С. Кроме того, это позволяет реализовать удобную иерархическую структуру «Дерево+Таблица» прямо на форме справочника.
Выбор конкретного метода реализации табличной части зависит от бизнес-требований к вашей задаче: