Как восстановить значения реквизитов в 1С после их переноса из шапки в табличную часть и изменения типа?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

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

Выясняем причину: почему «слетают» значения на форме?

Давайте проанализируем, как управляемая форма 1С работает с данными. Когда мы размещаем элемент формы (например, поле ввода или поле выбора) и связываем его через свойство ПутьКДанным с реквизитом первой строки табличной части (например, Объект.ИмяТабличнойЧасти[0].ИмяРеквизита), платформа ожидает, что в этой табличной части существует хотя бы одна строка.

В новых документах, где пользователи заполняют табличную часть с нуля, всё работает корректно. Но в старых документах, созданных до обновления конфигурации, новая табличная часть абсолютно пуста — в ней нет ни одной строки. Платформа пытается прочитать данные из несуществующей строки с индексом 0, возвращает пустоту и отображает на форме незаполненное поле. При этом старые данные никуда не пропали: они продолжают храниться в старом реквизите шапки документа в таблице базы данных (если этот реквизит еще не был физически удален из метаданных).

Второй аспект проблемы — изменение типа данных с Число на Строка. Для платформы 1С число 0 и строка "0" — это принципиально разные типы данных. Если в базе записано число, а элемент формы настроен на отображение строки, возникнет конфликт типов, из-за которого значение также не отобразится в интерфейсе.

Шаг 1. Написание обработки для переноса данных из шапки в ТЧ

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

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


// Создаем запрос для выборки документов, у которых старый реквизит заполнен,
// а новая табличная часть еще не содержит строк.
Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Док.Ссылка КАК Ссылка,
    |	Док.СтарыйРеквизитЧисло КАК СтарыйРеквизитЧисло
    |ИЗ
    |	Документ.ИмяВашегоДокумента КАК Док
    |ГДЕ
    |	Док.СтарыйРеквизитЧисло <> 0
    |	И НЕ Док.Ссылка В (
    |		ВЫБРАТЬ РАЗЛИЧНЫЕ
    |			ТЧ.Ссылка
    |		ИЗ
    |			Документ.ИмяВашегоДокумента.ИмяТабличнойЧасти КАК ТЧ
    |	)";

Выборка = Запрос.Выполнить().Выбрать();

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

Обратите внимание на использование параметра "ЧГ=0" в функции Формат. Если у вас в качестве старых значений использовались числа (например, 1000, 2000), стандартное преобразование в строку может добавить неразрывные пробелы в качестве разделителей групп разрядов (получится "1 000" вместо "1000"). Данный параметр гарантирует получение "чистой" строки без пробелов.

Шаг 2. Корректное преобразование значений по категориям

Часто числовые значения в старых реквизитах использовались как условные коды категорий (например: 0 — "Проект", 1 — "В работе", 2 — "Выполнено"). Если при переходе на строковый тип вы хотите уйти от числовых кодов и записывать в базу понятное текстовое представление, алгоритм переноса данных внутри цикла обработки следует модифицировать.

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


// Сопоставляем числовой код текстовой категории
Если Выборка.СтарыйРеквизитЧисло = 0 Тогда
    НоваяСтрока.НовыйРеквизитСтрока = "Проект";
ИначеЕсли Выборка.СтарыйРеквизитЧисло = 1 Тогда
    НоваяСтрока.НовыйРеквизитСтрока = "В работе";
ИначеЕсли Выборка.СтарыйРеквизитЧисло = 2 Тогда
    НоваяСтрока.НовыйРеквизитСтрока = "Выполнено";
Иначе
    НоваяСтрока.НовыйРеквизитСтрока = "Не определено";
КонецЕсли;

Такой подход повысит читаемость данных непосредственно в базе данных и упростит последующее построение отчетов.

Шаг 3. Решение проблемы с отображением синонимов в полях выбора

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

Если реквизит имеет тип Строка, элементы списка выбора также должны иметь строго строковые значения. Разберем, как правильно программно инициализировать список выбора на форме документа:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Получаем элемент управления на форме
    ПолеВыбора = Элементы.ИмяТабличнойЧастиНовыйРеквизитСтрока;
    
    // Очищаем стандартный список
    ПолеВыбора.СписокВыбора.Очистить();
    
    // Добавляем строковые значения (первый параметр) и их текстовые представления для пользователей (второй параметр)
    ПолеВыбора.СписокВыбора.Добавить("0", "Проект");
    ПолеВыбора.СписокВыбора.Добавить("1", "В работе");
    ПолеВыбора.СписокВыбора.Добавить("2", "Выполнено");
    
КонецПроцедуры

Если типы данных совпадают (в базе сохраняется строка "0", и в списке выбора значение имеет тип Строка со значением "0"), управляемая форма автоматически подставит правильное текстовое представление ("Проект"), и пользователь не увидит сырых данных.

Альтернативное решение: Использование Условного оформления

Если по какой-то причине вы решили оставить тип реквизита числовым (Число), но хотите, чтобы на форме вместо цифр 0, 1, 2 всегда красовался красивый текст, лучшим решением будет использование механизма Условного оформления управляемой формы. Этот способ хорош тем, что он вообще не требует написания программного кода.

Выполним настройку по шагам:

  1. Откройте форму документа в конфигураторе, перейдите на вкладку «Условное оформление» (в панели свойств формы).
  2. Добавьте новое правило оформления.
  3. В поле «Оформление» найдите параметр Текст и укажите значение, которое должен видеть пользователь (например, Проект).
  4. В поле «Условие» (Отбор) добавьте новое условие: Объект.ТабличнаяЧасть.НовыйРеквизит Равно 0.
  5. В поле «Оформляемые поля» выберите элемент формы, отображающий ваш реквизит в табличной части.
  6. Повторите эти шаги для остальных числовых значений (для 1 — "В работе", для 2 — "Выполнено").

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

← На главную