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