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