Сервис доступа к данным 1С для внешних систем
Жёлтый мост
Код · Программисту 1С

Разбор строки с разделителями в запросе: номенклатура по списку артикулов в УТ 11.5.27.70, КА 2.5.27.93 и БП 3.0.203.18

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

Управление торговлей 11.5.27.70Комплексная автоматизация 2.5.27.93Бухгалтерия предприятия 3.0.203.18

Задача

Менеджер присылает строку "А-100, А-101, Б-7" и спрашивает, что это за позиции. Обычно строку разбирают в коде функцией СтрРазделить, заполняют таблицу значений и передают ее в запрос параметром. Это работает, но в консоли запросов, в отчете на СКД или в обработке без кода так не сделать. Нужен разбор средствами самого запроса.

Решение

Строка дополняется разделителем в начале и в конце, чтобы каждый элемент стоял между двумя разделителями. Таблица цифр дает номера позиций символов, по функции ПОДСТРОКА отбираются позиции, где стоит разделитель. Для каждого разделителя соединением с той же таблицей находится ближайший следующий, между ними лежит один элемент. Элемент вырезается функцией ПОДСТРОКА, пробелы по краям убираются, пустые элементы и повторы отбрасываются.

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

Проверено на трех базах строкой из реальных артикулов с ловушками: лишние пробелы, повтор, пустой элемент, несуществующий артикул. Разбор совпал со встроенной функцией, найденные позиции совпали с независимым поиском, пропусков нет.

// Номенклатура по списку артикулов, вставленному одной строкой через разделитель,
// например из Excel: "А-100, А-101, Б-7". Строка разбирается прямо в запросе:
// без цикла в коде и без временной таблицы, заполняемой из встроенного языка.

// 1. Цифры от 0 до 9: из них собираются номера дней без таблиц календаря.
ВЫБРАТЬ
	0 КАК Цифра
ПОМЕСТИТЬ втЦифры

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	1

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	2

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	3

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	4

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	5

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	6

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	7

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	8

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	9
;

// 2. Номера позиций символов строки. Строка дополняется разделителем в начале и в конце,
//    чтобы каждый элемент стоял между двумя разделителями.
ВЫБРАТЬ
	1 + Единицы.Цифра + 10 * Десятки.Цифра + 100 * Сотни.Цифра + 1000 * Тысячи.Цифра КАК Позиция
ПОМЕСТИТЬ втПозиции
ИЗ
	втЦифры КАК Единицы,
	втЦифры КАК Десятки,
	втЦифры КАК Сотни,
	втЦифры КАК Тысячи
ГДЕ
	1 + Единицы.Цифра + 10 * Десятки.Цифра + 100 * Сотни.Цифра + 1000 * Тысячи.Цифра <= ДЛИНАСТРОКИ(&Разделитель + &Список + &Разделитель)
;

// 3. Позиции, на которых стоит разделитель.
ВЫБРАТЬ
	Позиции.Позиция КАК Позиция
ПОМЕСТИТЬ втРазделители
ИЗ
	втПозиции КАК Позиции
ГДЕ
	ПОДСТРОКА(&Разделитель + &Список + &Разделитель, Позиции.Позиция, 1) = &Разделитель
;

// 4. Для каждого разделителя ближайший следующий: между ними лежит один элемент.
ВЫБРАТЬ
	Левый.Позиция КАК Начало,
	МИНИМУМ(Правый.Позиция) КАК Конец
ПОМЕСТИТЬ втОтрезки
ИЗ
	втРазделители КАК Левый
		ВНУТРЕННЕЕ СОЕДИНЕНИЕ втРазделители КАК Правый
		ПО (Правый.Позиция > Левый.Позиция)
СГРУППИРОВАТЬ ПО
	Левый.Позиция
;

// 5. Элементы списка без пробелов по краям, пустые отбрасываются. Результат приводится
//    к строке ограниченной длины: строки неограниченной длины в запросе сравнивать нельзя,
//    поэтому пустые элементы отсекаются по длине, а не сравнением с пустой строкой.
ВЫБРАТЬ
	ВЫРАЗИТЬ(СОКРЛП(ПОДСТРОКА(&Разделитель + &Список + &Разделитель, Отрезки.Начало + 1, Отрезки.Конец - Отрезки.Начало - 1)) КАК СТРОКА(50)) КАК Артикул,
	МИНИМУМ(Отрезки.Начало) КАК Порядок
