Расширенная функция поиска строк по таблице значений

20.05.25

Разработка - Универсальные функции

Статья описывает функцию расширенного поиска по таблице значений, что она может, и как ей пользоваться.

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

На практике приходится искать по другим критериям – таким, как:

  1. Сравнивать значение в колонки с заданным не только по операнду сравнения, а, например, "больше некоторого значения" или "нахождения в списке"
  2. Сравнивать значения между колонками. Если условие сравнения выполняется, тогда строка должна попадать в результат
  3. Находить колонки, в которых значение значения реквизита равно «чему-то» определенному или больше/меньше «чего-то» определенного
  4. Вычислить функцию от значения в колонке, с чем-то сравнить и если результат будет "чем-то ", тогда включаем строку в массив результата.

Для этих целей служит функция "НайтиСтроки", указанная в этой статье.
Эта функция по аналогии со штатной "НайтиСтроки" также возвращает массив найденных строк.

 

//Осуществляет поиск по таблице значений. Возвращает массив найденных строк
//Параметры:
//	тзТаблица - ТаблицаЗначений - по ней идет поиск
//	Отбор - Строка,Структура,Соответствие - Условия поиска
// 		 - Структура - Выполняет поиск также как и встроеннная функция таблицы значений "НайтиСтроки"
//		 - Соответствие - В соответствии можно указать не только имя колонки, но и имя подчиненного значения в колонке. 
//			Например. Если есть колонка "Номенклатура", тлогда можно производить поиск по родителю этой номенклатуры, указав так "Номенклатура.Родитель"
//			Здесь через пробел также можно писать условия сравнения, например "Номенклатура.Родитель <>". Это означает, что выберуться только те строки, 
//			номенклатура которых не имеет родителя переданного в значении
//		 - Строка - Два варианта: 
//			1) В строке можно тоже указать как путь, по которому происходит сравнение, так и условие сравнения и строковое значение, Например:
//				"Номенклатура.Родитель = Варежки" Тогда функция вернет только те строки, Родитель номенклатуры которых имеет представление "Варежки"
//                2) Указать строковое значение. Тогда найдутся те строки, Значения колонок которых равно указанному
//                3) Написать текст подпрограммы, заключенный в {{ .. }}, которая проверяет значение в колонке. Подпрограмма должна возвращать ИСТИНА, если значение соответствует требуемому. 
//			Чтобы подпрогррамма возвращала ИСТИНУ или ЛОЖЬ в ней необходимо результат привоить переменной "Результат".
//				Пример: "{{Результат =  стрНайти(Строка(Данные),""Агароза"")>0}}". Вернет те строки таблицы,  в которых в значении присутствует "Агароза"
//              4) Написать вызов функции и произвести сравнение результата. Чтобы в качестве аргумента вставить в функцию значение, взятое из определенной колонки таблицы, необходимо Имя получения из колонки заключить в скобки "{}"
//			Пример: Если Отбор = "стрНайти({Номенклатура.Родитель},"виды")>0", тогда функция вернет строки, наименование родителя номенклатуры которого содержит "виды"
//			можно также сравнивать значения дыух колонок, указав в {} имя второй колонки. Например: "Строка({Номенклатура.Родитель}) = Строка({Товар.Родитель})"  - вернет те строки у которых совпадает родитель значения колонок "Номенклатура" и "Товар"
//
Функция НайтиСтроки(тзТаблица,Отбор) Экспорт
	мсвРезультат = НОвый Массив;
	Если ТипЗнч(Отбор) = Тип("Структура") Тогда
		Возврат тзТаблица.НайтиСтроки(Отбор);
	ИначеЕсли ТипЗнч(Отбор) = Тип("Соответствие") Тогда	
		//Необходимо разделить на простые условия и сложные
		сткОтбор = Новый Структура;
		мсвОтбор = Новый Массив;
		Для каждого Элемент Из Отбор Цикл
			Ключ = Элемент.Ключ;
			СтрПодобнаПоРегулярномуВыражению(Ключ,"\w+");
			Если СтрПодобнаПоРегулярномуВыражению(Ключ,"\w+") Тогда
				сткОтбор.Вставить(Элемент.Ключ,Элемент.Значение);
			Иначе
				сткУсловие = РазложитьУсловиеОтбора(Ключ);
				Если Элемент.Значение<>Неопределено Тогда
					сткУсловие.	ПравоеЗначение = Элемент.Значение;
				КонецЕсли;
				мсвОтбор.Добавить(сткУсловие);
			КонецЕсли;
		КонецЦикла;
		
		КоллекцияСтрок = Неопределено;
		Если сткОтбор.Количество()>0 Тогда
			КоллекцияСтрок = тзТаблица.НайтиСтроки(сткОтбор);
		Иначе			
			КоллекцияСтрок = тзТаблица;	
		КонецЕсли;
		
		Если НЕ ЗначениеЗаполнено(КоллекцияСтрок) Тогда
			//Условие уже не выполнилось;
			Возврат мсвРезультат;
		КонецЕсли;
		
		Если мсвОтбор.Количество()=0 Тогда
			Возврат КоллекцияСтрок;
		КонецЕсли;
		
		мсвУсловияОтбора = Новый Массив;
		
		
		Для каждого СтрокаДанных Из КоллекцияСтрок Цикл
			ФлВыполненоУсловие = ИСТИНА;
			Для каждого Элемент Из мсвОтбор Цикл
				Если НЕ ПринадлежитОтбору(СтрокаДанных,Элемент) Тогда
					ФлВыполненоУсловие = ЛОЖЬ;
					Прервать;
				КонецЕсли;
			КонецЦикла; 
			
			Если НЕ ФлВыполненоУсловие Тогда
				Продолжить;
			КонецЕсли;
			
			мсвРезультат.Добавить(СтрокаДанных);
			
		КонецЦикла;
		Возврат мсвРезультат;
	ИначеЕсли ТипЗнч(Отбор) = Тип("Строка") Тогда
		//Проверка на строковое условие сравнения, что СокрЛП(ЗначениеКолонкиТаблицы) = Строка в отборе
		Если Лев(Отбор,2)="{{" И Прав(Отбор,2)="}}" Тогда
			//Значит передана подпрограмма
			ТекстМодуля = Сред(Отбор,3,стрДлина(Отбор)-4);
			Для каждого СтрокаДанных Из тзТаблица Цикл
				Если УсловиеВыполнено(СтрокаДанных,ТекстМодуля) Тогда
					мсвРезультат.Добавить(СтрокаДанных);
				КонецЕсли;
			КонецЦикла;
			Возврат мсвРезультат;
		КонецЕсли;
		
		
		сткУсловиеОтбора = РазложитьУсловиеОтбора(Отбор);
		Для каждого СтрокаДанных Из тзТаблица Цикл
			Если ПринадлежитОтбору(СтрокаДанных,сткУсловиеОтбора) Тогда
				мсвРезультат.Добавить(СтрокаДанных);
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;
	Возврат мсвРезультат;	

