При работе в конфигурации «1С:Торговля и Склад 9.2» (платформа 1С 7.7) пользователи часто сталкиваются с необходимостью быстро перенести весь список товаров из формы подбора в документ. В отличие от платформы 1С 8.x, где предусмотрено выделение произвольного количества строк с помощью клавиш Shift, Ctrl или комбинации Ctrl+A, платформа 1С 7.7 не имеет штатного интерактивного механизма выделения нескольких строк в таблицах списка.
В этой статье мы подробно разберем, как написать процедуру для кнопки формы подбора номенклатуры, которая позволит автоматически выбрать весь справочник (или товары с остатками на складе) и заполнить таблицу подбора номенклатурой, ценами, остатками и суммами.
Рассмотрим, как устроена форма подбора номенклатуры в типовых конфигурациях 1С 7.7. Когда открывается форма подбора, система использует элемент управления ТаблицаПодбора. При штатной работе включение режима множественного выбора (параметр ФлагМножественногоВыбора метода Выбрать() объекта справочника) лишь оставляет окно подбора открытым после каждого клика, позволяя добавлять товары по одному.
Однако если перед нами стоит задача мгновенного переноса сотен или тысяч позиций, кликать по каждому элементу вручную неэффективно. Для решения этой задачи добавим на форму подбора кнопку и привяжем к ней процедуру на языке 1С 7.7.
Проанализируем простейший алгоритм обхода справочника. Нам необходимо создать объект Справочник.Номенклатура, запустить выборку элементов с помощью метода ВыбратьЭлементы() и при помощи функции ЭтоГруппа() исключить из переноса папки номенклатуры.
Разберем пример кода процедуры кнопки подбора:
Процедура ВыбратьВсе()
Спр = СоздатьОбъект("Справочник.Номенклатура");
Спр.ВыбратьЭлементы();
Пока Спр.ПолучитьЭлемент() = 1 Цикл
Если Спр.ЭтоГруппа() = 1 Тогда
Продолжить;
КонецЕсли;
ТаблицаПодбора.НоваяСтрока();
ТаблицаПодбора.Номенклатура = Спр.ТекущийЭлемент();
ТаблицаПодбора.Единица = Спр.БазоваяЕдиница;
КонецЦикла;
КонецПроцедуры
В этом коде процедура последовательно перебирает все позиционные элементы справочника, добавляет новую строку в табличную часть ТаблицаПодбора и подставляет текущую номенклатуру с ее базовой единицей измерения.
Выясним, как ограничить выборку только теми позициями, которые находятся внутри открытой пользователем группы. Для этого применим метод ИспользоватьРодителя() объекта справочника:
Процедура ВыбратьВсеВГруппе()
Если ПустоеЗначение(ТекущийЭлемент().Родитель) = 0 Тогда
Спр = СоздатьОбъект("Справочник.Номенклатура");
Спр.ИспользоватьРодителя(ТекущийЭлемент().Родитель);
Спр.ВыбратьЭлементы(1); // Параметр 1 включает выборку с учетом иерархии
Пока Спр.ПолучитьЭлемент() = 1 Цикл
Если Спр.ЭтоГруппа() = 1 Тогда
Продолжить;
КонецЕсли;
ТаблицаПодбора.НоваяСтрока();
ТаблицаПодбора.Номенклатура = Спр.ТекущийЭлемент();
ТаблицаПодбора.Единица = Спр.БазоваяЕдиница;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
На практике часто требуется подбирать не все подряд позиционные элементы, а только те товары, которые фактически числятся на остатках выбранного склада и фирмы. Кроме того, в таблицу подбора нужно автоматически подтянуть цену из установленного типа цен и рассчитать итоговую сумму.
Для работы с остатками в типовой конфигурации «Торговля и Склад 9.2» используется глобальная функция глПолучитьОстаткиНоменклатуры(), а для цен — функция ПолучитьЦенуНоменклатуры().
Рассмотрим полный рабочий алгоритм с проверкой заполнения типа цен и фильтрацией нулевых остатков:
Процедура ВыбратьВсеСОстатками()
// Проверяем, выбран ли тип цен в документе
Если ТипЦен.Выбран() = 0 Тогда
Если ВвестиЗначение(ТипЦен, "Выберите тип цен", "Справочник.ТипыЦен") = 0 Тогда
Сообщить("Для расчета суммы необходимо выбрать тип цен!");
СтатусВозврата(0);
Возврат;
КонецЕсли;
КонецЕсли;
Спр = СоздатьОбъект("Справочник.Номенклатура");
Спр.ВыбратьЭлементы();
Пока Спр.ПолучитьЭлемент() = 1 Цикл
// Пропускаем группы номенклатуры
Если Спр.ЭтоГруппа() = 1 Тогда
Продолжить;
КонецЕсли;
ТовОстаток = 0;
ТовОстатокПоФирме = 0;
// Получаем актуальный остаток товара по заданным параметрам
глПолучитьОстаткиНоменклатуры(ФирмаДляОстатковТМЦ, Спр.ТекущийЭлемент(), Спр.БазоваяЕдиница, ОстаткиТМЦ, ТовОстаток, ТовОстатокПоФирме, Склад, Резервы, 1);
// Исключаем позиции с нулевым или отрицательным остатком
Если ТовОстаток <= 0 Тогда
Продолжить;
КонецЕсли;
// Добавляем строку в таблицу подбора
ТаблицаПодбора.НоваяСтрока();
ТаблицаПодбора.Номенклатура = Спр.ТекущийЭлемент();
ТаблицаПодбора.Единица = Спр.БазоваяЕдиница;
ТаблицаПодбора.Количество = ТовОстаток;
ТовЦена = 0;
ТовВалюта = "";
// Получаем цену товара и рассчитываем сумму
Если ПолучитьЦенуНоменклатуры(Спр.ТекущийЭлемент(), Спр.БазоваяЕдиница, ТовЦена, ТовВалюта) = 1 Тогда
ТаблицаПодбора.Цена = ТовЦена;
ТаблицаПодбора.Сумма = ТаблицаПодбора.Цена * ТаблицаПодбора.Количество;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Проанализируем рекомендации по улучшению работы данного кода и альтернативные пути решения аналогичных задач:
ВыбратьЭлементы() с вызовом функции получения остатка на каждом шаге цикла может работать медленно в больших информационных базах (десятки тысяч элементов). Для ускорения рекомендуется использовать объект Запрос к регистру ОстаткиТМЦ, который выбирает только позиции с остатком > 0 за один подход.1С++ (объект ТабличноеПоле) или FormEx.