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