КонецФункции // ()


//Преобразует строку условий в Структуру
Функция РазложитьУсловиеОтбора(УсловиеОтбора)
	
	Результат = Новый Структура("ЛеваяЧасть,Операция,ПраваяЧасть,ФункцияЛевойЧасти,ФункцияПравойЧасти,ПравоеЗначение");
	Результат.Вставить("СравниватьКакСтроки",ЛОЖЬ);
	
	Операция = Неопределено;	ПраваяЧасть = "";
	//поищем символы сравнения внутри строки
	РезультатПоиска = СтрНайтиПоРегулярномуВыражению(УсловиеОтбора,"(\s*[>~<=]+\s*)");
	Если РезультатПоиска.НачальнаяПозиция>0 Тогда
		Операция = СокрЛП(РезультатПоиска.Значение); 
		ЛеваяЧасть = Лев(УсловиеОтбора,РезультатПоиска.НачальнаяПозиция-1);
		ПраваяЧасть = Сред(УсловиеОтбора,РезультатПоиска.НачальнаяПозиция + РезультатПоиска.Длина);
	Иначе
		//Символов сравнения нет. Тогда поищем пробелы
		Позиция = стрНайти(УсловиеОтбора," ");
		Если Позиция>0 Тогда
			ЛеваяЧасть = Лев(УсловиеОтбора,Позиция-1);
			Операция = СокрЛП(Сред(УсловиеОтбора,Позиция+1));
			нрегОперация = нрег(Операция);
			Если стрНайти(нрегОперация,"содержит ")=1 Тогда
				ПраваяЧасть = Сред(Операция,10);
				Операция = "СОДЕРЖИТ"	;
			ИначеЕсли стрНайти(нрегОперация,"не содержит ")=1 Тогда
				ПраваяЧасть = Сред(Операция,13);
				Операция = "НЕ СОДЕРЖИТ"	;
			ИначеЕсли стрНайти(нрегОперация,"в списке ")=1 Тогда
				ПраваяЧасть = Сред(Операция,10);
				Операция = "В СПИСКЕ"	;
			ИначеЕсли стрНайти(нрегОперация,"не в списке ")=1 Тогда
				ПраваяЧасть = Сред(Операция,13);
				Операция = "В СПИСКЕ"	;
			КонецЕсли;
		Иначе
			ЛеваяЧасть  =  УсловиеОтбора;
			ПраваяЧасть = "";
		КонецЕсли; 
	КонецЕсли;

	
	РезультатПоиска = СтрНайтиПоРегулярномуВыражению(ЛеваяЧасть,"\{[\w.]+\}");
	Если РезультатПоиска.НачальнаяПозиция>0 Тогда
		Результат.ФункцияЛевойЧасти = ЛеваяЧасть;
		ЛеваяЧасть = Сред(ЛеваяЧасть,РезультатПоиска.НачальнаяПозиция+1,РезультатПоиска.Длина-2);
	КонецЕсли;
	
	Если ПраваяЧасть<>"" Тогда
		РезультатПоиска = СтрНайтиПоРегулярномуВыражению(ПраваяЧасть,"\{[\w.]+\}");
		Если РезультатПоиска.НачальнаяПозиция>0 Тогда
			Результат.ФункцияПравойЧасти = ПраваяЧасть;
			ПраваяЧасть = Сред(ПраваяЧасть,РезультатПоиска.НачальнаяПозиция+1,РезультатПоиска.Длина-2);
		Иначе
			//Определим, вдруг справа стоит функция
			РезультатПоиска = СтрНайтиПоРегулярномуВыражению(ПраваяЧасть,"\{[\w.]+\(.*\)\}"); 
			Если РезультатПоиска.НачальнаяПозиция>0 Тогда
				Результат.ФункцияПравойЧасти = Сред(ПраваяЧасть,РезультатПоиска.НачальнаяПозиция+1,РезультатПоиска.Длина-2);	
			Иначе
				//Посмотрим, вдруг правое значение представлено списком
				РезультатПоиска = СтрНайтиПоРегулярномуВыражению(ПраваяЧасть,"\{[\w.]+\(.*\)\}"); 
				Результат.ПравоеЗначение = ПраваяЧасть;
			КонецЕсли;
			
			ПраваяЧасть = "";
		КонецЕсли;
	КонецЕсли;
	
	
	Если НЕ ЗначениеЗаполнено(Операция) Тогда
		Операция = "=";
	КонецЕсли;
	
	Результат.ЛеваяЧасть = ЛеваяЧасть;
	Результат.ПраваяЧасть = ПраваяЧасть;
	Результат.Операция = Операция;
		
	
	Возврат Результат;
