Как проверить соответствие длины и типа значения реквизиту табличной части в 1С

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

При разработке механизмов загрузки данных из внешних источников (текстовых файлов, Excel, XML или сторонних API) программисты 1С часто сталкиваются с проблемой: передаваемое значение оказывается длиннее или точнее, чем это предусмотрено в метаданных конфигурации. Если просто присвоить значение реквизиту, платформа может автоматически обрезать строку или округлить число без какого-либо уведомления, что приведет к потере данных. В этой статье мы подробно разберем, как программно проконтролировать, «влезает» ли значение в реквизит, и как правильно выдать предупреждение пользователю.

Метод 1. Проверка через свойства метаданных

Самый прямой путь — обратиться к метаданным конфигурации и сравнить характеристики входящего значения с установленными ограничениями реквизита. Разберем, как получить доступ к свойствам реквизита табличной части. Рассмотрим ситуацию на примере документа РеализацияТоваровУслуг и его табличной части Товары.

Для начала проанализируем, как программно добраться до описания типа реквизита:


// Получаем метаданные конкретного реквизита табличной части
МетаданныеРеквизита = Метаданные.Документы.РеализацияТоваровУслуг.ТабличныеЧасти.Товары.Реквизиты.Номенклатура;

// Тип реквизита (объект ОписаниеТипов)
ОписаниеТипа = МетаданныеРеквизита.Тип;

// Если это строка, проверим длину
Если ОписаниеТипа.СодержитТип(Тип("Строка")) Тогда
    МаксДлина = ОписаниеТипа.КвалификаторыСтроки.Длина;
    // Здесь можно сравнить со СтрДлина(ВходящееЗначение)
КонецЕсли;

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

Метод 2. Использование объекта ОписаниеТипов и метода ПривестиЗначение

Этот способ является наиболее «чистым» и рекомендуемым с точки зрения платформы 1С. У объекта ОписаниеТипов есть замечательный метод ПривестиЗначение(). Он берет входное значение и пытается максимально корректно «втиснуть» его в рамки заданного типа, обрезая строки и округляя числа согласно правилам метаданных.

Рассмотрим алгоритм проверки:

  1. Получаем объект ОписаниеТипов из метаданных нужного реквизита.
  2. Используем метод ПривестиЗначение() для входящих данных.
  3. Сравниваем полученный результат с оригиналом.

Проанализируем пример функции для такой проверки:


Функция ДанныеВлезаютВРеквизит(ВходящееЗначение, ИмяДокумента, ИмяТЧ, ИмяРеквизита) Экспорт
    
    // Получаем описание типа из метаданных
    ОписаниеТипа = Метаданные.Документы[ИмяДокумента].ТабличныеЧасти[ИмяТЧ].Реквизиты[ИмяРеквизита].Тип;
    
    // Приводим значение к типу реквизита
    ПриведенноеЗначение = ОписаниеТипа.ПривестиЗначение(ВходящееЗначение);
    
    // Сравниваем. Внимание: для адекватного сравнения строк и чисел 
    // может потребоваться дополнительная логика
    Если Строка(ВходящееЗначение) <> Строка(ПриведенноеЗначение) Тогда
        Возврат Ложь; // Значение изменилось, значит оно не влезло или исказилось
    КонецЕсли;
    
    Возврат Истина;
    
КонецФункции

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

Метод 3. Проверка числовых показателей (Разрядность и Точность)

Проверка чисел часто вызывает затруднения. Например, если в метаданных число имеет длину 15 и точность 3, это значит, что на целую часть отведено 12 знаков (15 минус 3). Если вы попытаетесь записать число с 13 знаками в целой части, платформа его обрежет.

Выясним причину, по которой обычное сравнение строк может не подойти для чисел. Число 100 и строка "100.000" содержательно равны, но строковое сравнение выдаст Ложь. Поэтому для чисел лучше использовать математический подход.

Разберем, как рассчитать максимально возможное число на основе метаданных:


Квалификаторы = ОписаниеТипа.КвалификаторыЧисла;
Длина = Квалификаторы.Длина;
Точность = Квалификаторы.Точность;

// Максимальное целое число, которое влезет
МаксЦелое = Pow(10, Длина - Точность) - 1;

Если Абс(ВходящееЧисло) > МаксЦелое Тогда
    Сообщить("Целая часть числа слишком велика!");
КонецЕсли;

Также не забывайте проверять свойство ДопустимыйЗнак. Если в метаданных указано ДопустимыйЗнак.Неотрицательное, а из файла пришло отрицательное число, метод ПривестиЗначение() превратит его в ноль, что тоже является потерей данных.

Метод 4. Косвенная проверка через присваивание

Существует «ленивый», но действенный способ, который предложили участники обсуждения: попытаться записать значение в реквизит объекта (или строки таблицы значений с типизированными колонками), а затем сравнить то, что получилось, с исходником.

Рассмотрим этот процесс по шагам:

  1. Создаем новую строку в табличной части (или используем вспомогательную таблицу значений с теми же типами).
  2. Присваиваем значение реквизиту: НоваяСтрока.Количество = ЗначениеИзФайла;.
  3. Сравниваем: Если НоваяСтрока.Количество <> ЗначениеИзФайла Тогда....

Этот метод хорош тем, что платформа сама берет на себя всю работу по преобразованию типов. Однако он может быть менее производительным при больших объемах данных из-за создания лишних объектов в памяти.

Советы по обработке строковых данных

При работе со строками, загружаемыми из текстовых файлов (особенно формата DBF или TXT с фиксированной шириной), крайне важно использовать функцию СокрЛП() (TrimAll). Часто значение не «влезает» только из-за того, что в конце строки притаились невидимые пробелы.

Посмотрим на пример правильной обработки строки:


ЗначениеОчищенное = СокрЛП(ЗначениеИзФайла);
Если СтрДлина(ЗначениеОчищенное) > МаксДлинаИзМетаданных Тогда
    ТекстОшибки = СтрШаблон("Строка '%1' слишком длинная (макс. %2 симв.)", ЗначениеОчищенное, МаксДлинаИзМетаданных);
    // Вывод сообщения или запись в лог
КонецЕсли;

Использование Библиотеки Стандартных Подсистем (БСП)

Если ваша конфигурация построена на БСП, мы можем воспользоваться готовыми инструментами. Например, модули СтроковыеФункцииКлиентСервер или ОбщегоНазначения содержат функции для валидации данных. Также полезно заглянуть в механизмы обмена данными, где проверка соответствия типов является стандартной процедурой.

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

Заключение

Мы рассмотрели несколько способов проверки данных на соответствие метаданным. Выбор конкретного метода зависит от ваших задач:

Помните, что своевременная проверка данных на этапе загрузки — это залог чистоты информационной базы и отсутствия трудноуловимых ошибок в расчетах и отчетах в будущем.

← На главную