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

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

В разработке на платформе 1С программисты часто сталкиваются со стандартным поведением системы: если для реквизита или ячейки таблицы установлен тип Число, то по умолчанию система инициализирует его нулем. Это создает серьезную проблему в бизнес-логике, когда необходимо четко понимать: ввел ли пользователь 0 (как осознанный результат) или же он просто пропустил ячейку (значение не введено). Ситуация осложняется, если мы хотим сэкономить место в базе данных и избежать использования составных типов данных (например, Число + Неопределено), так как они увеличивают объем таблиц в СУБД.

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

Метод 1: Кодирование "пустого" значения (Магические числа)

Разберем самый популярный способ, который позволяет сохранить тип данных Число в базе, но при этом выделить специальное значение под признак "не введено". Суть метода заключается в выборе числа, которое гарантированно не может встретиться в реальных расчетах.

Проанализируем шаги реализации этого метода:

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

Рассмотрим пример кода для обработки данных перед записью:


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

Метод 2: Использование дополнительного флага (Булево)

Посмотрим на ситуацию с другой стороны. Чтобы не портить сами данные "кривыми" значениями, мы можем добавить в структуру таблицы дополнительную колонку, например ЗначениеВведено с типом Булево. Это решение более прозрачное с точки зрения математики, но требует больше действий при проектировании интерфейса.

Алгоритм работы будет следующим:

Рассмотрим, как это выглядит в коде формы:


&НаКлиенте
Процедура ПоказательПриИзменении(Элемент)
    ТекущиеДанные = Элементы.ТаблицаДанных.ТекущиеДанные;
    Если ТекущиеДанные <> Неопределено Тогда
        // Даже если введен 0, мы помечаем, что ввод состоялся
        ТекущиеДанные.ПоказательЗаполнен = Истина;
    КонецЕсли;
КонецПроцедуры

Метод 3: Архитектурное решение через Регистр Сведений

Выясним, как использовать саму структуру базы данных для решения нашей задачи. Если данные хранятся в РегистреСведений, то самым правильным подходом будет отсутствие записи. Если записи по конкретному разрезу (измерениям) нет — значит, значение не введено. Если запись есть и в ресурсе стоит 0 — значит, введен именно ноль.

Для реализации этого подхода в отчетах или формах (типа "шахматка") мы используем ЛевоеСоединение. Проанализируем пример логики запроса:


ВЫБРАТЬ
    СправочникОбъекты.Ссылка КАК Объект,
    ЕСТЬNULL(РегистрДанные.Значение, "НЕ_ВВЕДЕНО") КАК Результат
ИЗ
    Справочник.Объекты КАК СправочникОбъекты
ЛЕВОЕ СОЕДИНЕНИЕ
    РегистрСведений.ДанныеПоказателей КАК РегистрДанные
    ПО СправочникОбъекты.Ссылка = РегистрДанные.Объект

В данном случае, если результат соединения NULL, мы точно знаем, что данных нет. В интерфейсе 1С такие поля будут выглядеть пустыми, что и требуется заказчику.

Метод 4: Визуализация и форматирование интерфейса

Даже если мы решили хранить "магическое число" или использовать флаги, нам нужно красиво показать это пользователю. Рассмотрим использование свойства Формат и события ТекстРедактирования.

Параметр ЧН (Числовое Неопределено):
В свойствах поля ввода на форме можно указать строку формата, например: ЧН='Не введено'. Однако это сработает только в том случае, если значение в поле строго равно 0. Поскольку нам нужно отличать введенный ноль от невведенного, этот метод подходит только в связке с программной установкой формата.

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


&НаСервере
Процедура ОформитьЯчейкиНаСервере()
    Для Каждого Строка Из Объект.Данные Цикл
        Если Строка.Значение = -999999 Тогда
            // Устанавливаем текст, который увидит пользователь вместо числа
            // Используем условное оформление или программную установку текста
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Также полезно использовать свойство ТекстПодсказки. Если значение в ячейке является "пустым" маркером, мы можем отображать в ней серый текст "Введите значение", что визуально подскажет пользователю о необходимости ввода данных.

Сравнение подходов: что выбрать?

Проанализируем плюсы и минусы каждого метода, чтобы вы могли сделать правильный выбор:

1. Магические числа:

2. Дополнительное поле Булево:

3. Отсутствие записей в Регистре:

Почему стоит избегать составного типа?

Многие начинающие разработчики решают задачу просто: устанавливают тип Число, Неопределено. Разберем, почему опытные специалисты (как в обсуждении на форуме) стараются этого избегать:

  1. Объем памяти в СУБД: При создании составного типа в MS SQL Server 1С создает несколько дополнительных колонок для хранения метаданных типа. Это "раздувает" таблицы.
  2. Сложность запросов: При использовании составных типов в запросах придется постоянно использовать конструкцию ВЫРАЗИТЬ, что может снижать производительность на больших объемах данных.
  3. Проблемы с индексацией: Поля составного типа сложнее индексировать, что может замедлить поиск и выборку данных.

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

← На главную