КонецФункции // ()


//Проверяет, что данные удовлетворяют условию Отбора
Функция ПринадлежитОтбору(Данные,Знач УсловиеОтбора) Экспорт
	
	Если ТипЗнч(УсловиеОтбора)=Тип("Структура") Тогда
		сткЧастиУсловия = УсловиеОтбора;
	Иначе
		сткЧастиУсловия = РазложитьУсловиеОтбора(УсловиеОтбора);	
	КонецЕсли;
	
	
	ЛевоеЗначение = ПолучитьРеквизит(Данные,сткЧастиУсловия.ЛеваяЧасть);
	Если ЗначениеЗаполнено(сткЧастиУсловия.ФункцияЛевойЧасти) Тогда
		АргументЗамены = "{"+сткЧастиУсловия.ЛеваяЧасть+"}";
		Если стрНайти(сткЧастиУсловия.ФункцияЛевойЧасти,АргументЗамены)>0 Тогда
			Выражение = стрЗаменить(сткЧастиУсловия.ФункцияЛевойЧасти,АргументЗамены,"ЛевоеЗначение");
			ЛевоеЗначение = Вычислить(Выражение);
		Иначе	
			ЛевоеЗначение = Вычислить(сткЧастиУсловия.ФункцияЛевойЧасти+"(ЛевоеЗначение)");
		КонецЕсли;
	КонецЕсли;
	
	
	Если ЗначениеЗаполнено(сткЧастиУсловия.ПраваяЧасть) Тогда
		ПравоеЗначение = ПолучитьРеквизит(Данные,сткЧастиУсловия.ПраваяЧасть); 
		Если ЗначениеЗаполнено(сткЧастиУсловия.ФункцияПравойЧасти) Тогда
			АргументЗамены = "{"+сткЧастиУсловия.ПраваяЧасть+"}";
			Если стрНайти(сткЧастиУсловия.ФункцияПравойЧасти,АргументЗамены)>0 Тогда
				Выражение = стрЗаменить(сткЧастиУсловия.ФункцияПравойЧасти,АргументЗамены,"ПравоеЗначение");
				ПравоеЗначение = Вычислить(Выражение);
			Иначе
				ПравоеЗначение = Вычислить(сткЧастиУсловия.ФункцияПравойЧасти+"(ПравоеЗначение)");	
			КонецЕсли;
		КонецЕсли;
	ИначеЕсли ЗначениеЗаполнено(сткЧастиУсловия.ФункцияПравойЧасти) Тогда	
		ПравоеЗначение = Вычислить(сткЧастиУсловия.ФункцияПравойЧасти);
	Иначе
		ПравоеЗначение = сткЧастиУсловия.ПравоеЗначение;	
	КонецЕсли;
	
	
	УсловиеСравнения = ВРЕГ(сткЧастиУсловия.Операция);	
	Если ПравоеЗначение<>Неопределено Тогда
		Если ТипЗнч(ПравоеЗначение)<>ТипЗнч(ЛевоеЗначение) Тогда
			Если ТипЗнч(ПравоеЗначение)<>Тип("Массив") И ТипЗнч(ПравоеЗначение)<>Тип("СписокЗначений") Тогда
				ЛевоеЗначение = Строка(ЛевоеЗначение);
				ПравоеЗначение = Строка(ПравоеЗначение);
			КонецЕсли;
		КонецЕсли;
	КонецЕсли;
	
	
	Если УсловиеСравнения="=" И ЛевоеЗначение = ПравоеЗначение Тогда
		Возврат ИСТИНА;
	ИначеЕсли УсловиеСравнения="<>" И ЛевоеЗначение <> ПравоеЗначение Тогда
		Возврат ИСТИНА;
	ИначеЕсли УсловиеСравнения=">" И ЛевоеЗначение > ПравоеЗначение Тогда
		Возврат ИСТИНА;
	ИначеЕсли УсловиеСравнения=">=" И ЛевоеЗначение >= ПравоеЗначение Тогда
		Возврат ИСТИНА;
	ИначеЕсли УсловиеСравнения="<" И ЛевоеЗначение < ПравоеЗначение Тогда
		Возврат ИСТИНА;
	ИначеЕсли УсловиеСравнения="<=" И ЛевоеЗначение <= ПравоеЗначение Тогда
		Возврат ИСТИНА;
	ИначеЕсли (УсловиеСравнения)="В СПИСКЕ" Тогда
		Если ТипЗнч(ПравоеЗначение)=Тип("Массив") Тогда
			Возврат ПравоеЗначение.Найти(ЛевоеЗначение)<>Неопределено;
		ИначеЕсли ТипЗнч(ПравоеЗначение)=Тип("СписокЗначений") Тогда	
			Возврат ПравоеЗначение.НайтиПоЗначению(ЛевоеЗначение)<>Неопределено;
		КонецЕсли;
	ИначеЕсли (УсловиеСравнения)="НЕ В СПИСКЕ" Тогда	
		Если ТипЗнч(ПравоеЗначение)=Тип("Массив") Тогда
			Возврат ПравоеЗначение.Найти(ЛевоеЗначение)=Неопределено;
		ИначеЕсли ТипЗнч(ПравоеЗначение)=Тип("СписокЗначений") Тогда	
			Возврат ПравоеЗначение.НайтиПоЗначению(ЛевоеЗначение)=Неопределено;
		КонецЕсли;	
	ИначеЕсли (УсловиеСравнения)="ЗАПОЛНЕНО"  Тогда	
		Возврат  ЗначениеЗаполнено(ЛевоеЗначение);
	ИначеЕсли (УсловиеСравнения)="НЕ ЗАПОЛНЕНО" Тогда
		Возврат НЕ  ЗначениеЗаполнено(ЛевоеЗначение);
	ИначеЕсли (УсловиеСравнения)="~"  Тогда	
		Возврат СтрПодобнаПоРегулярномуВыражению(ЛевоеЗначение,ПравоеЗначение);
	ИначеЕсли (УсловиеСравнения)="СОДЕРЖИТ"  Тогда	
		стрТекущееЗначение = нрег(Строка(ЛевоеЗначение));
		стрЗначениеСравнения = нрег(Строка(ПравоеЗначение));
		Возврат стрНайти(стрТекущееЗначение,стрЗначениеСравнения)>0;
	ИначеЕсли (УсловиеСравнения)="НЕ СОДЕРЖИТ"  Тогда	
		стрТекущееЗначение = нрег(Строка(ЛевоеЗначение));
		стрЗначениеСравнения = нрег(Строка(ПравоеЗначение));
		Возврат стрНайти(стрТекущееЗначение,стрЗначениеСравнения)=0;
	КонецЕсли;
	Возврат ЛОЖЬ;

