В практике разработки на платформе 1С:Предприятие программисты часто сталкиваются с ситуацией, когда текстовые данные, которые должны иметь неограниченную длину, внезапно обрезаются до определенного количества символов (например, 525 или 1024). Эта проблема особенно актуальна при динамическом формировании таблиц значений, загрузке данных из макетов или использовании построителей отчетов. В данной статье мы разберем причины такого поведения платформы и выработаем надежные способы решения проблемы.
Рассмотрим классический сценарий: программа считывает текст (например, пункты Устава организации) из макета табличного документа. Для преобразования табличного документа в ТаблицаЗначений используется ПостроительОтчета. Далее данные из одной таблицы переносятся в другую (итоговую) таблицу для последующей загрузки в табличную часть объекта. В какой-то момент выясняется, что длинные пункты (более 2000 символов) обрезаются, хотя в метаданных реквизита и в коде указано, что строка должна быть неограниченной.
Проанализируем причину: когда ПостроительОтчета анализирует данные макета для создания таблицы, он автоматически определяет типы колонок. Если самая длинная строка в исходных данных на момент анализа составляет, к примеру, 525 символов, построитель может создать колонку с типом Строка и фиксированной длиной 525 символов вместо неограниченной строки. Главная опасность кроется в использовании метода Скопировать(). При вызове ТаблицаЗначений.Скопировать() новая таблица полностью наследует метаданные колонок, включая скрытые ограничения длины.
Выясним, на каком этапе данные теряют свою целостность. Проанализируем типичный ошибочный код:
// Получаем ТЗ из построителя (здесь колонки могут получить ограничение длины)
ТЗИзМакета = ПостроительОтчета.Результат.Выгрузить();
// Создаем итоговую таблицу копированием первой полученной ТЗ
ИтоговаяТЗ = ТЗИзМакета.Скопировать();
// При добавлении новых данных из других источников в ИтоговаяТЗ
// строки будут обрезаться по длине самой первой таблицы
Для каждого СтрокаИсточник Из ДругаяТЗ Цикл
НоваяСтрока = ИтоговаяТЗ.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаИсточник); // Обрезка происходит здесь!
КонецЦикла;
В данном примере ИтоговаяТЗ унаследовала объект ОписаниеТипов для колонки текста. Даже если вы попытаетесь программно записать туда длинную строку, платформа «молча» обрежет ее до того лимита, который был определен в ТЗИзМакета.
Наиболее надежный способ избежать обрезки — отказаться от автоматического определения типов при создании итоговой таблицы. Мы должны вручную инициализировать колонки с нужными квалификаторами. Рассмотрим, как правильно задать тип «Строка неограниченной длины».
Для создания описания типа строки без ограничений используем конструктор ОписаниеТипов. Важно помнить: если не указывать КвалификаторыСтроки или передать их пустыми, строка будет считаться неограниченной.
ТЗСодержаниеРазделов = Новый ТаблицаЗначений;
// Правильное добавление колонки с неограниченной длиной
// Вариант 1: Просто указание типа
ТЗСодержаниеРазделов.Колонки.Добавить("СодержаниеПункта", Новый ОписаниеТипов("Строка"));
// Вариант 2: Явное указание пустых квалификаторов (гарантирует неограниченность)
Квалификаторы = Новый КвалификаторыСтроки(0, ДопустимаяДлина.Переменная);
ТЗСодержаниеРазделов.Колонки.Добавить("СодержаниеПункта", Новый ОписаниеТипов("Строка",,,, Квалификаторы));
Обратите внимание: использование Новый КвалификаторыСтроки(20000) все равно создает ограничение. Если ваш текст окажется длиннее 20 000 символов, он снова будет обрезан. Только нулевая длина в квалификаторах или их отсутствие в ОписаниеТипов("Строка") обеспечивают истинную неограниченность.
Если вам необходимо собрать данные из нескольких таблиц, полученных через ПостроительОтчета, никогда не используйте первую таблицу как «шаблон» через Скопировать(). Вместо этого создайте «чистую» таблицу с программно заданными колонками и наполняйте ее в цикле.
Проанализируем правильный алгоритм совместной работы:
ТаблицаЗначений.Колонки.Добавить() с корректными типами.ЗаполнитьЗначенияСвойств() для копирования данных в новую строку эталонной таблицы.Пример реализации такого подхода:
// 1. Подготовка эталона
ИтоговаяТаблица = Новый ТаблицаЗначений;
ИтоговаяТаблица.Колонки.Добавить("НаименованиеРаздела", Новый ОписаниеТипов("Строка"));
ИтоговаяТаблица.Колонки.Добавить("СодержаниеПункта", Новый ОписаниеТипов("Строка")); // Неограниченная
// 2. Наполнение данными
Для каждого СтрокаИзИсточника Из ТЗПолученнаяИзМакета Цикл
НоваяСтрока = ИтоговаяТаблица.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаИзИсточника);
КонецЦикла;
Важно понимать технический нюанс: функция ЗаполнитьЗначенияСвойств не меняет тип колонки в приемнике. Она лишь пытается привести значение источника к тому типу, который уже жестко задан в приемнике. Если в приемнике (вашей итоговой таблице) колонка уже имеет тип Строка(525), то при копировании данных функция просто передаст первые 525 символов. Именно поэтому критически важно настроить типы в ТаблицаЗначений до начала ее заполнения.
Разберем еще несколько моментов, которые помогут в диагностике подобных ошибок:
ТЗ.Колонки.ИмяКолонки.ТипЗнч. Посмотрите на квалификаторы строки. Если длина там отлична от 0, значит, ограничение установлено.Таким образом, мы выяснили, что основной причиной «загадочной» обрезки строк является наследование типов при копировании таблиц. Соблюдая правила явной инициализации структуры ТаблицаЗначений, вы обеспечите сохранность данных любого объема.