Практически в каждой организации в один прекрасный день начальнику приходит в голову мысль облегчить жизнь простым кладовщикам. Они, бедные набивают приходные накладные, в то время как их присылают нам по почте в электронном виде. И озадачивают штатного или внештатного программиста задачей сделать загрузку приходных накладных автоматической. Программист берется за дело и решает ее в короткий срок, что может быть проще взять файл (как правило, это документ екселя) и пробежаться по колонкам определяя колонку с наименованием номенклатуры, количеством, ценой. Как правило делают простую проверку – нашли номенклатуру по наименованию – выбрали, если не нашли номенклатуру - создаем новую автоматически и плевать что отличие только в запятой, все равно это новая номенклатура. Это приводит к тому, что справочник номенклатуры раздувается, и у нас появляются множество дублей номенклатуры, выбрать правильную становится труднее и начинаются проблемы с пересортицей, инвентаризацией и прочим. Если программист более опытный он выведет форму диалога, где предложит пользователю, который загружает данные, выбрать правильную номенклатуру или создать новую. Идеально если поиск при этом будет интеллектуальным и предложит варианты, которые имеют незначительные отклонения в названии номенклатуры. Давайте попробуем создать нечто подобное.
Сначала создадим обработку в ней нашу основную форму, на которой Поле табличного документа в первую колонку мы буде вносить наименование товара, а во вторую количество, цена будет жить в третей колонке.
Основой системы будет функция поиска номенклатуры, она будет использовать следующий механизм:
Общая структура обработки такая:
Основная форма выглядит так:
И имеет следующий код:
Процедура КоманднаяПанель1Настройки(Кнопка) // Вставить содержимое обработчика. форма = получитьформу("ФормаСохраненнихРешений"); форма.Открыть(); КонецПроцедуры Процедура КнопкаВыполнитьНажатие(Кнопка) // Вставить содержимое обработчика. КоличествоЭлементов = этаформа.ЭлементыФормы.ПолеТабличногоДокумента1.ВысотаТаблицы ; //Если КоличествоЭлементов <= 0 Тогда Предупреждение(КоличествоЭлементов); Для К = 2 По КоличествоЭлементов Цикл сообщить(этаформа.ЭлементыФормы.ПолеТабличногоДокумента1.Область("R"+Формат(к,"ЧГ=")+"C"+Формат(1,"ЧГ=")).Текст); названиеТМЦ=этаформа.ЭлементыФормы.ПолеТабличногоДокумента1.Область("R"+Формат(к,"ЧГ=")+"C"+Формат(1,"ЧГ=")).Текст; КоличествоТМЦ=этаформа.ЭлементыФормы.ПолеТабличногоДокумента1.Область("R"+Формат(к,"ЧГ=")+"C"+Формат(2,"ЧГ=")).Текст; ЦенаТМЦ=этаформа.ЭлементыФормы.ПолеТабличногоДокумента1.Область("R"+Формат(к,"ЧГ=")+"C"+Формат(3,"ЧГ=")).Текст; Сообщить(найтиТМЦ(названиеТМЦ)); конеццикла; КонецПроцедуры функция найтиТМЦ (наименованиеТМЦ) перем ТаблицаСоответствий; // данная функция ищет номенклатуру // сначала по наименованию // если не нашла по таблице соответствий // и в последнюю очередь задействует нечеткий поиск ТаблицаСоответствий = ВосстановитьЗначение("тс"); ТМЦ = справочники.Номенклатура; //ищем по точное соответствие наименованию ТмцСсылка=ТМЦ.НайтиПоНаименованию(наименованиеТМЦ,истина); если ТмцСсылка = ТМЦ.ПустаяСсылка() тогда // точное соответствие по наименованию не найдено // включаем поиск по таблице соответствий НайденнаяСтрока = ТаблицаСоответствий.Найти(наименованиеТМЦ, "Наименование"); Если НайденнаяСтрока = Неопределено Тогда // опять ничего не найдено нужно задействовать нечеткий поиск // тут все что разбирали в предыдущих примерах МассивОтбор = Новый Массив(); МассивОтбор.Добавить(Метаданные.Справочники.Номенклатура); Если Не ПолнотекстовыйПоиск.ИндексАктуален() Тогда Попытка Предупреждение("Пробуем обновить индекс. Это может занять некоторое время"); ПолнотекстовыйПоиск.ОбновитьИндекс(Истина, Ложь); Предупреждение("Все хорошо индекс обновлен!"); Исключение Предупреждение(("Упс! Ошибка при обновлении индекса!") + ОписаниеОшибки()); КонецПопытки; КонецЕсли; СписокПоиска = ПолнотекстовыйПоиск.СоздатьСписок("", 10); // первый параметр строка поиска, второй размер списка // указываем, в каких объектах искать строку СписокПоиска.ОбластьПоиска = МассивОтбор; СписокПоиска.ПолучатьОписание = Истина; ПоказыватьОписания = Истина; СписокПоиска.ПорогНечеткости = 25; //процент нечеткости для слова из 4 букв, одна может быть неправильной СписокПоиска.СтрокаПоиска = наименованиеТМЦ; // текст поиска можно задать и так СписокПоиска.РазмерПорции = 10; // а ето, сколько стандартно будет вывожится результатов СписокПоиска.ПерваяЧасть(); Колво = СписокПоиска.ПолноеКоличество(); Если СписокПоиска.ПолноеКоличество() = 0 Тогда Предупреждение("Начего не найдено!" ); Если СписокПоиска.СлишкомМногоРезультатов() Тогда Предупреждение("Найдено слишком много результатов!"); КонецЕсли; КонецЕсли; // теперь мы получаем в списке поиска массив объектов номенклатуры // которые в могут соответствовать названию номенклатуры // даже если найден только один объект пользователь должен // согласится с предложенным выбором // для начала очистим список выбора Списоквыбора.Очистить(); Для х = 1 По мин(СписокПоиска.ПолноеКоличество(),10) Цикл ВыбраннаяСтрока = списокПоиска[х-1]; списоквыбора.Добавить(ВыбраннаяСтрока.Значение); КонецЦикла; НазваниеТМЦ=наименованиеТМЦ ; // общий реквищит чтобы отобразился в форме выбора форма = получитьформу("ФормаВыбораВариантов"); ТмцСсылка = форма.ОткрытьМодально(); если ( ТмцСсылка = неопределено) тогда Сообщить("Вы ничего не выбрали, данная строка не импортируется!"); иначе // если пользователь выбрал какую-то номенклатуру // соответствие наименование - номенклатура нужно занести в таблицу соответствий НоваяСтрока = ТаблицаСоответствий.Добавить() ; сООБЩИТЬ(ТмцСсылка); НоваяСтрока.ТМЦ =ТмцСсылка; НоваяСтрока.наименование =наименованиеТМЦ; СохранитьЗначение("тс", ТаблицаСоответствий); возврат ТмцСсылка; Конецесли; Иначе ТмцСсылка = НайденнаяСтрока.тмц; возврат ТмцСсылка; КонецЕсли; иначе возврат ТмцСсылка; конецесли; конецфункции;
Как видите ми не создаем никакого документа мы просто выводим найденную номенклатуру в виде сообщений.
Вторая форма это форма выбора соответствий названия номенклатуры поставщика, с номенклатурой, внесенной в базу. Для примера я специально убрал дефис из названия номенклатуры, нечеткий поиск нашел две позиции номенклатуры. Выглядит так
Код модуля простой:
Процедура КнопкаВыполнитьНажатие(Кнопка) ОповеститьОВыборе(ЭлементыФормы.СписокТМЦ.ТекущаяСтрока.ЗНАЧЕНИЕ) КонецПроцедуры
И последняя форма, она скорее для галочки, чем для работы, просмотр таблицы соответствий, после нашего выбора номенклатуры она будет выглядеть так:
Если при следующей загрузке попадется наименование Футболка (кол. т.195) SXXL номенклатура Футболка (кол. т.195) S-XXL будет выбрана автоматически, таким чином у нас будет система, которая запоминает выбор пользователя и потом поступает аналогично.
И конечно код модуля:
Процедура ПриОткрытии() перем тс; // Востанавливаем значение из таблицы тс=ВосстановитьЗначение("тс"); если тс=неопределено тогда иначе ТаблицаСоответствий.Загрузить(тс ); конецесли; КонецПроцедуры Процедура ПередЗакрытием(Отказ, СтандартнаяОбработка) //сохраняем таблицу перем тс; тс= ТаблицаСоответствий.Выгрузить() ; СохранитьЗначение("тс", тс); КонецПроцедуры
Файл обработки выложу в рубрике разработки. Ссылка