КонецФункции // ()





//Возвращает значение реквизита из данных по пути
Функция ПолучитьРеквизит(Данные,Знач ИмяРеквизита,ЗначениеПоУмолчанию = Неопределено) Экспорт
	Если НЕ ЗначениеЗаполнено(ИмяРеквизита) Тогда
		Возврат ЗначениеПоУмолчанию;
	КонецЕсли; 
	
	Позиция = стрНайти(ИмяРеквизита,".");
	СледующееИмяРеквизита = Неопределено;
	Если Позиция>0 Тогда
		СледующееИмяРеквизита = Сред(ИмяРеквизита,Позиция+1);
		ИмяРеквизита = Лев(ИмяРеквизита,Позиция-1);
	КонецЕсли;
	
			
		
	сткЗначения = Новый Структура(ИмяРеквизита);
	ЗаполнитьЗначенияСвойств(сткЗначения,Данные);
	Если сткЗначения[ИмяРеквизита] = Неопределено Тогда
		Возврат ЗначениеПоУмолчанию;
	КонецЕсли;
		
	Результат =  сткЗначения[ИмяРеквизита];

	Если ЗначениеЗаполнено(СледующееИмяРеквизита) Тогда
		Возврат ПолучитьРеквизит(Результат,СледующееИмяРеквизита,ЗначениеПоУмолчанию);
	КонецЕсли;
	Возврат Результат;