ПОМЕСТИТЬ втАртикулы
ИЗ
	втОтрезки КАК Отрезки
ГДЕ
	ДЛИНАСТРОКИ(СОКРЛП(ПОДСТРОКА(&Разделитель + &Список + &Разделитель, Отрезки.Начало + 1, Отрезки.Конец - Отрезки.Начало - 1))) > 0
СГРУППИРОВАТЬ ПО
	ВЫРАЗИТЬ(СОКРЛП(ПОДСТРОКА(&Разделитель + &Список + &Разделитель, Отрезки.Начало + 1, Отрезки.Конец - Отрезки.Начало - 1)) КАК СТРОКА(50))
ИНДЕКСИРОВАТЬ ПО
	Артикул
;

// 6. Каждый артикул из списка и найденная по нему номенклатура. Не найденные
//    артикулы остаются в результате с пустой номенклатурой. Артикул справочника
//    сравнивается без пробелов по краям: пробел в начале артикула встречается часто,
//    и простое равенство такую позицию не находит.
ВЫБРАТЬ
	Артикулы.Порядок КАК Порядок,
	Артикулы.Артикул КАК Артикул,
	Номенклатура.Ссылка КАК Номенклатура,
	ВЫБОР
		КОГДА Номенклатура.Ссылка ЕСТЬ NULL
			ТОГДА "не найден"
		ИНАЧЕ &ПустаяСтрока
	КОНЕЦ КАК Примечание
ИЗ
	втАртикулы КАК Артикулы
		ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура
		ПО (СОКРЛП(Номенклатура.Артикул) = Артикулы.Артикул)
			И (НЕ Номенклатура.ПометкаУдаления)

УПОРЯДОЧИТЬ ПО
	Порядок
// Номенклатура по списку артикулов, вставленному одной строкой через разделитель,
// например из Excel: "А-100, А-101, Б-7". Строка разбирается прямо в запросе:
// без цикла в коде и без временной таблицы, заполняемой из встроенного языка.

// 1. Цифры от 0 до 9: из них собираются номера дней без таблиц календаря.
ВЫБРАТЬ
	0 КАК Цифра
ПОМЕСТИТЬ втЦифры

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	1

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	2

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	3

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	4

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	5

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	6

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	7

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	8

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	9
;

// 2. Номера позиций символов строки. Строка дополняется разделителем в начале и в конце,
//    чтобы каждый элемент стоял между двумя разделителями.
ВЫБРАТЬ
	1 + Единицы.Цифра + 10 * Десятки.Цифра + 100 * Сотни.Цифра + 1000 * Тысячи.Цифра КАК Позиция
ПОМЕСТИТЬ втПозиции
ИЗ
	втЦифры КАК Единицы,
	втЦифры КАК Десятки,
	втЦифры КАК Сотни,
	втЦифры КАК Тысячи
ГДЕ
	1 + Единицы.Цифра + 10 * Десятки.Цифра + 100 * Сотни.Цифра + 1000 * Тысячи.Цифра <= ДЛИНАСТРОКИ(&Разделитель + &Список + &Разделитель)
;

// 3. Позиции, на которых стоит разделитель.
ВЫБРАТЬ
	Позиции.Позиция КАК Позиция
ПОМЕСТИТЬ втРазделители
ИЗ
	втПозиции КАК Позиции
ГДЕ
	ПОДСТРОКА(&Разделитель + &Список + &Разделитель, Позиции.Позиция, 1) = &Разделитель
;

// 4. Для каждого разделителя ближайший следующий: между ними лежит один элемент.
ВЫБРАТЬ
	Левый.Позиция КАК Начало,
	МИНИМУМ(Правый.Позиция) КАК Конец
ПОМЕСТИТЬ втОтрезки
ИЗ
	втРазделители КАК Левый
		ВНУТРЕННЕЕ СОЕДИНЕНИЕ втРазделители КАК Правый
		ПО (Правый.Позиция > Левый.Позиция)
СГРУППИРОВАТЬ ПО
	Левый.Позиция
;

