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

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

В процессе разработки интерфейсов для автоматизации торговли, особенно при работе со сканерами штрихкодов, часто возникает необходимость предоставить пользователю возможность быстрого ручного ввода количества товара. Одной из распространенных задач является добавление кнопки, которая вызывает диалог ввода числа для текущей строки таблицы. Однако начинающие разработчики часто сталкиваются с ошибкой «Значение не является значением объектного типа» при обращении к ТекущиеДанные. Разберем детально, почему это происходит, как исправить логику и как сделать код современным и отказоустойчивым.

Анализ причины ошибки: Почему ТекущиеДанные возвращают Неопределено

Рассмотрим ситуацию, описанную в исходном вопросе. Ошибка возникает на строке:

Если ТекущаяСтрока.КоличествоРеализации > 1 Тогда

Текст ошибки прямо говорит о том, что программа пытается обратиться к свойству КоличествоРеализации у объекта, которого не существует. Проанализируем, почему переменная ТекущаяСтрока может стать пустой (Неопределено):

  1. Отсутствие фокуса: Если пользователь нажал кнопку на форме, фокус управления мог перейти с таблицы на кнопку. В некоторых сценариях, если в таблице не выделена ни одна строка синим цветом, свойство Элементы.Товары.ТекущиеДанные вернет Неопределено.
  2. Пустая таблица: Если в табличной части нет записей, текущих данных быть не может по определению.
  3. Программное изменение: Если перед вызовом процедуры код программно обновил таблицу или пересчитал ее, фокус строки мог сброситься.

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

Шаг 1: Добавление проверки на наличие текущей строки

Прежде всего, изменим начало процедуры. Мы должны убедиться, что строка выбрана. Если она не выбрана, мы просто прекращаем выполнение или выводим сообщение пользователю.


&НаКлиенте
Процедура ДобавитьТовар(Команда)
    ТекущаяСтрока = Элементы.Товары.ТекущиеДанные;
    
    // Проверяем, что строка вообще выбрана
    Если ТекущаяСтрока = Неопределено Тогда
        Сообщить("Пожалуйста, выберите строку с товаром в списке!");
        Возврат;
    КонецЕсли;

    // Теперь обращение к свойствам безопасно
    Если ТекущаяСтрока.КоличествоРеализации > 0 Тогда
        // Продолжаем логику...
    КонецЕсли;
КонецПроцедуры

Шаг 2: Переход от ВвестиЧисло к ПоказатьВводЧисла

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

Метод ПоказатьВводЧисла не останавливает выполнение кода. Вместо этого он принимает ОписаниеОповещения — ссылку на другую процедуру, которая выполнится только тогда, когда пользователь нажмет «ОК» или «Отмена». Это позволяет интерфейсу оставаться отзывчивым.

Разберем по шагам, как переписать код на асинхронный лад:


&НаКлиенте
Процедура ДобавитьТовар(Команда)
    ТекущаяСтрока = Элементы.Товары.ТекущиеДанные;
    
    Если ТекущаяСтрока = Неопределено Тогда
        Возврат;
    КонецЕсли;

    // Создаем описание оповещения, указываем процедуру завершения
    // Параметры: "ИмяПроцедуры", ЭтотОбъект, ДополнительныеПараметры (индекс строки)
    ПараметрыОповещения = Новый ОписаниеОповещения("ПослеВводаКоличества", ЭтотОбъект, ТекущаяСтрока.ПолучитьИдентификатор());
    
    // Вызываем немодальное окно
    ПоказатьВводЧисла(ПараметрыОповещения, ТекущаяСтрока.КоличествоРеализации, "Введите количество для товара: " + ТекущаяСтрока.Номенклатура, 10, 3);
КонецПроцедуры

&НаКлиенте
Процедура ПослеВводаКоличества(ВведенноеЧисло, ИдентификаторСтроки) Экспорт
    // Если пользователь нажал Отмена, ВведенноеЧисло будет Неопределено
    Если ВведенноеЧисло = Неопределено Тогда
        Возврат;
    КонецЕсли;

    // Находим строку по идентификатору, так как пока мы вводили число, фокус мог сместиться
    ТекущаяСтрока = Объект.Товары.НайтиПоИдентификатору(ИдентификаторСтроки);
    
    Если ТекущаяСтрока <> Неопределено Тогда
        
        // Проверяем логику превышения заказа
        Если ВведенноеЧисло > ТекущаяСтрока.КоличествоВЗаказе Тогда
            ПоказатьПредупреждение(, "Введенное количество превышает объем заказа!");
            Возврат;
        КонецЕсли;

        // Присваиваем значение
        ТекущаяСтрока.КоличествоРеализации = ВведенноеЧисло;
        
        // Исправляем формулу суммы (используем Реализацию, а не Заказ!)
        ТекущаяСтрока.Сумма = ТекущаяСтрока.КоличествоРеализации * ТекущаяСтрока.Цена;
        
    КонецЕсли;
КонецПроцедуры

Разбор логических ошибок в расчетах

Проанализируем исходный код автора. В нем содержалась критическая логическая ошибка:

ТекущаяСтрока.Сумма = ТекущаяСтрока.КоличествоВЗаказе * ТекущаяСтрока.Цена;

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

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

Альтернативный вариант: Быстрый ввод в ячейке

Рассмотрим совет из обсуждения: иногда кнопка — это лишнее действие. Если пользователю нужно часто менять количество, стоит проверить настройки колонки в конфигураторе. Если у колонки КоличествоРеализации установлено свойство ТолькоПросмотр = Ложь и РежимРедактирования = ВходПриВводе, пользователь может просто кликнуть по числу и сразу ввести новое значение с клавиатуры.

Чтобы при таком вводе сохранялась логика проверки (не больше заказа) и пересчета суммы, необходимо использовать событие таблицы ТоварыПриИзменении или событие конкретного поля КоличествоРеализацииПриИзменении.


&НаКлиенте
Процедура ТоварыКоличествоРеализацииПриИзменении(Элемент)
    ТекущаяСтрока = Элементы.Товары.ТекущиеДанные;
    Если ТекущаяСтрока = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    // Валидация
    Если ТекущаяСтрока.КоличествоРеализации > ТекущаяСтрока.КоличествоВЗаказе Тогда
        ТекущаяСтрока.КоличествоРеализации = ТекущаяСтрока.КоличествоВЗаказе;
        ПоказатьПредупреждение(, "Превышение заказа недопустимо!");
    КонецЕсли;
    
    // Пересчет суммы
    ТекущаяСтрока.Сумма = ТекущаяСтрока.КоличествоРеализации * ТекущаяСтрока.Цена;
КонецПроцедуры

Итоги и рекомендации

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

  1. Всегда проверять ТекущиеДанные: Никогда не обращайтесь к свойствам строки через точку без предварительной проверки Если ТекущиеДанные <> Неопределено.
  2. Использовать асинхронность: Метод ПоказатьВводЧисла является стандартом для современной платформы 8.3. Это гарантирует работу кода во всех типах клиентов (тонкий, веб, мобильный).
  3. Соблюдать точность данных: При вызове диалога ввода (параметры 10, 3) убедитесь, что тип данных в метаданных (конфигураторе) совпадает по длине и точности, иначе 1С округлит введенные данные, что вызовет вопросы у пользователя.
  4. Контролировать контекст: При использовании оповещений лучше передавать идентификатор строки, так как за время ожидания ввода пользователь может переключиться на другую строку или даже в другой документ.

Эти подходы сделают вашу работу с табличными частями профессиональной и защищенной от случайных падений системы.

← На главную