КонецФункции // ()

//Выполняет текст 
Функция УсловиеВыполнено(Данные,___Условие,Ошибка = "") Экспорт
	___ТекстМодуля = "";
	Параметры = Неопределено;
	Результат = ЛОЖЬ;
	
	Если ТипЗнч(___Условие)=Тип("Строка") Тогда
		___ТекстМодуля = ___Условие;	
	ИначеЕсли ТипЗнч(___Условие)=Тип("Структура") Тогда	
		___Условие.Свойство("ТекстМодуля",___ТекстМодуля);
		___Условие.Свойство("Параметры",Параметры);
	Иначе
		Возврат ЛОЖЬ;
	КонецЕсли; 
	
	Если ЗначениеЗаполнено(___ТекстМодуля) Тогда
		Попытка
			Выполнить(___ТекстМодуля);
		Исключение
			Ошибка = ОписаниеОшибки();		
			Результат = ЛОЖЬ;
		КонецПопытки;
	КонецЕсли;
	
	Возврат Результат;	

КонецФункции // ()

 

Первый аргумент: таблица значений, в которой мы ищем строки.

Второй аргумент "Отбор": это условие, по которому происходит отбор.

 

Если Отбор - структура, тогда функция работает также, как штатная.

 

Начну с описания случая, когда Отбор - строка, т.к. его понимание приведет к пониманию того, как пользоваться случаем, когда "Отбор" - соответствие.

Пусть Таблица, по которой идет поиск имеет три колонки "Номенклатура", "Товар", "Количество", "Цена", "Сумма".

  • Колонки "Номенклатура" и "Товар" - ссылки на справочник "Номенклатура". При этом не всегда значение в колонке "Товар" совпадает со значением в колонке "Номенклатура".
  • Колонки "Количество", "Цена", "Сумма" - числовые.