// 5. Элементы списка без пробелов по краям, пустые отбрасываются. Результат приводится
//    к строке ограниченной длины: строки неограниченной длины в запросе сравнивать нельзя,
//    поэтому пустые элементы отсекаются по длине, а не сравнением с пустой строкой.
ВЫБРАТЬ
	ВЫРАЗИТЬ(СОКРЛП(ПОДСТРОКА(&Разделитель + &Список + &Разделитель, Отрезки.Начало + 1, Отрезки.Конец - Отрезки.Начало - 1)) КАК СТРОКА(50)) КАК Артикул,
	МИНИМУМ(Отрезки.Начало) КАК Порядок
ПОМЕСТИТЬ втАртикулы
ИЗ
	втОтрезки КАК Отрезки
ГДЕ
	ДЛИНАСТРОКИ(СОКРЛП(ПОДСТРОКА(&Разделитель + &Список + &Разделитель, Отрезки.Начало + 1, Отрезки.Конец - Отрезки.Начало - 1))) > 0
СГРУППИРОВАТЬ ПО
	ВЫРАЗИТЬ(СОКРЛП(ПОДСТРОКА(&Разделитель + &Список + &Разделитель, Отрезки.Начало + 1, Отрезки.Конец - Отрезки.Начало - 1)) КАК СТРОКА(50))
ИНДЕКСИРОВАТЬ ПО
	Артикул
;

// 6. Каждый артикул из списка и найденная по нему номенклатура. Не найденные
//    артикулы остаются в результате с пустой номенклатурой. Артикул справочника
//    сравнивается без пробелов по краям: пробел в начале артикула встречается часто,
//    и простое равенство такую позицию не находит.
ВЫБРАТЬ
	Артикулы.Порядок КАК Порядок,
	Артикулы.Артикул КАК Артикул,
	Номенклатура.Ссылка КАК Номенклатура,
	ВЫБОР
		КОГДА Номенклатура.Ссылка ЕСТЬ NULL
			ТОГДА "не найден"
		ИНАЧЕ &ПустаяСтрока
	КОНЕЦ КАК Примечание
ИЗ
	втАртикулы КАК Артикулы
		ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура
		ПО (СОКРЛП(Номенклатура.Артикул) = Артикулы.Артикул)
			И (НЕ Номенклатура.ПометкаУдаления)

УПОРЯДОЧИТЬ ПО
	Порядок
// Номенклатура по списку артикулов, вставленному одной строкой через разделитель,
// например из Excel: "А-100, А-101, Б-7". Строка разбирается прямо в запросе:
// без цикла в коде и без временной таблицы, заполняемой из встроенного языка.

// 1. Цифры от 0 до 9: из них собираются номера дней без таблиц календаря.
ВЫБРАТЬ
	0 КАК Цифра
ПОМЕСТИТЬ втЦифры

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	1

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	2

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	3

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	4

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	5

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	6

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	7

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	8

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
	9
;

// 2. Номера позиций символов строки. Строка дополняется разделителем в начале и в конце,
//    чтобы каждый элемент стоял между двумя разделителями.
ВЫБРАТЬ
	1 + Единицы.Цифра + 10 * Десятки.Цифра + 100 * Сотни.Цифра + 1000 * Тысячи.Цифра КАК Позиция
ПОМЕСТИТЬ втПозиции
ИЗ
	втЦифры КАК Единицы,
	втЦифры КАК Десятки,
	втЦифры КАК Сотни,
	втЦифры КАК Тысячи
ГДЕ
	1 + Единицы.Цифра + 10 * Десятки.Цифра + 100 * Сотни.Цифра + 1000 * Тысячи.Цифра <= ДЛИНАСТРОКИ(&Разделитель + &Список + &Разделитель)
;

// 3. Позиции, на которых стоит разделитель.
ВЫБРАТЬ
	Позиции.Позиция КАК Позиция
ПОМЕСТИТЬ втРазделители
ИЗ
	втПозиции КАК Позиции
ГДЕ
	ПОДСТРОКА(&Разделитель + &Список + &Разделитель, Позиции.Позиция, 1) = &Разделитель
;

// 4. Для каждого разделителя ближайший следующий: между ними лежит один элемент.
ВЫБРАТЬ
	Левый.Позиция КАК Начало,
	МИНИМУМ(Правый.Позиция) КАК Конец
