Диалог ввода числа во встроенном языке 1С 8.3: от ВвестиЧисло до своей формы
Содержание
Чтобы ввести число от пользователя в 1С 8.3, на клиенте вызывают ПоказатьВводЧисла() с описанием оповещения или Ждать ВвестиЧислоАсинх() в асинхронной процедуре. Старый ВвестиЧисло() работает только там, где разрешены модальные окна.
Частое заблуждение — искать для этого объект Запрос. Запрос во встроенном языке 1С — это обращение к базе данных на языке запросов, к диалогам он отношения не имеет. Функции с названием вроде «ПолучениеЧисла» в платформе тоже нет: ввод числа идёт через диалоги ввода, через ввод значения с описанием типов или через свою форму.
С чего начать: какой метод ввода числа подходит вашей конфигурации
Выбор метода зависит от одного свойства конфигурации — режима использования модальности. Откройте конфигуратор, встаньте на корень дерева конфигурации и откройте свойства. Свойство называется Режим использования модальности и принимает три значения:
- 🟢 Использовать — модальные окна разрешены,
ВвестиЧисло()работает. - 🟡 Использовать с предупреждением — работает, но при проверке модулей платформа предупредит.
- 🔴 Не использовать — модальный вызов падает с ошибкой
Использование модальных окон в данном режиме запрещено!.
Типовые конфигурации на 8.3 (БП 3.0, ЗУП 3.1, УТ 11) работают в режиме «Не использовать». Значит, в доработке типовой базы ВвестиЧисло() не годится.
| Метод | Модальность | Версия платформы | Когда применять |
|---|---|---|---|
ВвестиЧисло() | нужна | любая 8.x | старые самописные конфигурации, обычные формы |
ПоказатьВводЧисла() | не нужна | 8.3.3 и новее | типовые конфигурации, веб-клиент |
ВвестиЧислоАсинх() | не нужна | номер не ниже 8.3.18 | новый код, линейная логика без оповещений |
ВвестиЗначение() / ПоказатьВводЗначения() | зависит от варианта | 8.3.x | нужен запрет отрицательных или особый тип |
| Своя форма | не нужна | 8.3.x | несколько полей, диапазон, подсказки |
Все диалоги ввода — клиентские методы. Их вызывают только в процедурах с директивой &НаКлиенте. На сервере окна показать нельзя.
Ввод числа через встроенные диалоги: три варианта кода
У всех трёх методов одинаковые параметры по смыслу:
- Число — начальное значение в поле.
- Подсказка — заголовок окна.
- Длина — общее количество разрядов.
- Точность — количество знаков после запятой.
Длина и точность работают как квалификаторы реквизита. Если задать длину 5 и точность 2, пользователь введёт максимум 999.99. Точность 0 — только целые.
Модальный ВвестиЧисло()
Метод возвращает Истина, если пользователь нажал ОК, и Ложь при отмене. Само значение пишется в переменную, переданную первым параметром.
&НаКлиенте
Процедура ЗапроситьКоличество(Команда)
Количество = 1;
Если ВвестиЧисло(Количество, "Количество, шт.", 10, 0) Тогда
Объект.Количество = Количество;
КонецЕсли;
КонецПроцедуры
Переменную объявите до вызова и задайте ей начальное значение. Пользователь увидит его в поле.
Немодальный ПоказатьВводЧисла()
Код разделяется на две процедуры. Первая показывает окно и сразу завершается. Вторая вызывается платформой, когда пользователь закроет диалог.
&НаКлиенте
Процедура ЗапроситьКоличество(Команда)
Оповещение = Новый ОписаниеОповещения("ПослеВводаКоличества", ЭтотОбъект);
ПоказатьВводЧисла(Оповещение, 1, "Количество, шт.", 10, 0);
КонецПроцедуры
&НаКлиенте
Процедура ПослеВводаКоличества(Число, ДополнительныеПараметры) Экспорт
Если Число = Неопределено Тогда
Возврат; // пользователь нажал «Отмена»
КонецЕсли;
Объект.Количество = Число;
КонецПроцедуры
Три вещи, на которых спотыкаются чаще всего:
- 📌 процедура-обработчик обязательно
Экспорт, иначе платформа её не найдёт; - 📌 у обработчика два параметра: результат и дополнительные параметры;
- 📌 код после
ПоказатьВводЧисла()в первой процедуре выполнится сразу, не дожидаясь ввода. Всё, что зависит от числа, переносите в обработчик.
Через ДополнительныеПараметры передают контекст — например, номер строки табличной части:
Оповещение = Новый ОписаниеОповещения("ПослеВводаКоличества", ЭтотОбъект,
Новый Структура("ИдентификаторСтроки", Элементы.Товары.ТекущаяСтрока));
Асинхронный ВвестиЧислоАсинх()
С платформы 8.3.18 появились асинхронные методы. Код снова выглядит линейно, но окно немодальное.
&НаКлиенте
Асинх Процедура ЗапроситьКоличество(Команда)
Число = Ждать ВвестиЧислоАсинх(1, "Количество, шт.", 10, 0);
Если Число = Неопределено Тогда
Возврат;
КонецЕсли;
Объект.Количество = Число;
КонецПроцедуры
Процедура помечается словом Асинх, вызов — оператором Ждать. При отмене возвращается Неопределено. Режим совместимости конфигурации должен быть не ниже 8.3.18, иначе ключевые слова не распознаются.
Ограничение знака и типа: ввод числа через ВвестиЗначение
ВвестиЧисло() не умеет запрещать минус. Для количества, цены или процента это неудобно. Задачу решает ввод значения с описанием типов:
&НаКлиенте
Процедура ЗапроситьЦену(Команда)
ТипЦены = Новый ОписаниеТипов("Число",
Новый КвалификаторыЧисла(15, 2, ДопустимыйЗнак.Неотрицательный));
Оповещение = Новый ОписаниеОповещения("ПослеВводаЦены", ЭтотОбъект);
ПоказатьВводЗначения(Оповещение, 0, "Цена, руб.", ТипЦены);
КонецПроцедуры
&НаКлиенте
Процедура ПослеВводаЦены(Значение, ДополнительныеПараметры) Экспорт
Если Значение = Неопределено Тогда
Возврат;
КонецЕсли;
Объект.Цена = Значение;
КонецПроцедуры
Квалификатор ДопустимыйЗнак.Неотрицательный не даст ввести отрицательное значение прямо в поле. Длина 15 и точность 2 совпадают с типичным реквизитом суммы.
Асинхронная пара для этого метода — ВвестиЗначениеАсинх(), модальная — ВвестиЗначение().
Проверка введённого числа и повторный запрос
Длина, точность и знак — это ограничения формата. Бизнес-правила («скидка от 0 до 30 %», «количество кратно 10») проверяете сами. Лучший момент — в обработчике сразу после ввода.
Пример: скидка не больше 30 %. Если введено больше, сообщаем и снова открываем диалог с введённым значением.
&НаКлиенте
Процедура ЗапроситьСкидку(Команда)
ПоказатьВводСкидки(0);
КонецПроцедуры
&НаКлиенте
Процедура ПоказатьВводСкидки(НачальноеЗначение)
Оповещение = Новый ОписаниеОповещения("ПослеВводаСкидки", ЭтотОбъект);
ПоказатьВводЧисла(Оповещение, НачальноеЗначение, "Скидка, % (0–30)", 5, 2);
КонецПроцедуры
&НаКлиенте
Процедура ПослеВводаСкидки(Число, ДополнительныеПараметры) Экспорт
Если Число = Неопределено Тогда
Возврат;
КонецЕсли;
Если Число < 0 Или Число > 30 Тогда
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Скидка должна быть от 0 до 30 %.";
Сообщение.Сообщить();
ПоказатьВводСкидки(Число);
Возврат;
КонецЕсли;
Объект.ПроцентСкидки = Число;
КонецПроцедуры
Не крутите повторный запрос без выхода. Отмена всегда должна завершать цикл — проверка Число = Неопределено стоит первой.
Проверка прямо в поле формы
Часто диалог вообще не нужен: число вводят в поле реквизита на форме документа. Тогда проверку ставят в обработчик события поля ПриИзменении. Он срабатывает, когда пользователь ушёл из поля с новым значением.
&НаКлиенте
Процедура ПроцентСкидкиПриИзменении(Элемент)
Если Объект.ПроцентСкидки > 30 Тогда
Объект.ПроцентСкидки = 30;
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Скидка ограничена 30 %, значение исправлено.";
Сообщение.Поле = "Объект.ПроцентСкидки";
Сообщение.Сообщить();
КонецЕсли;
КонецПроцедуры
Свойство Поле привязывает сообщение к полю: пользователь увидит, где ошибка, и щелчком по сообщению перейдёт к нему. Для жёсткого запрета при записи добавьте проверку в модуль объекта, в обработчик ОбработкаПроверкиЗаполнения, — тогда документ с неверным числом не запишется ни из формы, ни из обработки.
Если число пришло строкой
Из файла, буфера или поля типа «Строка» число приходит текстом: "1 250,50". Функция Число() на такой строке упадёт с исключением. Очистите строку и оберните преобразование в Попытка:
&НаКлиентеНаСервереБезКонтекста
Функция СтрокаВЧисло(Знач Текст, ЗначениеПоУмолчанию = 0)
Текст = СтрЗаменить(Текст, " ", "");
Текст = СтрЗаменить(Текст, Символы.НПП, "");
Текст = СтрЗаменить(Текст, ",", ".");
Попытка
Возврат Число(Текст);
Исключение
Возврат ЗначениеПоУмолчанию;
КонецПопытки;
КонецФункции
Символы.НПП — неразрывный пробел. Его подставляет сама 1С при форматировании разрядов, и именно он чаще всего ломает обратное преобразование.
Клиент-серверный вариант: куда попадает введённое число
Диалог живёт на клиенте, а запись в базу, расчёты и запросы — на сервере. Число нужно явно передать параметром серверной процедуры:
&НаКлиенте
Асинх Процедура ПересчитатьЦены(Команда)
Процент = Ждать ВвестиЧислоАсинх(0, "Наценка, %", 6, 2);
Если Процент = Неопределено Тогда
Возврат;
КонецЕсли;
ПересчитатьЦеныНаСервере(Процент);
КонецПроцедуры
&НаСервере
Процедура ПересчитатьЦеныНаСервере(Процент)
Если Процент < 0 Или Процент > 500 Тогда
ВызватьИсключение "Недопустимая наценка: " + Формат(Процент, "ЧДЦ=2; ЧН=0");
КонецЕсли;
Для Каждого Строка Из Объект.Товары Цикл
Строка.Цена = Окр(Строка.Цена * (1 + Процент / 100), 2);
КонецЦикла;
КонецПроцедуры
Что учесть при таком разделении:
- 🔁 Проверку дублируйте на сервере. Клиентский код можно обойти, серверный — нет. Для записи в базу это обязательно.
- 📡 Один серверный вызов вместо пяти. Соберите все введённые значения на клиенте и передайте за один раз — каждый вызов сервера идёт по сети.
- 🚫 Фоновые задания, регламентные задания, HTTP-сервисы, обработчики
ПриЗаписивыполняются без пользовательского окна. Спрашивать там нечего — значение берите из параметров или настроек. - 🌐 Веб-клиент блокирует модальные окна независимо от вкуса разработчика, поэтому код для него — только
ПоказатьВводЧисла()или асинхронный вариант.
Своя форма для ввода чисел: когда стандартного окна мало
Стандартный диалог даёт одно поле и заголовок. Если нужно несколько чисел сразу, пояснение под полем, диапазон или кнопки «+/–», делайте свою форму. Обычно её создают в общей форме или в форме обработки.
Шаги
- Создайте форму, на вкладке Реквизиты добавьте реквизит
ЗначениетипаЧислос нужными длиной и точностью. Для неотрицательных значений в квалификаторе отметьте «Неотрицательное». - Перетащите реквизит на форму. В свойствах поля задайте
МинимальноеЗначениеиМаксимальноеЗначение— платформа не пропустит значение за границами. - Для мелкого шага включите у поля
КнопкаРегулирования— появятся стрелки увеличения и уменьшения. - На вкладке Параметры формы добавьте параметр
НачальноеЗначениетипаЧисло. - Добавьте команду «Готово» с обработчиком, который закрывает форму и возвращает число.
Код формы ввода:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Значение = Параметры.НачальноеЗначение;
КонецПроцедуры
&НаКлиенте
Процедура Готово(Команда)
Если ПроверитьЗаполнение() Тогда
Закрыть(Значение);
КонецЕсли;
КонецПроцедуры
Вызов из другой формы:
&НаКлиенте
Процедура ОткрытьВводНормы(Команда)
Параметры = Новый Структура("НачальноеЗначение", Объект.Норма);
Оповещение = Новый ОписаниеОповещения("ПослеВводаНормы", ЭтотОбъект);
ОткрытьФорму("ОбщаяФорма.ВводНормы", Параметры, ЭтотОбъект,,,,
Оповещение, РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);
КонецПроцедуры
&НаКлиенте
Процедура ПослеВводаНормы(Результат, ДополнительныеПараметры) Экспорт
Если Результат = Неопределено Тогда
Возврат; // форму закрыли крестиком
КонецЕсли;
Объект.Норма = Результат;
КонецПроцедуры
Значение, переданное в Закрыть(), приходит в обработчик оповещения первым параметром. Закрытие крестиком даёт Неопределено.
Режим БлокироватьОкноВладельца не делает форму модальной в смысле платформы. Он блокирует только окно-владелец и работает при режиме модальности «Не использовать».
Если реквизиту поставить флажок «Проверка заполнения: Выдавать ошибку», ПроверитьЗаполнение() не пропустит ноль. Учтите это: для числа «пусто» и «0» — одно и то же значение.
Как показать число пользователю: Формат() и свойства поля
Ввод — половина дела. Число нужно ещё правильно вывести: в сообщении, заголовке, печатной форме.
Функция Формат() принимает форматную строку из пар «ключ=значение» через точку с запятой:
| Ключ | Что делает | Пример | Результат |
|---|---|---|---|
ЧДЦ | знаков после запятой, с округлением | Формат(1234.567, "ЧДЦ=2") | 1 234,57 |
ЧГ=0 | убирает группировку разрядов | Формат(1234567, "ЧГ=0") | 1234567 |
ЧРД | разделитель дробной части | Формат(12.5, "ЧДЦ=2; ЧРД=.") | 12.50 |
ЧН | что выводить вместо нуля | Формат(0, "ЧН=—") | — |
ЧЦ | общее число разрядов | Формат(42, "ЧЦ=6; ЧВН=") | 000042 |
ЧВН | выводить ведущие нули | см. строку выше |
Склеивать число со строкой через «+» без Формат() нельзя: при значении 1250 в тексте появится 1 250 с неразрывным пробелом, а в коде документа или имени файла это ломает сравнение. Для идентификаторов всегда пишите Формат(Число, "ЧГ=0").
Ещё два приёма:
- 🧾
ЧислоПрописью()— сумма словами для печатных форм:ЧислоПрописью(1250.50, "Л=ru_RU", "рубль, рубля, рублей, м, копейка, копейки, копеек, ж, 2"). - 🖊️ Свойства поля формы
ФорматиФорматРедактирования. Первое управляет видом в списке, второе — видом при редактировании. Например,ЧДЦ=2в формате иЧГ=0в формате редактирования: в списке1 250,00, а при вводе цифры не прыгают из-за пробелов.
Частые вопросы
Можно ли ограничить ввод только целыми числами?
ПоказатьВводЧисла() или в квалификаторе типа. Дробную часть пользователь ввести не сможет.Почему ПоказатьВводЧисла() не ждёт ответа и код идёт дальше?
Ждать ВвестиЧислоАсинх().Как отличить отмену от ввода нуля?
Неопределено, а ноль — это число 0. В модальном ВвестиЧисло() смотрите на возвращаемое Истина/Ложь.Работает ли ввод числа в обычных формах толстого клиента?
ВвестиЧисло() при разрешённой модальности. Немодальные методы тоже доступны в обычном приложении на 8.3, но переписывать старый код без необходимости смысла нет.Как запросить сразу два числа, например количество и цену?
Закрыть() структуру с обоими значениями.