Самый простой случай - это когда мы задаем в "Отборе" программный код, заключенный между "{{" и "}}". Внутри этого кода можно обратиться к переменной "Данные", которая будет содержать строку таблицы, а в переменную "Результат" необходимо занести ИСТИНА или ЛОЖЬ, как результат выполнения. Если "Результат" будет ИСТИНА, тогда строка таблицы попадет в массив найденных строк.

Например, если аргумент "Отбор" указан как:

Отбор = "{{Если Строка(Данные.Номенклатура)  = Строка(Данные.Товар) Тогда Результат = ИСТИНА Иначе Результат = ЛОЖЬ}}";

В этом случае функция вернет массив строк, в которых представление значения в колонках "Товар" и "Номенклатура" одинаковые.


Более сложный случай – мы в отборе указываем на имя колонки, операнд сравнения и то, с чем сравниваем. Если это условие будет выполнено, тогда строка таблицы попадет в результат. В общем случае этот вариант выглядит так:

Отбор = "ЛевоеЗначение ОперандСравнения [ПравоеЗначение]";

Где:

ОперандСравнения – одно из возможных значений "=", ">", "<", ">=", "<=", "В СПИСКЕ", "НЕ В СПИСКЕ", "ЗАПОЛНЕНО", "НЕ ЗАПОЛНЕНО", "СОДЕРЖИТ", "НЕ СОДЕРЖИТ", "~"

  • Операнд "~" означает, что надо проверить правое значение на совпадение с регулярным выражением, указанным в правой части.
  • При операнде "ЗАПОЛНЕНО" и "НЕ ЗАПОЛНЕНО" правая часть не должна иметь ничего, т.к. эти операнды проверяют левое значение на «заполненность».
  • Операнды: "СОДЕРЖИТ", "НЕ СОДЕРЖИТ" проверяют вхождение правого значения в левом.

ЛевоеЗначение – это значение, полученное из колонки и каким-то образом обработанное. Чтобы получить "Левое значение" из колонки можно:

  1. Указать имя колонки напрямую, например: "Товар" или "Номенклатура". Тогда в качестве Левого значения будет взято значение этой колонки.
  2. Указать путь имени реквизита значения колонки через символ точки. Пример: "Номенклатура.Родитель.Наименование". В этом случае в качестве левого значения будет наименование родителя номенклатуры.
  3. Указать путь имени реквизита и функцию его модификации. При этом чтобы значение, взятое по пути, попало аргументом в функцию, необходимо путь заключить в скобки "{}".
    Пример: "Лев({Номенклатура.Родитель},5)". В качестве левого значения будет взято 5 символов из представления "родителя" значения колонки "Номенклатуры"

ПравоеЗначение можно задать одним из следующих образов:

  • Взять конкретную строку, указанную после операндов. В этом случае операнды: "В СПИСКЕ", "НЕ В СПИСКЕ", "СОДЕРЖИТ", "НЕ СОДЕРЖИТ" должны быть отделены пробелом от строки операнда.
  • Использовать функцию или значение, взятое из определенной колонки по аналогии с п.3. Пример: "Лев(Лев({Товар.Родитель},5))". В этом примере в качестве правого значения возьмется первые 5 символов представления значения родителя.
  • Использовать функцию без вызова колонки. Тогда функцию нужно экранировать скобками {}, иначе она воспримется как строка символов. Пример: {Число(4)}

Следует отметить, что если тип левого значения не совпадает с типом правого, тогда сравнение происходит "строковое". Оба значения приводятся перед сравнением к строке, за исключением случая, когда правое значение - массив или список значений.

 

А теперь примеры.

Пример 1. Найдем колонки, в которых значение колонки "Цена" равна значению в колонке "Сумма":

Отбор = "Цена = {Сумма}";
мсвСтроки = НайтиСтроки(ТЗ,Отбор);

 
Пример 2. Найдем колонки, у которых цена больше 2.

Отбор = "Цена>{Число(2)}";

Здесь мы привели "2" к числу. Если этого не делать, а написать так "Цена> 2", тогда та цена, равная 10 не попадет, т.к. "2" функция посчитает, что это строка и приведет 10 к строке "10". Строка "10" меньше строки "2", т.к. символ "1" идет перед символом "2".


Пример 3. Найдем колонки, у которых наименование родителя значения колонки "Номенклатура" содержат 5 первых символов наименования родителя значения из колонки "Товар":

