Как реализовать две табличные части в одном документе в 1С 7.7

Программист 1С v7.7 Управленческий учет
← На главную

В платформе «1С:Предприятие 7.7» на уровне ядра заложено жесткое архитектурное ограничение: любой документ может содержать только одну физическую табличную часть (ТЧ). Однако в реальной практике автоматизации учета — например, при оформлении выдачи спецодежды и одновременного расчета компенсации за неизрасходованные нормы — бизнес-логика требует наличия двух и более независимых таблиц на форме одного документа.

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

Постановка задачи: почему одной таблицы бывает мало

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

  1. На первой вкладке («Выдача») отражаются фактически выданные вещи, находящиеся в эксплуатации (с указанием конкретной номенклатуры, даты выдачи, нормативного срока износа и документа-основания).
  2. На второй вкладке («Компенсация») рассчитываются вещи, которые сотрудник должен был получить по нормам, но не получил. За них предприятие выплачивает денежную компенсацию (здесь требуются дополнительные поля: цена, сумма компенсации, количество к зачету).

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


Способ 1. Визуальное разделение одной физической ТЧ по признаку строки (Метод псевдо-ТЧ)

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

Рассмотрим по шагам алгоритм реализации этого метода:

  1. В метаданных существующей табличной части документа создаем служебный реквизит, например, НомТЧ (тип: Число, длина: 1). Этот реквизит будет служить маркером: значение "1" будет соответствовать строкам первой вкладки («Выдача»), значение "2" — строкам второй вкладки («Компенсация»).
  2. На форму документа добавляем стандартный элемент диалога «Закладки».
  3. Размещаем на форме штатную визуальную таблицу документа, но программно управляем видимостью ее колонок и фильтрацией строк при переключении закладок.

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


Процедура ПриВыбореЗакладки(НомерЗакладки, ЗначениеЗакладки)
    // Управляем видимостью колонок в зависимости от выбранной вкладки
    Если ЗначениеЗакладки = "Выдача" Тогда
        Форма.Цена.Видимость(0);
        Форма.Сумма.Видимость(0);
        Форма.ДокументВыдачи.Видимость(1);
    ИначеЕсли ЗначениеЗакладки = "Компенсация" Тогда
        Форма.Цена.Видимость(1);
        Форма.Сумма.Видимость(1);
        Форма.ДокументВыдачи.Видимость(0);
    КонецЕсли;
    
    // Активизируем фильтрацию строк на форме
    // Применяем отбор строк по значению реквизита НомТЧ
    УстановитьФильтрСтрок(ЗначениеЗакладки);
КонецПроцедуры

Основной минус данного подхода заключается в том, что стандартный механизм фильтрации строк табличной части в 1С 7.7 (через встроенный метод ВидыОтбора или визуальные хаки) работает нестабильно и имеет ограничения по производительности на больших объемах данных. Поэтому разработчики часто модернизируют этот метод с использованием виртуальной Таблицы Значений (ТЗ).


Способ 2. Использование виртуальных Таблиц Значений на форме документа

Это более продвинутый и профессиональный вариант первого метода. Вместо прямой работы со строками реальной ТЧ документа на форму выводятся независимые элементы диалога типа «ТаблицаЗначений» (например, ТЗ_Выдача и ТЗ_Компенсация).

Проанализируем детально схему работы этой технологии:

  1. При открытии документа (в предопределенной процедуре ПриОткрытии) мы считываем данные из единственной реальной ТЧ документа.
  2. Программно распределяем эти строки по двум независимым объектам ТаблицаЗначений в соответствии со значением реквизита-маркера НомТЧ.
  3. Пользователь видит на вкладках независимые таблицы, может интерактивно добавлять, удалять и редактировать в них строки.
  4. При записи документа (в процедуре ПриЗаписи) мы полностью очищаем реальную табличную часть документа и программно «сливаем» данные из обеих экранных таблиц обратно в ТЧ, устанавливая для каждой строки соответствующий индекс НомТЧ.

Разберем пример программного кода для реализации этого механизма. Сначала напишем процедуру инициализации и заполнения экранных таблиц при открытии формы:


