Смена типа реквизита через расширение: что разрешает платформа и как не потерять данные
Содержание
Изменить тип реквизита в расширении 1С можно только у реквизита, который создан в самом расширении: открываете расширение в конфигураторе, меняете свойство «Тип» и обновляете конфигурацию базы данных. У реквизита основной конфигурации тип через расширение не меняется: заимствованный объект берёт тип из основной конфигурации. Там работает обходной путь — новый реквизит нужного типа в расширении плюс перенос данных.
Какой вариант выбрать, зависит от того, чей реквизит. Своё поле расширения — правка свойства за пять минут. Чужое поле типовой конфигурации — небольшой проект: новый реквизит, обработка переноса, замена на формах и в коде. Ниже оба варианта по шагам.
Чей это реквизит: что расширение может и не может поменять
Первым делом определите происхождение реквизита. Откройте расширение в конфигураторе (Конфигурация → Расширения конфигурации, двойной щелчок по строке) и найдите объект в дереве.
- 🟢 Собственный реквизит расширения. Добавлен в расширении к заимствованному справочнику или документу, либо принадлежит собственному объекту расширения. Его имя обычно начинается с префикса расширения, например
Расш1_ДатаПоставки. Тип редактируется как у обычного реквизита. - 🔴 Реквизит основной конфигурации. Виден в расширении только потому, что заимствован объект или форма. Свойства такого реквизита в расширении не редактируются — они берутся из основной конфигурации.
- 🟡 Реквизит основной конфигурации со снятой поддержкой. Если конфигурация снята с поддержки или в ней включена возможность изменений, тип можно поменять прямо в основной конфигурации. Но тогда это уже не работа с расширением, и при каждом обновлении типовой придётся сравнивать изменения вручную.
| Ситуация | Где менять тип | Что будет с данными |
|---|---|---|
| Свой реквизит расширения | Свойство «Тип» в расширении | Платформа преобразует значения при реструктуризации; что не преобразуется, станет пустым |
| Реквизит типовой, конфигурация на поддержке | Новый реквизит в расширении | Старые данные остаются, переносите их обработкой |
| Реквизит типовой, поддержка снята | В основной конфигурации | Реструктуризация основной таблицы, риски при обновлениях |
Расширения нужны как раз для того, чтобы не снимать типовую с поддержки. Если ради одного типа реквизита вы готовы снять поддержку, сначала оцените второй способ из этой статьи — он дороже по разовой работе, но дешевле при каждом обновлении.
Подготовка базы и расширения перед сменой типа
Смена типа — операция с данными. Ошибиться можно один раз, поэтому подготовка обязательна.
- Сделайте резервную копию. Для файловой базы — выгрузка в
.dtчерезАдминистрирование → Выгрузить информационную базув конфигураторе или копия каталога базы. Для клиент-серверной — бэкап средствами СУБД. Без копии тип не меняйте: обратного пути у неконвертированных значений нет. - Сохраните расширение в файл. В списке расширений выделите нужное и выполните сохранение в файл
.cfe. Это ваша точка отката для метаданных. - Проверьте, сколько данных затронет смена. Простым запросом в консоли запросов посчитайте записи, где реквизит заполнен, и посмотрите примеры значений. Если вы меняете строку на число, сразу ищите строки, которые числом не являются:
"12,5 кг","б/н", пробелы. - Найдите все места использования. В расширении: правый клик по реквизиту →
Найти ссылки на объект. Ищите и по тексту модулей — запросы, где поле сравнивается или выводится, ссылки на него по имени в строках. - Выберите окно для работ. Обновление структуры базы с данными расширения требует, чтобы пользователи не работали с изменяемыми таблицами. Предупредите людей заранее и делайте это вне рабочего времени.
Способ 1. Меняем тип собственного реквизита расширения
Это прямой путь. Подходит, когда реквизит добавили вы сами в расширении.
- Откройте конфигуратор,
Конфигурация → Расширения конфигурации, откройте нужное расширение. - В дереве найдите объект (справочник, документ) и в нём реквизит или реквизит табличной части.
- Откройте палитру свойств (
Alt+Enter) и нажмите кнопку выбора у свойства «Тип». - Выберите новый тип. Для строки задайте длину, для числа — длину и точность. Если нужен составной тип, поставьте флажок «Составной тип данных» и отметьте нужные типы.
- Проверьте связанные свойства: «Заполнять из данных заполнения», «Проверка заполнения», «Связи параметров выбора», «Параметры выбора». Они могут потерять смысл при новом типе.
- Выполните
Конфигурация → Обновить конфигурацию базы данных(F7) для этого расширения. - Платформа покажет окно реорганизации с перечнем изменений. Прочитайте его и только потом принимайте.
Что происходит со значениями при реструктуризации
При смене типа платформа пытается преобразовать хранимые значения:
- 🔁 число → строка: обычно без потерь,
125становится"125"; - 🔁 строка → число: преобразуются только корректные числа, остальное становится нулём;
- 🔁 строка большей длины → строка меньшей длины: хвост обрезается;
- 🔁 простой тип → составной, который включает старый тип: значения сохраняются;
- ❌ ссылка на один справочник → ссылка на другой: значения не переносятся, реквизит станет пустым.
Если хоть часть значений не преобразуется автоматически, не полагайтесь на реструктуризацию. Используйте схему с новым реквизитом и переносом данных — так старые значения останутся до тех пор, пока вы не проверите результат.
Способ 2. Тип реквизита основной конфигурации: новый реквизит в расширении
Нужно, например, хранить в справочнике «Номенклатура» срок годности числом дней, а в типовой это строка, либо нужна ссылка на свой справочник вместо строкового поля. Тип типового реквизита поменять нельзя, поэтому делаем замену.
- Заимствуйте объект. Правый клик по справочнику в основной конфигурации →
Добавить в расширение. - Добавьте реквизит. В заимствованном объекте создайте реквизит с нужным типом, например
Расш1_СрокГодностиДней, тип «Число», длина 5, точность 0. - Обновите базу.
F7для расширения. Новый реквизит появится пустым у всех элементов. - Перенесите данные обработкой (код — в следующем разделе).
- Поменяйте формы. Заимствуйте форму объекта, добавьте элемент для нового реквизита, старый элемент скройте через свойство «Видимость» в расширении формы.
- Поменяйте код. Там, где типовой код читает старое поле, а вам нужно новое, используйте аннотации методов в модуле расширения:
&После— чтобы дописать поведение,&Вместо— чтобы заменить метод целиком. Для запросов — своё поле в тексте запроса в вашем коде расширения. - Поддерживайте синхронность, если старое поле всё ещё нужно типовым отчётам и обменам. Например, в обработчике
ПередЗаписьюобъекта заполняйте старое строковое поле из нового числового.
Старый реквизит не удаляйте и не очищайте: он принадлежит типовой. Обмены, печатные формы и отчёты основной конфигурации продолжат с ним работать.
Перенос данных при изменении типа реквизита
Обработку переноса удобнее всего положить в само расширение: объект «Обработка» в расширении с одной командой или кодом в модуле формы на сервере. Ниже пример для переноса строкового срока годности в числовой реквизит расширения.
&НаСервереБезКонтекста
Функция ПеренестиСрокГодности()
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Расш1_СрокГодностиДней = 0";
Выборка = Запрос.Выполнить().Выбрать();
Перенесено = 0;
Ошибки = Новый Массив;
Пока Выборка.Следующий() Цикл
Объект = Выборка.Ссылка.ПолучитьОбъект();
СтрокаСрока = СокрЛП(Объект.СрокГодности);
Если ПустаяСтрока(СтрокаСрока) Тогда
Продолжить;
КонецЕсли;
Попытка
Объект.Расш1_СрокГодностиДней = Число(СтрокаСрока);
Исключение
Ошибки.Добавить(Строка(Выборка.Ссылка) + ": " + СтрокаСрока);
Продолжить;
КонецПопытки;
Объект.ОбменДанными.Загрузка = Истина;
Объект.Записать();
Перенесено = Перенесено + 1;
КонецЦикла;
Возврат СтрШаблон("Перенесено: %1, не распознано: %2",
Формат(Перенесено, "ЧН=0; ЧГ=0"), Формат(Ошибки.Количество(), "ЧН=0; ЧГ=0"));
КонецФункции
Пояснения к коду:
СрокГодностив примере — условное имя исходного строкового реквизита. Подставьте имя своего поля.ОбменДанными.Загрузка = Истинаотключает проверки и подписки при записи. Это ускоряет перенос и не запускает лишнюю логику, но и не проверяет заполнение — поэтому проверку делайте отдельным запросом после переноса.- Массив
Ошибки— список значений, которые не стали числом. Выведите его в сообщение или в табличный документ и разберите вручную. - Условие
= 0в запросе делает обработку повторяемой: запустили ещё раз — она возьмёт только необработанные элементы.
Перенос в больших базах
На сотнях тысяч объектов одна транзакция и одна выборка — плохая идея.
- 📦 делите перенос на порции, например по 1000 объектов, через
ВЫБРАТЬ ПЕРВЫЕ 1000и повторный запуск; - ⏱ запускайте фоновым заданием, чтобы не держать клиент;
- 🧾 для регистров сведений, где реквизит — ресурс, используйте наборы записей с отбором и записью с замещением, а не поэлементную перезапись объектов.
Перезапись документов с ОбменДанными.Загрузка = Истина не перепроводит их. Если от реквизита зависят движения, после переноса нужно перепровести документы за нужный период, иначе остатки и обороты останутся по старым данным.
Версии платформы и режим совместимости
Возможности расширений сильно зависят от версии платформы.
- 🧩 Расширения конфигурации появились в платформе 8.3.6. Тогда они меняли формы и модули, но не структуру данных.
- 🧩 Хранить свои данные — добавлять реквизиты и табличные части к заимствованным объектам, создавать свои справочники и документы — расширения научились в 8.3.11. На платформе с номером ниже 8.3.11 реквизитов в расширении нет, и менять тип нечего.
- 🧩 У самого расширения есть свойство «Режим совместимости». Оно не может разрешать больше, чем режим совместимости основной конфигурации и сама платформа. Если в свойствах расширения недоступны нужные объекты, проверьте эти три значения.
Практическое правило: работайте на той же версии платформы, что и на рабочем сервере. Расширение, собранное в более новом конфигураторе, может не загрузиться в базу на старой платформе.
Ещё один момент — назначение расширения (свойство «Назначение»: исправление, адаптация, дополнение). Оно влияет на порядок применения нескольких расширений к одному объекту. Если два расширения добавляют реквизиты к одному справочнику, у каждого свой реквизит со своим префиксом, и конфликта по типу между ними нет.
Тестирование и контроль версий расширения
Где тестировать
Тип меняйте сначала на копии рабочей базы, а не в продуктиве. Порядок проверки:
- Загрузите копию
.dtв отдельную тестовую базу. - Примените изменённое расширение и обновите конфигурацию базы данных.
- Запустите перенос и сверьте количество записей: сколько было заполнено до, сколько после, сколько ушло в ошибки.
- Откройте формы объекта, создайте новый элемент, запишите существующий.
- Сформируйте отчёты, где участвует поле, и проверьте обмены, если реквизит в них выгружается.
Отладка
Ставьте точки останова в модулях расширения так же, как в основной конфигурации. Если метод перехвачен аннотацией &Вместо, проверьте, что после смены типа не осталось сравнений вида Если Объект.Расш1_Поле = "" Тогда для поля, которое стало числом — синтаксический контроль такую ошибку не поймает, она проявится только в работе.
Контроль версий
- 🗂 Заполните свойство «Версия» расширения и меняйте его при каждом изменении структуры. Так по списку расширений видно, какая редакция стоит в базе.
- 🗂 Расширение подключается к хранилищу конфигурации отдельно от основной конфигурации. Командная разработка идёт так же: захват объекта, правка типа, помещение.
- 🗂 Если вы работаете в 1С:EDT, расширение — отдельный проект, и смена типа видна в истории Git как изменение файла метаданных реквизита.
- 🗂 Храните
.cfeкаждой выпущенной версии. Откат метаданных без файла превращается в ручное восстановление.
Откат расширения на версию со старым типом снова запустит реструктуризацию. Значения, которые уже стали пустыми при первой смене типа, при откате не вернутся — вернуть их можно только из резервной копии базы.
Производительность после изменения типа реквизита
Тип поля влияет на размер таблиц и скорость запросов. Что учитывать:
| Изменение типа | Влияние на базу | Что сделать |
|---|---|---|
| Строка → строка неограниченной длины | Поле нельзя индексировать, по нему неудобно отбирать и сортировать в запросах | Оставьте фиксированную длину, если по полю ищут |
| Простой тип → составной | Платформа хранит тип и значение в нескольких колонках, запросы с отбором по полю становятся тяжелее | Берите составной тип только при реальной необходимости |
| Строка → ссылка на справочник | Отбор по ссылке быстрее, при выводе нужно соединение со справочником | Включите индексирование, если по полю часто отбирают |
| Число большой длины → короткое | Экономия места, риск переполнения | Проверьте максимальные значения до смены |
Отдельно о реквизитах расширения. Данные, которые расширение добавляет к заимствованным объектам, платформа хранит отдельно от таблиц основной конфигурации. Запрос, где одновременно участвуют поля типовой и поля расширения, обходится дороже. Поэтому:
- 🚀 включайте свойство «Индексировать» у реквизита расширения, если по нему строят отборы в списках и отчётах;
- 🚀 не выводите поле расширения в динамический список без надобности;
- 🚀 после массового переноса данных в клиент-серверной базе обновите статистику СУБД — регламентным заданием обслуживания или вручную в окно работ.
Ошибки при смене типа и что с ними делать
Если после всех проверок данные расходятся с исходными, не пытайтесь «досинхронизировать» их второй обработкой поверх. Сравните выгрузку старых значений из резервной копии с текущими и переносите только расхождения — так вы не перезапишете то, что пользователи уже успели поправить вручную.