Отбор = "{Номенклатура.Родитель} СОДЕРЖИТ Лев({Товар.Родитель},5)";


Пример 4. Найдем строки, в которых представление значения колонки "Номенклатура" вначале содержит любые символы, а в конце обязательно цифры:

Отбор = "{Номенклатура} ~ .+\d+";

Здесь мы прибегли к использованию регулярных выражений.


Теперь можно перейти к случаю, когда Отбор  - соответствие.
Ключ каждого элемента соответствия это по сути строка условия, описанного выше. Только вместо правого значения можно использовать значение элемента соответствия.
Это удобно сделать, когда Левое значение надо проверить на вхождение в массив или список значений с использованием операндов "В СПИСКЕ"  или "НЕ В СПИСКЕ" или не приводить значение из строки в Число, как это было в примере 2. Все элементы соответствия объединяются по условию "И".

Пример 5. Необходимо найти те строки, у которых значение в колонке Сумма больше 5.

Отбор = Новый Соответствие;
Отбор.Вставить("Сумма >",5);
мсвСтроки = НайтиСтроки(ТЗ,Отбор);


Пример 6. Найти строки, у которых не заполнена цена:

Отбор.Вставить("Цена не заполнено");


Пример 7. Найти строки, у которых представление родителя номенклатуры находится в некотором списке, состоящем из "Пирожки" и "Тарелки". При этом реквизит номенклатуры "ТипНомеклатуры"   -  не является услугой и при этом номенклатура не является группой.

мсвСписок = Новый Массив; //Здесь сам список 
мсвСписок.Добавить("Пирожки");
мсвСписок.Добавить("Тарелки");

Отбор = Новый Соответствие;
Отбор.Вставить("Строка({Номенклатура.Родитель}) В СПИСКЕ",мсвСписок); //Приводим "Родителя к представлению через функцию "Строка(...)""
Отбор.Вставить("Номенклатура.ТипНоменклатуры <>",Перечисления.ТипыНоменклатуры.Услуга); //Сравниваем с услугой
Отбор.Вставить("Номенклатура.ЭтоГруппа",ЛОЖЬ); //Операнд "=" можно опускать
мсвСтроки = НайтиСтроки(ТЗ,Отбор);

 

 

ТаблицаЗначений Поиск НайтиСтроки Отбор

См. также

Универсальные функции Программист Платформа 1С v8.3 1C:Бухгалтерия Бесплатно (free)

Благодаря этим пяти строчкам можно больше не заморачиваться с загрузкой из внешних файлов. Пользуюсь везде, всегда и постоянно.

21.05.2024    33050    dimanich70    83    

154

Универсальные функции Программист Платформа 1С v8.3 1C:Бухгалтерия Абонемент ($m)

Задача: вставить картинку из буфера обмена на форму средствами платформы 1С.

1 стартмани

18.03.2024    5216    6    John_d    11    

57

Универсальные функции Программист Стажер Платформа 1С v8.3 1C:Бухгалтерия Бесплатно (free)

Пришлось помучиться с GUID-ами немного, решил поделиться опытом, мало ли кому пригодится.

12.02.2024    38173    atdonya    29    

62

Универсальные функции Программист Платформа 1С v8.3 Бесплатно (free)

На заключительных этапах, когда идет отладка или доработка интерфейса, необходимо много раз переоткрыть внешний объект. Вот один из способов автоматизации этого.

30.11.2023    6831    ke.92@mail.ru    17    

66

WEB-интеграция Универсальные функции Механизмы платформы 1С Программист Платформа 1С v8.3 1C:Бухгалтерия Бесплатно (free)

При работе с интеграциями рано или поздно придется столкнуться с получением JSON файлов. И, конечно же, жизнь заставит проверять файлы перед тем, как записывать данные в БД.

28.08.2023    18754    YA_418728146    8    

173

Пакетная печать Печатные формы Адаптация типовых решений Универсальные функции Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Россия Абонемент ($m)

Расширение для программ 1С:Управление торговлей, 1С:Комплексная автоматизация, 1С:ERP, которое позволяет распечатывать печатные формы для непроведенных документов. Можно настроить, каким пользователям, какие конкретные формы документов разрешено печатать без проведения документа.

2 стартмани

22.08.2023    5060    81    progmaster    11    

4