Процедура ПриОткрытии()
    // Создаем колонки для первой таблицы значений
    ТЗ_Выдача.НоваяКолонка("Номенклатура", "Справочник.Номенклатура");
    ТЗ_Выдача.НоваяКолонка("Количество", "Число", 10, 2);
    ТЗ_Выдача.НоваяКолонка("ДатаВыдачи", "Дата");
    
    // Создаем колонки для второй таблицы значений
    ТЗ_Компенсация.НоваяКолонка("Номенклатура", "Справочник.Номенклатура");
    ТЗ_Компенсация.НоваяКолонка("Количество", "Число", 10, 2);
    ТЗ_Компенсация.НоваяКолонка("Цена", "Число", 15, 2);
    ТЗ_Компенсация.НоваяКолонка("Сумма", "Число", 15, 2);
    
    // Выгружаем данные из физической ТЧ документа в экранные ТЗ
    ВыбратьСтроки();
    Пока ПолучитьСтроку() = 1 Цикл
        Если НомТЧ = 1 Тогда
            ТЗ_Выдача.НоваяСтрока();
            ТЗ_Выдача.Номенклатура = Номенклатура;
            ТЗ_Выдача.Количество = Количество;
            ТЗ_Выдача.ДатаВыдачи = ДатаВыдачи;
        ИначеЕсли НомТЧ = 2 Тогда
            ТЗ_Компенсация.НоваяСтрока();
            ТЗ_Компенсация.Номенклатура = Номенклатура;
            ТЗ_Компенсация.Количество = Количество;
            ТЗ_Компенсация.Цена = Цена;
            ТЗ_Компенсация.Сумма = Сумма;
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Теперь рассмотрим процедуру свертки и обратной записи данных при сохранении документа пользователем:


Процедура ПриЗаписи()
    // Очищаем физическую табличную часть документа перед перезаписью
    УдалитьСтроки();
    
    // Переносим строки из первой таблицы (Выдача)
    ТЗ_Выдача.ВыбратьСтроки();
    Пока ТЗ_Выдача.ПолучитьСтроку() = 1 Цикл
        НоваяСтрока();
        НомТЧ = 1;
        Номенклатура = ТЗ_Выдача.Номенклатура;
        Количество = ТЗ_Выдача.Количество;
        ДатаВыдачи = ТЗ_Выдача.ДатаВыдачи;
    КонецЦикла;
    
    // Переносим строки из второй таблицы (Компенсация)
    ТЗ_Компенсация.ВыбратьСтроки();
    Пока ТЗ_Компенсация.ПолучитьСтроку() = 1 Цикл
        НоваяСтрока();
        НомТЧ = 2;
        Номенклатура = ТЗ_Компенсация.Номенклатура;
        Количество = ТЗ_Компенсация.Количество;
        Цена = ТЗ_Компенсация.Цена;
        Сумма = ТЗ_Компенсация.Сумма;
    КонецЦикла;
КонецПроцедуры

Преимущества метода виртуальных ТЗ:

Недостатки метода:


Способ 3. Использование подчиненного служебного справочника

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

Для реализации этого метода выполним следующие шаги:

  1. Создаем в конфигураторе новый подчиненный справочник, например, СоставКомпенсацииДокумента. В качестве его владельца указываем тип Документ.СписаниеИВыдачаВещей.
  2. Реквизитами этого справочника делаем те поля, которые планировалось использовать во второй табличной части (Номенклатура, Количество, Цена, Сумма).
  3. На форме документа на первой вкладке оставляем штатную ТЧ (для «Выдачи»). На второй вкладке размещаем стандартную Таблицу Значений (для «Компенсации»), которая при открытии документа заполняется данными из подчиненного справочника посредством позиционирования по владельцу (текущему документу).
  4. При записи документа мы в одной транзакции обновляем элементы подчиненного справочника в соответствии с изменениями, внесенными пользователем на второй вкладке.

Посмотрим, как выглядит программная логика считывания данных из подчиненного справочника при открытии документа:


Процедура ЗагрузитьДанныеИзСправочника()
    ТЗ_Компенсация.УдалитьСтроки();
    
    Спр = СоздатьОбъект("Справочник.СоставКомпенсацииДокумента");
    // Устанавливаем отбор по владельцу - текущему документу
    Спр.ИспользоватьВладельца(ТекущийДокумент());
    Спр.ВыбратьЭлементы();
    Пока Спр.ПолучитьЭлемент() = 1 Цикл
        ТЗ_Компенсация.НоваяСтрока();
        ТЗ_Компенсация.Номенклатура = Спр.Номенклатура;
        ТЗ_Компенсация.Количество = Спр.Количество;
        ТЗ_Компенсация.Цена = Спр.Цена;
        ТЗ_Компенсация.Сумма = Спр.Сумма;
        // Сохраняем ссылку на элемент для последующей быстрой перезаписи
        ТЗ_Компенсация.СсылкаНаЭлемент = Спр.ТекущийЭлемент();
    КонецЦикла;
КонецПроцедуры

При записи документа мы синхронизируем изменения. Если строка в ТЗ новая — создаем элемент справочника, если изменена — обновляем существующий, если удалена — удаляем элемент справочника.

Почему этот метод считается одним из лучших?


Способ 4. Сериализация таблицы значений в строку неограниченной длины

