В процессе разработки интерфейсов для автоматизации торговли, особенно при работе со сканерами штрихкодов, часто возникает необходимость предоставить пользователю возможность быстрого ручного ввода количества товара. Одной из распространенных задач является добавление кнопки, которая вызывает диалог ввода числа для текущей строки таблицы. Однако начинающие разработчики часто сталкиваются с ошибкой «Значение не является значением объектного типа» при обращении к ТекущиеДанные. Разберем детально, почему это происходит, как исправить логику и как сделать код современным и отказоустойчивым.
Рассмотрим ситуацию, описанную в исходном вопросе. Ошибка возникает на строке:
Если ТекущаяСтрока.КоличествоРеализации > 1 Тогда
Текст ошибки прямо говорит о том, что программа пытается обратиться к свойству КоличествоРеализации у объекта, которого не существует. Проанализируем, почему переменная ТекущаяСтрока может стать пустой (Неопределено):
Элементы.Товары.ТекущиеДанные вернет Неопределено.Проанализируем ситуацию: чтобы избежать аварийного завершения работы программы, мы должны всегда проверять наличие данных перед обращением к ним. Это золотое правило программирования в 1С.
Прежде всего, изменим начало процедуры. Мы должны убедиться, что строка выбрана. Если она не выбрана, мы просто прекращаем выполнение или выводим сообщение пользователю.
&НаКлиенте
Процедура ДобавитьТовар(Команда)
ТекущаяСтрока = Элементы.Товары.ТекущиеДанные;
// Проверяем, что строка вообще выбрана
Если ТекущаяСтрока = Неопределено Тогда
Сообщить("Пожалуйста, выберите строку с товаром в списке!");
Возврат;
КонецЕсли;
// Теперь обращение к свойствам безопасно
Если ТекущаяСтрока.КоличествоРеализации > 0 Тогда
// Продолжаем логику...
КонецЕсли;
КонецПроцедуры
В современных конфигурациях «1С:Предприятие 8.3» на управляемых формах использование синхронного метода ВвестиЧисло крайне не рекомендуется. В веб-клиенте или в мобильном приложении такой код просто выдаст ошибку, так как платформа требует асинхронного подхода. Выясним, чем отличается ПоказатьВводЧисла.
Метод ПоказатьВводЧисла не останавливает выполнение кода. Вместо этого он принимает ОписаниеОповещения — ссылку на другую процедуру, которая выполнится только тогда, когда пользователь нажмет «ОК» или «Отмена». Это позволяет интерфейсу оставаться отзывчивым.
Разберем по шагам, как переписать код на асинхронный лад:
&НаКлиенте
Процедура ДобавитьТовар(Команда)
ТекущаяСтрока = Элементы.Товары.ТекущиеДанные;
Если ТекущаяСтрока = Неопределено Тогда
Возврат;
КонецЕсли;
// Создаем описание оповещения, указываем процедуру завершения
// Параметры: "ИмяПроцедуры", ЭтотОбъект, ДополнительныеПараметры (индекс строки)
ПараметрыОповещения = Новый ОписаниеОповещения("ПослеВводаКоличества", ЭтотОбъект, ТекущаяСтрока.ПолучитьИдентификатор());
// Вызываем немодальное окно
ПоказатьВводЧисла(ПараметрыОповещения, ТекущаяСтрока.КоличествоРеализации, "Введите количество для товара: " + ТекущаяСтрока.Номенклатура, 10, 3);
КонецПроцедуры
&НаКлиенте
Процедура ПослеВводаКоличества(ВведенноеЧисло, ИдентификаторСтроки) Экспорт
// Если пользователь нажал Отмена, ВведенноеЧисло будет Неопределено
Если ВведенноеЧисло = Неопределено Тогда
Возврат;
КонецЕсли;
// Находим строку по идентификатору, так как пока мы вводили число, фокус мог сместиться
ТекущаяСтрока = Объект.Товары.НайтиПоИдентификатору(ИдентификаторСтроки);
Если ТекущаяСтрока <> Неопределено Тогда
// Проверяем логику превышения заказа
Если ВведенноеЧисло > ТекущаяСтрока.КоличествоВЗаказе Тогда
ПоказатьПредупреждение(, "Введенное количество превышает объем заказа!");
Возврат;
КонецЕсли;
// Присваиваем значение
ТекущаяСтрока.КоличествоРеализации = ВведенноеЧисло;
// Исправляем формулу суммы (используем Реализацию, а не Заказ!)
ТекущаяСтрока.Сумма = ТекущаяСтрока.КоличествоРеализации * ТекущаяСтрока.Цена;
КонецЕсли;
КонецПроцедуры
Проанализируем исходный код автора. В нем содержалась критическая логическая ошибка:
ТекущаяСтрока.Сумма = ТекущаяСтрока.КоличествоВЗаказе * ТекущаяСтрока.Цена;
Если мы фиксируем Реализацию (то есть то, что фактически отгружаем), то и сумма строки должна считаться от количества реализации. Если оставлять количество из заказа, то итоговая сумма документа будет неверной, если товара отгрузили меньше, чем планировалось. Мы исправили это в примере выше, умножая Цена на КоличествоРеализации.
Также важно помнить: метод ВвестиЧисло напрямую меняет значение переменной, если она была передана в него. В асинхронном методе ПоказатьВводЧисла мы получаем новое значение в отдельный параметр ВведенноеЧисло, что гораздо безопаснее, так как позволяет выполнить проверку до того, как данные в таблице изменятся.
Рассмотрим совет из обсуждения: иногда кнопка — это лишнее действие. Если пользователю нужно часто менять количество, стоит проверить настройки колонки в конфигураторе.
Если у колонки КоличествоРеализации установлено свойство ТолькоПросмотр = Ложь и РежимРедактирования = ВходПриВводе, пользователь может просто кликнуть по числу и сразу ввести новое значение с клавиатуры.
Чтобы при таком вводе сохранялась логика проверки (не больше заказа) и пересчета суммы, необходимо использовать событие таблицы ТоварыПриИзменении или событие конкретного поля КоличествоРеализацииПриИзменении.
&НаКлиенте
Процедура ТоварыКоличествоРеализацииПриИзменении(Элемент)
ТекущаяСтрока = Элементы.Товары.ТекущиеДанные;
Если ТекущаяСтрока = Неопределено Тогда
Возврат;
КонецЕсли;
// Валидация
Если ТекущаяСтрока.КоличествоРеализации > ТекущаяСтрока.КоличествоВЗаказе Тогда
ТекущаяСтрока.КоличествоРеализации = ТекущаяСтрока.КоличествоВЗаказе;
ПоказатьПредупреждение(, "Превышение заказа недопустимо!");
КонецЕсли;
// Пересчет суммы
ТекущаяСтрока.Сумма = ТекущаяСтрока.КоличествоРеализации * ТекущаяСтрока.Цена;
КонецПроцедуры
Проанализировав проблему, мы выяснили, что для стабильной работы кода необходимо придерживаться следующих правил:
Если ТекущиеДанные <> Неопределено.ПоказатьВводЧисла является стандартом для современной платформы 8.3. Это гарантирует работу кода во всех типах клиентов (тонкий, веб, мобильный).Эти подходы сделают вашу работу с табличными частями профессиональной и защищенной от случайных падений системы.