Инструментарий разработчика Универсальные функции Платформа 1С v8.3 1C:Бухгалтерия 1С:Розница 2 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Зарплата и Управление Персоналом 3.x Абонемент ($m)

Копирует в буфер значения из списков, из ячеек отчетов, таблиц, настроек списков, других отборов и вставляет в выбранную настройку отбора. Работает с Объект не найден. Работает как в одной так и между разными базами 1С. Использует комбинации [Alt+C] Копировать список, [Alt+V] Вставить список. Также для копирования данных используется стандартная [Ctrl+C] (например из открытого xls, mxl, doc и т.п. файла скопировать список наименований)

1 стартмани

13.10.2022    20266    195    sapervodichka    113    

137
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. user-z99999 74 20.05.25 13:08 Сейчас в теме
Можно таблицу значений закинуть в запрос.
И там искать.
2. chekonst 76 20.05.25 14:04 Сейчас в теме
(1) Я думал над этим. А как быть с регулярными выражениями?
3. Spurk 42 20.05.25 17:00 Сейчас в теме
(2) Одной рукой вы даёте работу с регулярными выражениями, а другой рукой даёте штуки по видов запросов в цикле.
Если я правильно понял, ваш механизм работает перебором строк. Там для каждой строки вы используете отбор и складываете результат в массив, который возвращаете. Исходя из примера, у меня есть таблица значений на 1000 строк, и в отборе мы прописываем:
Отбор.Вставить("Строка({Номенклатура.тип}) Равно",мсвСписок);
Представление не получается просто так, если вы указали например Строка(Номенклатура.Родитель), точнее оно получается после запроса в базу.В данном примере каждый раз при новой строке вы будете гонять в базу данных, получится 1000 запросов - что не хорошо. И это если такой отбор один. В этом случае нужно сразу выгрузить все типы и колонки которые будут участвовать в отборе. Но тогда лучше отобрать сразу запросом.
Созинов; BigB; +2 Ответить
4. chekonst 76 20.05.25 17:19 Сейчас в теме
(3) Ну вообще, как известно, нет ничего универсального. Все надо использовать в меру. Может именно для вас этот метод и слишком долгий, а для кого то нет. Интересно сколько времени у вас занял перебор 1000 строк? Час? Пол часа? Минута? Несколько секунд? Если последний ответ Да. Тогда чем же этот метод плох?
7. Spurk 42 21.05.25 03:04 Сейчас в теме
(4) При чём тут долго/плохо? Пользуйтесь на здоровье.
Я сделал замечание про то, что механизм можно использовать, например с работой с строками. Для чего регулярки и есть.
Использовать с ссылочными данными не нужно. Сам подход многократного обращения в базу порицается как самим вендором, так и остальным миром "правильного" it.
Так же, например, при отборе по документСсылка.Контрагент для каждой строки, можно налететь на такую ситуацию, когда вы заблочите документ для других. Про это можно прочитать в книге "Настольная книга 1С:Эксперта по технологическим вопросам".
5. user-z99999 74 20.05.25 17:54 Сейчас в теме
(2) Запрос может только ПОДОБНО (like).
Насколько полно 1с поддерживает like в запросах, не проверял.
6. TMV 11 20.05.25 22:09 Сейчас в теме
выглядит как костыль.
а за имена типа "___ТекстМодуля " надо бить по рукам
8. chekonst 76 21.05.25 09:35 Сейчас в теме
(6) Да,именно костыль, т.к. 1С такое не встроило.
И как вы думаете, почему именно в этом месте вставлено "___", а в других нет? По приколу? Почему это вместо "Выполнить" вставлена отдельная функция? Тоже по приколу?
9. TMV 11 21.05.25 11:00 Сейчас в теме
(8) ничем иным это не объяснить, но можете попробовать
10. chekonst 76 21.05.25 11:14 Сейчас в теме
(9) УсловиеВыполнено() написана отдельной функцией, чтобы "экранировать" текст модуля выполнения от переменных основной, вызывающей функции. Иначе может произойти затирание значений основной функции.
"____" служат для этих же целей. Вы же, как я понял, не любите их применять и даже пытаетесь оторвать мне руки. Вот, надеясь, на эту нелюбовь их и ставят, что другие программисты не затирали такими же именами, но без "___" переменные. Вы на С++ писали? Там такого полно и никто не возмущается и не предлагает оторвать руки.
Оставьте свое сообщение