Этот метод часто используется как быстрое "обходное" решение (workaround), когда нет возможности или желания менять структуру метаданных конфигурации путем добавления новых таблиц или справочников.

Идея метода заключается в следующем: вся вторая табличная часть на форме верстается как обычная экранная «ТаблицаЗначений». Но хранится она в базе данных внутри одного-единственного текстового реквизита шапки документа с типом данных «Строка неограниченной длины».

Для реализации используются мощные встроенные функции платформы 1С 7.7: ЗначениеВСтрокуВнутр() и ЗначениеИзСтрокиВнутр(). Они позволяют преобразовывать сложные объекты платформы (включая таблицы значений со всеми строками, колонками, типами данных и ссылками) в одну системную строку специального формата и восстанавливать их обратно.

Разберем, как выглядит этот код на практике. Запись таблицы значений в текстовый реквизит шапки ХранилищеТЧ2 при сохранении документа:


Процедура ПриЗаписи()
    // Сериализуем экранную таблицу компенсаций в системную строку
    ХранилищеТЧ2 = ЗначениеВСтрокуВнутр(ТЗ_Компенсация);
КонецПроцедуры

И обратное чтение (десериализация) данных при открытии формы документа:


Процедура ПриОткрытии()
    Если ПустаяСтрока(ХранилищеТЧ2) = 0 Тогда
        // Восстанавливаем полноценную таблицу значений со всеми данными из строки
        ТЗ_Компенсация = ЗначениеИзСтрокиВнутр(ХранилищеТЧ2);
    Иначе
        // Если документ новый и строка пуста - инициализируем структуру таблицы вручную
        ТЗ_Компенсация.НоваяКолонка("Номенклатура", "Справочник.Номенклатура");
        ТЗ_Компенсация.НоваяКолонка("Количество", "Число", 10, 2);
    КонецЕсли;
КонецПроцедуры

Важные технологические риски при использовании сериализации:

  1. Нарушение ссылочной целостности базы данных: Строка неограниченной длины хранит внутренние уникальные идентификаторы (ID) объектов (например, конкретной одежды или сотрудника) в виде обычного текста. Если пользователь физически удалит товарную позицию из справочника, система 1С 7.7 не "увидит" ссылку внутри текстовой строки и позволит совершить удаление. При последующем открытии документа в таблице компенсаций отобразится пустая строка со значением <Объект не найден>.
  2. Ограничения файловой версии (DBF): В файловом варианте базы данных все строки неограниченной длины всех документов и справочников физически пишутся в один общий файл — 1SBLOB.dbf. При высокой интенсивности работы пользователей этот файл начинает лавинообразно увеличиваться в размерах, что нередко приводит к критическим сбоям СУБД, повреждению таблиц и зависанию транзакций.
  3. Невозможность построения прямых отчетов: Вы не сможете сделать стандартный 1С-запрос к содержимому второй табличной части, так как для СУБД это просто зашифрованный нечитаемый текст. Чтобы построить отчет, вам придется программно перебирать все документы выборкой, открывать их и расшифровывать строку обратно в ТЗ, что крайне медленно.

Способ 5. Реализация через подчиненный скрытый документ (Архитектура ЗиК 7.7)

Этот сложный, но проверенный временем подход использовался самой фирмой «1С» в крупных тиражных решениях, таких как «Зарплата и Кадры 7.7» (для разделения сложных расчетов по отпускам и больничным листам).

Суть схемы состоит в следующем: в системе создаются два самостоятельных документа:

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

Чтобы подчиненные документы не путали операторов базы данных, их программно исключают из отображения во всех общих журналах документов конфигурации.


Сравнительный анализ решений: какую технологию выбрать?

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

Критерий сравнения Метод псевдо-ТЧ (Способ 1, 2) Подчиненный справочник (Способ 3) Сериализация в строку (Способ 4) Подчиненный документ (Способ 5)
Сложность программного кода Средняя Средняя Очень низкая (простая строка) Высокая (синхронизация транзакций)
Ссылочная целостность БД Да (полная штатная) Да (полная штатная) Нет (риск удаления объектов) Да (полная штатная)
Возможность быстрых отчетов Да (по общей ТЧ с фильтром) Да (очень удобно по справочнику) Нет (требуется парсинг строк) Да (по регистрам подчиненного дока)
Влияние на размер базы данных Минимальное Минимальное Высокое (раздувание 1SBLOB.dbf) Среднее (создание новых объектов)

Рекомендации по выбору решения

Для бизнес-задачи интеграции учета выдачи вещей и компенсаций на платформе 1С 7.7 наиболее сбалансированным решением является Способ №3 (Использование подчиненного справочника) или Способ №2 (Виртуальные ТЗ на форме).

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

← На главную