В разработке на платформе 1С программисты часто сталкиваются со стандартным поведением системы: если для реквизита или ячейки таблицы установлен тип Число, то по умолчанию система инициализирует его нулем. Это создает серьезную проблему в бизнес-логике, когда необходимо четко понимать: ввел ли пользователь 0 (как осознанный результат) или же он просто пропустил ячейку (значение не введено). Ситуация осложняется, если мы хотим сэкономить место в базе данных и избежать использования составных типов данных (например, Число + Неопределено), так как они увеличивают объем таблиц в СУБД.
В этой статье мы подробно разберем, как реализовать механизм разделения нуля и "пустоты", проанализируем различные подходы — от "магических чисел" до архитектурных хитростей — и выясним, какой метод будет наиболее эффективным для вашей задачи.
Разберем самый популярный способ, который позволяет сохранить тип данных Число в базе, но при этом выделить специальное значение под признак "не введено". Суть метода заключается в выборе числа, которое гарантированно не может встретиться в реальных расчетах.
Проанализируем шаги реализации этого метода:
-1. Если возможны любые числа, используем экстремально малые или дробные значения, например -9999999999 или 0.1 (если работаем только с целыми числами).РегистрСведений) проверяем, заполнено ли поле в форме. Если нет — записываем наше спецчисло.Рассмотрим пример кода для обработки данных перед записью:
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
// Допустим, -999999 — это наш маркер "Не введено"
Для Каждого СтрокаТЧ Из ТекущийОбъект.ДанныеДляРасчета Цикл
Если СтрокаТЧ.ЗначениеДляЗаписи = 0 И СтрокаТЧ.ПользовательНичегоНеВводил Тогда
СтрокаТЧ.ЧисловоеПоле = -999999;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Посмотрим на ситуацию с другой стороны. Чтобы не портить сами данные "кривыми" значениями, мы можем добавить в структуру таблицы дополнительную колонку, например ЗначениеВведено с типом Булево. Это решение более прозрачное с точки зрения математики, но требует больше действий при проектировании интерфейса.
Алгоритм работы будет следующим:
Показатель (Число) и ПоказательЗаполнен (Булево).ПриИзменении числового поля программно устанавливаем флаг ПоказательЗаполнен = Истина.Ложь.Рассмотрим, как это выглядит в коде формы:
&НаКлиенте
Процедура ПоказательПриИзменении(Элемент)
ТекущиеДанные = Элементы.ТаблицаДанных.ТекущиеДанные;
Если ТекущиеДанные <> Неопределено Тогда
// Даже если введен 0, мы помечаем, что ввод состоялся
ТекущиеДанные.ПоказательЗаполнен = Истина;
КонецЕсли;
КонецПроцедуры
Выясним, как использовать саму структуру базы данных для решения нашей задачи. Если данные хранятся в РегистреСведений, то самым правильным подходом будет отсутствие записи. Если записи по конкретному разрезу (измерениям) нет — значит, значение не введено. Если запись есть и в ресурсе стоит 0 — значит, введен именно ноль.
Для реализации этого подхода в отчетах или формах (типа "шахматка") мы используем ЛевоеСоединение. Проанализируем пример логики запроса:
ВЫБРАТЬ
СправочникОбъекты.Ссылка КАК Объект,
ЕСТЬNULL(РегистрДанные.Значение, "НЕ_ВВЕДЕНО") КАК Результат
ИЗ
Справочник.Объекты КАК СправочникОбъекты
ЛЕВОЕ СОЕДИНЕНИЕ
РегистрСведений.ДанныеПоказателей КАК РегистрДанные
ПО СправочникОбъекты.Ссылка = РегистрДанные.Объект
В данном случае, если результат соединения NULL, мы точно знаем, что данных нет. В интерфейсе 1С такие поля будут выглядеть пустыми, что и требуется заказчику.
Даже если мы решили хранить "магическое число" или использовать флаги, нам нужно красиво показать это пользователю. Рассмотрим использование свойства Формат и события ТекстРедактирования.
Параметр ЧН (Числовое Неопределено):
В свойствах поля ввода на форме можно указать строку формата, например: ЧН='Не введено'. Однако это сработает только в том случае, если значение в поле строго равно 0. Поскольку нам нужно отличать введенный ноль от невведенного, этот метод подходит только в связке с программной установкой формата.
Разберем пример динамического изменения представления:
&НаСервере
Процедура ОформитьЯчейкиНаСервере()
Для Каждого Строка Из Объект.Данные Цикл
Если Строка.Значение = -999999 Тогда
// Устанавливаем текст, который увидит пользователь вместо числа
// Используем условное оформление или программную установку текста
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Также полезно использовать свойство ТекстПодсказки. Если значение в ячейке является "пустым" маркером, мы можем отображать в ней серый текст "Введите значение", что визуально подскажет пользователю о необходимости ввода данных.
Проанализируем плюсы и минусы каждого метода, чтобы вы могли сделать правильный выбор:
1. Магические числа:
2. Дополнительное поле Булево:
3. Отсутствие записей в Регистре:
Многие начинающие разработчики решают задачу просто: устанавливают тип Число, Неопределено. Разберем, почему опытные специалисты (как в обсуждении на форуме) стараются этого избегать:
ВЫРАЗИТЬ, что может снижать производительность на больших объемах данных.Таким образом, использование кодирования или флагов является более профессиональным подходом для высоконагруженных систем или задач, требующих строгой экономии ресурсов. Мы рекомендуем остановиться на методе с Регистром Сведений (отсутствие записи = нет значения), если структура данных это позволяет, либо на методе магического числа, если требуется работа в рамках одной плоской таблицы.