Поиск документов по представлению

Часть 1. Многабукаф

Кому лень читать – можно сразу скроллить вниз к обработке.

Итак, задача поставлена, и теперь нам нужно понять, являются ли входящие строки представлениями документов.

Тут на помощь приходят регулярные выражения и шикарная публикация: Регулярные выражения без внешних компонент? Легко!

Точка входа в самом низу ОбработатьДокументы(МассивПредставлений) ей мы отдаем массив строк представлений.

&НаКлиенте
Функция ПостроитьФабрикуXDTO(Фасет)
	Чтение = Новый ЧтениеXML;
    Чтение.УстановитьСтроку(
                "<Model xmlns=""http://v8.1c.ru/8.1/xdto"" xmlns:xs=""http://www.w3.org/2001/XMLSchema"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xsi:type=""Model"">
                |<package targetNamespace=""sample-my-package"">
                |<valueType name=""testtypes"" base=""xs:string"">
                |<pattern>" + Фасет + "</pattern>
                |</valueType>
                |<objectType name=""TestObj"">
                |<property xmlns:d4p1=""sample-my-package"" name=""TestItem"" type=""d4p1:testtypes""/>
                |</objectType>
                |</package>
                |</Model>");

    Модель = ФабрикаXDTO.ПрочитатьXML(Чтение);
    МояФабрикаXDTO = Новый ФабрикаXDTO(Модель);
    Пакет = МояФабрикаXDTO.Пакеты.Получить("sample-my-package");
    Тест = МояФабрикаXDTO.Создать(Пакет.Получить("TestObj"));
	
	Возврат Тест;
КонецФункции

&НаКлиенте
Функция ПроверитьСтроку(Фабрика, Строка)
    Попытка
        Фабрика.TestItem = Строка;
        Возврат Истина;
    Исключение
        Возврат Ложь;
    КонецПопытки;
    
КонецФункции

&НаКлиенте
Функция ПроверитьПредставление(Фабрика, ДокументСтрокой)
	Возврат ПроверитьСтроку(Фабрика,ДокументСтрокой);
КонецФункции

&НаКлиенте
Функция ОбработатьДокументы(МассивПредставлений)
	ДокументыКОбработке = Новый Массив;
	
	Фабрика = ПостроитьФабрикуXDTO(".*\sот\s\d{2}\.\d{2}.\d{4}\s\d{1,2}:\d{2}:\d{2}");
	
	Для Каждого ДокументСтрокой ИЗ МассивПредставлений Цикл
		Если СокрЛП(ДокументСтрокой) = "" тогда
			Продолжить;
		КонецЕсли;
		ДокументСтрокойСЛП = СокрЛП(ДокументСтрокой);
		Если ПроверитьПредставление(Фабрика,ДокументСтрокойСЛП) тогда
			ДокументыКОбработке.Добавить(ДокументСтрокойСЛП);
		Иначе
			Сообщение = Новый СообщениеПользователю;
			Сообщение.Текст = "Строка """+ДокументСтрокойСЛП+""" не выглядит как представление документа";
			Сообщение.Сообщить();
		КонецЕсли;
	КонецЦикла;
	
	Результат = ОбработатьДокументыСервер(ДокументыКОбработке);
	
	Возврат Результат;
КонецФункции

Как вы знаете, строка документа состоит из синонима документа, номера и даты. Для определения вида документа по синониму построим список синонимов документов конфигурации:

&НаСервере
Функция ПолучитьТЗМетаданныхДокументов()
	КвалификаторыСтроки = Новый КвалификаторыСтроки(250);
    ОписаниеСтроки = Новый ОписаниеТипов("Строка", ,КвалификаторыСтроки);
	
	КвалификаторыЧисла = Новый КвалификаторыЧисла(3, 0, ДопустимыйЗнак.Неотрицательный);
    ОписаниеЧисла = Новый ОписаниеТипов("Число", КвалификаторыЧисла);
	
	ТЗМетаданные = Новый ТаблицаЗначений;
	ТЗМетаданные.Колонки.Добавить("Имя", ОписаниеСтроки);
	ТЗМетаданные.Колонки.Добавить("Синоним", ОписаниеСтроки);
	ТЗМетаданные.Колонки.Добавить("Вес", ОписаниеЧисла);
	
	Для Каждого ЭлементМетаданных ИЗ Метаданные.Документы Цикл
		НС = ТЗМетаданные.Добавить();
		ЗаполнитьЗначенияСвойств(НС,ЭлементМетаданных);
		НС.Вес = СтрДлина(ЭлементМетаданных.Синоним);
		Если ЗначениеЗаполнено(ЭлементМетаданных.ПредставлениеОбъекта) Тогда
			НС.Синоним = ЭлементМетаданных.ПредставлениеОбъекта;
		КонецЕсли;
	КонецЦикла;
	
	ТЗМетаданные.Сортировать("Вес Убыв,Синоним");
	Возврат ТЗМетаданные;
КонецФункции

Тут всё просто – пробежались по метаданным документов, собрали все синонимы и имена документов и отсортировали по убыванию длины строки. Большой соблазн сразу разбить строку представления по ” от “, но бывают синонимы документов, которые содержат ” от ” в своем тексте, например “Приход товаров от поставщика 1 от 03.05.2018 00:00:00″. Поэтому искать будем от максимальной длины строки. Кто-то может захотеть искать последний ” от ” в представлении, но мне захотелось так.

Ну и, наконец, собираем всё в кучку:

//Возвращает документ по имени, номеру и дате
&НаСервере
Функция ВернутьДок(Имя,НомерДок,ДатаДок)
	Возврат Документы[Имя].НайтиПоНомеру(НомерДок,ДатаДок);
КонецФункции

&НаСервере
Функция ОбработатьДокументыСервер(СписокПредставлений)
	//Построили ТЗ синонимов и имен документов
	ТЗМетаданных = ПолучитьТЗМетаданныхДокументов();
	МассивСсылок = Новый Массив; ///Пустой массив результата
	//Для каждой строки из списка представлений
	Для Каждого ПредставлениеДок ИЗ СписокПредставлений Цикл
		//Пробегаем по имеющимся синонимам метаданных от самых длинных
		//Тут, конечно, можно покопаться с грязной строкой и не бегать
		//по ТЗ синонимов, а получить просто отбором, но мне лень
		Для Каждого ШаблонПоиска ИЗ ТЗМетаданных Цикл
			//и прикладываем к имеющейся "грязной" строке документа
			Если Найти(ПредставлениеДок,ШаблонПоиска.Синоним) Тогда
				//Если нашли - исключаем из неё синоним,
				//Теперь нужно получить из хвоста номер и дату
				СтрокаНомерДата = СокрЛП(СтрЗаменить(ПредставлениеДок,ШаблонПоиска.Синоним,""));
				//Разбили по " от " хвост. В первом элементе массива номер - во втором дата
				МассивНомерДата = СтрокаВМассивСтрок(СтрокаНомердата," от ");
				НомерДок = СокрЛП(МассивНомерДата[0]);
				//Пересоберем дату строкой к типу Дата 1С
				СтрокаДата = СокрЛП(МассивНомерДата[1]);
				ДатаПоЭлементам = СтрЗаменить(СтрЗаменить(СтрокаДата," ",":"),".",":");
				МассивЭлементовДаты = СтрокаВМассивСтрок(ДатаПоЭлементам,":");
				//02.06.2017 16:02:44
				// 0  1    2  3  4  5
				ДатаДок = Дата(МассивЭлементовДаты[2],МассивЭлементовДаты[1],МассивЭлементовДаты[0],
				  	       МассивЭлементовДаты[3],МассивЭлементовДаты[4],МассивЭлементовДаты[5]);
				//Получим нужный документ	
				НайденныйДок = ВернутьДок(ШаблонПоиска.Имя,НомерДок,ДатаДок);
				Если ЗначениеЗаполнено(НайденныйДок) Тогда
					//Нашли и добавили в массив ссылок
					МассивСсылок.Добавить(НайденныйДок);
				Иначе
					Сообщение = Новый СообщениеПользователю;
					Сообщение.Текст = "Документ """+ПредставлениеДок+""" не найден";
					Сообщение.Сообщить();
				КонецЕсли;
				Прервать;
			КонецЕсли;
		КонецЦикла;
	КонецЦикла;
	Возврат МассивСсылок;
КонецФункции

Ну вот, вкратце, так. Вы можете использовать куски кода и написать свою обработку, а можете скачать за 1$m нижеописанную обработку, чем порадуете меня и сэкономите свое время.

Часть 2. Обработка

Итак, для ленивых, и тех, кто просто хочет поделиться $m.

Так как обычно я нищенствую, я не знаю, чем обработка отличается от других, присутствующих на инфостарте, ибо я их не скачивал.

Тестировалась на платформах: 8.2.19+, 8.3.11

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

В КАТАЛОГ »