ПОМЕСТИТЬ втОтрезки
ИЗ
	втРазделители КАК Левый
		ВНУТРЕННЕЕ СОЕДИНЕНИЕ втРазделители КАК Правый
		ПО (Правый.Позиция > Левый.Позиция)
СГРУППИРОВАТЬ ПО
	Левый.Позиция
;

// 5. Элементы списка без пробелов по краям, пустые отбрасываются. Результат приводится
//    к строке ограниченной длины: строки неограниченной длины в запросе сравнивать нельзя,
//    поэтому пустые элементы отсекаются по длине, а не сравнением с пустой строкой.
ВЫБРАТЬ
	ВЫРАЗИТЬ(СОКРЛП(ПОДСТРОКА(&Разделитель + &Список + &Разделитель, Отрезки.Начало + 1, Отрезки.Конец - Отрезки.Начало - 1)) КАК СТРОКА(50)) КАК Артикул,
	МИНИМУМ(Отрезки.Начало) КАК Порядок
ПОМЕСТИТЬ втАртикулы
ИЗ
	втОтрезки КАК Отрезки
ГДЕ
	ДЛИНАСТРОКИ(СОКРЛП(ПОДСТРОКА(&Разделитель + &Список + &Разделитель, Отрезки.Начало + 1, Отрезки.Конец - Отрезки.Начало - 1))) > 0
СГРУППИРОВАТЬ ПО
	ВЫРАЗИТЬ(СОКРЛП(ПОДСТРОКА(&Разделитель + &Список + &Разделитель, Отрезки.Начало + 1, Отрезки.Конец - Отрезки.Начало - 1)) КАК СТРОКА(50))
ИНДЕКСИРОВАТЬ ПО
	Артикул
;

// 6. Каждый артикул из списка и найденная по нему номенклатура. Не найденные
//    артикулы остаются в результате с пустой номенклатурой. Артикул справочника
//    сравнивается без пробелов по краям: пробел в начале артикула встречается часто,
//    и простое равенство такую позицию не находит.
ВЫБРАТЬ
	Артикулы.Порядок КАК Порядок,
	Артикулы.Артикул КАК Артикул,
	Номенклатура.Ссылка КАК Номенклатура,
	ВЫБОР
		КОГДА Номенклатура.Ссылка ЕСТЬ NULL
			ТОГДА "не найден"
		ИНАЧЕ &ПустаяСтрока
	КОНЕЦ КАК Примечание
ИЗ
	втАртикулы КАК Артикулы
		ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура
		ПО (СОКРЛП(Номенклатура.Артикул) = Артикулы.Артикул)
			И (НЕ Номенклатура.ПометкаУдаления)

УПОРЯДОЧИТЬ ПО
	Порядок
Обработка для Управление торговлей 11.5.27.70Открыть через "Файл, Открыть", выбрать даты, нажать "Сформировать результат". Ничего не пишет в базу, работает от прав пользователя.
Скачать .epf
Обработка для Комплексная автоматизация 2.5.27.93Открыть через "Файл, Открыть", выбрать даты, нажать "Сформировать результат". Ничего не пишет в базу, работает от прав пользователя.
Скачать .epf
Обработка для Бухгалтерия предприятия 3.0.203.18Открыть через "Файл, Открыть", выбрать даты, нажать "Сформировать результат". Ничего не пишет в базу, работает от прав пользователя.
Скачать .epf

Что учесть

Как воспользоваться

  1. Выберите вкладку своей конфигурации над кодом: под каждой лежит запрос, выполненный именно в этой конфигурации.
  2. Скачайте обработку под ней и откройте в 1С через "Файл, Открыть". Форма покажет поля отбора, результат появится в той же форме таблицей.
  3. Нужно иначе: скопируйте запрос кнопкой над кодом и подставьте в консоль запросов или в свою обработку. Все параметры перечислены в тексте, значения по умолчанию видны в обработке.
  4. Хотите то же самое, но под свою базу и свои поля: подключите базу к мосту и попросите ИИ доработать этот запрос. Он увидит структуру вашей конфигурации и проверит результат на ваших данных.
Свои задачи таким же способом. Подключение занимает около пятнадцати минут: обработка из кабинета, ключ, готовый текст для ИИ. При регистрации даются три дня работы одной базы, карта не нужна.
Подключить свою базу Другие решения

Комментарии

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