Строка не закрывающаяся кавычкой запрос 1с
Необходимость задавать исполняемый код в пользовательском режиме появляется не так уж и редко. Для этого создано множество инструментов - универсальные регламентные задания, консоли кода, динамические подписки на события и т.д. С помощью этих инструментов можно создавать код, содержащий запросы, и хорошо бы иметь возможность вызывать для этих запросов конструктор. Более того, во всем известных "Инструментах разработчика" уже есть решение этой задачи для обычных форм с применением библиотеки регулярных выражений (внешней библиотеки, подключаемой как COM-объект).
Мы же рассмотрим решение исключительно средствами 1С, которое вы сможете легко встраивать в свои формы, и которое будет подходить как для обычной, так и для управляемой формы (в толстом клиенте). Следующая иллюстрация показывает, чего мы хотим добиться от нашего алгоритма:
То есть нам необходимо получить возможность работать с запросами в коде аналогичную той, что дает Конфигуратор - открывать существующий запрос, изменять его, и затем возвращать измененный запрос в код на языке 1С с форматированием и сохранением позиции курсора. Эта задача сложна лишь потому, что у поля тестового документа 1С мало методов для работы с текстом и их придется "изобретать" самостоятельно.
Сначала опишем алгоритм на человеческом языке, а затем перейдем к реализации алгоритма на языке платформы.
Нам нужно:
1) Определить позицию курсора в поле текстового документа на форме.
2) Извлечь текст до курсора и после курсора.
3) В тексте, расположенном до курсора, найти открывающую запрос кавычку. В тексте расположенном после курсора найти первую несдвоенную кавычку от начала строки, это будет закрывающая кавычка.
4) Отделить текст запроса, расположенный между открывающей и закрывающей кавычками. А также выделить код, расположенный до начала запроса и после него.
5) Преобразовать код запроса таким образом, чтобы он нормально воспринимался конструктором запроса. Вместо двойных кавычек подставить одинарные, убрать символы вертикальной черты. После чего передать полученный текст в конструктор.
6) После закрытия конструктора сделать обратное преобразование полученного из него кода запроса. Добавить отступы и привести его к виду, который будет нормально воспринят интерпретатором языка 1С.
7) Соединить новый код запроса с текстом, который раньше располагался до и после текста запроса. Загрузить полученный код в поле формы и восстановить позицию курсора.
Теперь перейдем к поэтапной реализации этого алгоритма на языке 1С. Для демонстрации выберем обычную форму. Для управляемой формы код будет отличаться всего несколькими строками, и он также есть в прикрепленном к этой публикации файле. Пусть поле текстового документа на нашей форме имеет имя "Поле".
1) Упростим процесс кодирования введением дополнительных переменных и определим текущую позицию курсора. Позицию курсора запишем в переменные НачалоСтроки и НачалоКолонки. Значение переменной НачалоСтроки в ходе алгорима менять не будем. Оно понадобится в конце для восстановления позиции курсора:
//БЛОК №1 - ИНИЦИАЛИЗАЦИЯ ПЕРЕМЕННЫХ
ЭлементПоля = ЭлементыФормы . Поле ;
Кавычка = """" ;
ДвойнаяКавычка = """""" ;
ЗаменаДляДвойнойКавычки = Строка (Новый УникальныйИдентификатор );
КоличествоСтрок = ЭлементПоля . КоличествоСтрок ();
НачалоСтроки = 0 ;
НачалоКолонки = 0 ;
КонецСтроки = 0 ;
КонецКолонки = 0 ;
ЭлементПоля . ПолучитьГраницыВыделения ( НачалоСтроки , НачалоКолонки , КонецСтроки , КонецКолонки );
ЭлементПоля . УстановитьГраницыВыделения ( НачалоСтроки , НачалоКолонки , Началостроки , НачалоКолонки );
2) Определим текст, расположенный до курсора и после него. Для этого поле текстового документа дает нам только одну возможность - устанавливать границы выделения и получать выделенный текст. Далее нам придется искать открывающую и закрывающую запрос кавычку. Сильной помехой в этом могут оказаться двойные кавычки. Чтобы избежать лишнего кода по обработке двойных кавычек используем следующий прием. Временно заменим все двойные кавычки на уникальную строку. Обратную замену будем проводить в конце алгоритма, при получении нового кода:
//БЛОК №2 - ОПРЕДЕЛЕНИЕ ТЕКСТА ДО КУРСОРА И ПОСЛЕ КУРСОРА
ЭлементПоля . УстановитьГраницыВыделения ( 1 , 1 , Началостроки , НачалоКолонки );
ТекстДоКурсора = ЭлементПоля . ВыделенныйТекст ;
ЭлементПоля . УстановитьГраницыВыделения ( НачалоСтроки , НачалоКолонки , КоличествоСтрок + 1 , 1 );
ТекстПослеКурсора = ЭлементПоля . ВыделенныйТекст ;
ЭлементПоля . УстановитьГраницыВыделения ( НачалоСтроки , НачалоКолонки , Началостроки , НачалоКолонки );
//гарантируем отсутствие в тексте двойных кавычек
ТекстДоКурсора = СтрЗаменить ( ТекстДоКурсора , ДвойнаяКавычка , ЗаменаДляДвойнойКавычки );
//в тексте после курсора необходимо оставить первую кавычку, если сразу после нее идет двойная
//случай подряд идущих кавычек в количестве более 5-ти штук обрабатывать не будем
ТекстПослеКурсора = СтрЗаменить ( Лев ( ТекстПослеКурсора , 1 ) +
СтрЗаменить ( Сред ( ТекстПослеКурсора , 2 ), ДвойнаяКавычка , ЗаменаДляДвойнойКавычки ), ДвойнаяКавычка , ЗаменаДляДвойнойКавычки ) ;
3) Двигаясь по строке кода, расположенного до курсора, находим открывающую запрос кавычку. Поскольку мы избавились от двойных кавычек, то найти ее несложно. Нужно просто найти кавычку, которая не была закрыта следующей за ней. Правда, нужно учитывать, что кавычки в комментариях надо пропустить, перемещаясь сразу к концу строки, а также то, что курсор сам мог находиться внутри двойной кавычки в строке запроса:
//БЛОК №3 - ИЩЕМ ПОЗИЦИЮ ОТКРВАЮЩЕЙ И ЗАКРЫВАЮЩЕЙ КАВЫЧКИ ДЛЯ СТРОКИ ЗАПРОСА
ПозицияОткрывающейКавычки = 0 ;
ПозицияЗакрывающейКавычки = 0 ;
ВСтроке = Ложь;
КавычкиЕсть = Ложь;
ПозицияПредыдущейКавычки = 0 ;
ПоизцияПоследнейКавычки = 0 ;
Позиция = 1 ;
ДлинаТекстаДоКурсора = СтрДлина ( ТекстДоКурсора );
//ИЩЕМ ОТКРЫВАЮЩУЮ КАВЫЧКУ
Пока Позиция < = ДлинаТекстаДоКурсора Цикл
ТекущийСимвол = Сред ( ТекстДоКурсора , Позиция , 1 );
ПредыдущийСимвол = " " ;
Если Позиция > 1 Тогда
ПредыдущийСимвол = Сред ( ТекстДоКурсора , Позиция - 1 , 1 );
КонецЕсли;
Если ТекущийСимвол = Кавычка Тогда
ВСтроке = НЕ ВСтроке ;
ПозицияПредыдущейКавычки = ПоизцияПоследнейКавычки ;
ПоизцияПоследнейКавычки = Позиция ;
КавычкиЕсть = Истина;
КонецЕсли;
//Обработка комментария - начало
Если НЕ ВСтроке И ПредыдущийСимвол = "/" И ТекущийСимвол = "/" Тогда
//это комментарий, пропускаем символы до конца строки
Пока ТекущийСимвол <> Символы . LF И ТекущийСимвол <> Символы . CR Цикл
Позиция = Позиция + 1 ;
Если Позиция > ДлинаТекстаДоКурсора Тогда
Прервать;
КонецЕсли;
ТекущийСимвол = Сред ( ТекстДоКурсора , Позиция , 1 );
КонецЦикла;
Продолжить;
КонецЕсли;
//Обработка комментария - конец
Позиция = Позиция + 1 ;
КонецЦикла;
//ОСОБЫМ ОБРАЗОМ ОБРАБОТАЕМ СЛУЧАЙ НАХОЖДЕНИЯ КУРСОРА В
//ДВОЙНОЙ КАВЫЧКЕ ВНУТРИ СТРОКИ ЗАПРОСА
Если НЕ ВСтроке И КавычкиЕсть И СтрДлина ( ТекстПослеКурсора ) > 0 Тогда
Если Сред ( ТекстДоКурсора , ДлинаТекстаДоКурсора , 1 ) = Кавычка И Лев ( ТекстПослеКурсора , 1 ) = Кавычка Тогда
ВСтроке = Истина;
ПоизцияПоследнейКавычки = ПозицияПредыдущейКавычки ;
ТекстДоКурсора = Лев ( ТекстДоКурсора , ДлинаТекстаДоКурсора - 1 );
ТекстПослеКурсора = ЗаменаДляДвойнойКавычки + Сред ( ТекстПослеКурсора , 2 );
КонецЕсли;
КонецЕсли;
//ЕСЛИ НАШИЛИ ОТКРЫВАЮЩУЮ КАВЫЧКУ, ТО ИЩЕМ ЗАКРЫВАЮЩУЮ
Если ВСтроке Тогда
ПозицияОткрывающейКавычки = ПоизцияПоследнейКавычки ;
ПозицияЗакрывающейКавычки = Найти ( ТекстПослеКурсора , Кавычка );
КонецЕсли;
4) Теперь можно выделить код между кавычками (запрос) и код расположенный до и после запроса. Чтобы текст запроса был воспринят конструктором его необходимо преобразовать, убрав из начала каждой его строки вертикальную черту:
//БЛОК №4 - ОПРЕДЕЛЯЕМ ТЕКСТ ДО ЗАПРОСА, ТЕКСТ ЗАПРОСА И ТЕКСТ ПОСЛЕ ЗАПРОСА
//ПОСЛЕ ЧЕГО ВОЗРАЩАЕМ ДВОЙНЫЕ КАВЫЧКИ В КОД, НЕ ЯВЛЯЮЩИЙСЯ ЧАСТЬЮ ЗАПРОСА
Конструктор = Новый( "КонструкторЗапроса" );
ГраницыЗапросаНайдены = ПозицияОткрывающейКавычки <> 0 И ПозицияЗакрывающейКавычки <> 0 ;
ТекстДоНачалаЗапроса = Лев ( ТекстДоКурсора , ПозицияОткрывающейКавычки );
ТекстПослеКонцаЗапроса = Сред ( ТекстПослеКурсора , ПозицияЗакрывающейКавычки );
ТекстЗапросаССимвовамиВертикальнойЧерты = Сред ( ТекстДоКурсора , ПозицияОткрывающейКавычки + 1 )
+ Лев ( ТекстПослеКурсора , ПозицияЗакрывающейКавычки - 1 );
//для конструктора запроса вместо двойной кавычки будем подставлять одинарную
ТекстЗапросаССимвовамиВертикальнойЧерты =
СтрЗаменить ( ТекстЗапросаССимвовамиВертикальнойЧерты , ЗаменаДляДвойнойКавычки , Кавычка );
КоличествоСтрокВТексте = СтрЧислоСтрок ( ТекстЗапросаССимвовамиВертикальнойЧерты );
ТекстЗапроса = "" ;
Для К = 1 To КоличествоСтрокВТексте Цикл
СтрокаИзТекстаЗапроса = СокрЛП ( СтрПолучитьСтроку ( ТекстЗапросаССимвовамиВертикальнойЧерты , К ));
Если Лев ( СтрокаИзТекстаЗапроса , 1 ) = "|" Тогда
//для конструктора запроса убираем вертикальную черту в начале строки
СтрокаИзТекстаЗапроса = Сред ( СтрокаИзТекстаЗапроса , 2 );
КонецЕсли;
ТекстЗапроса = ТекстЗапроса + СтрокаИзТекстаЗапроса + Символы . LF ;
КонецЦикла;
Конструктор . Текст = ТекстЗапроса ;
КонецЕсли;
//возвращаем двойные кавычки
ТекстДоНачалаЗапроса = СтрЗаменить ( ТекстДоНачалаЗапроса , ЗаменаДляДвойнойКавычки , ДвойнаяКавычка );
ТекстПослеКонцаЗапроса = СтрЗаменить ( ТекстПослеКонцаЗапроса , ЗаменаДляДвойнойКавычки , ДвойнаяКавычка );
5) Передаем текст запроса в конструктор и, если конструктор отработал успешно, вычисляем отступ, который будем добавлять к строкам запроса. Отступ необходимо добавлять, чтобы код запроса вставился на форму красиво, а не безусловно лепился к левому краю текстового поля:
//БЛОК №5 - ОТКРЫВАЕМ КОНСТРУКТОР ЗАПРОСА С ПОЛУЧЕННОЙ СТРОКОЙ ЗАПРОСА И В СЛУЧАЕ УСПЕШНОГО
//РЕЗУЛЬТАТА ВЫЧИСЛЯЕМ ОТСТУП, КОТОРЫЙ БУДЕМ ДОБАВЛЯТЬ К КАЖДОЙ СТРОКЕ ЗАПРОСА
Если НЕ Конструктор . ОткрытьМодально () Тогда
Возврат;
КонецЕсли;
ТекстЗапроса = Конструктор . Текст ;
Если ПустаяСтрока ( ТекстЗапроса ) Тогда
Возврат;
КонецЕсли;
ДлинаТекстаДоНачалаЗапроса = СтрДлина ( ТекстДоНачалаЗапроса );
Позиция = ДлинаТекстаДоНачалаЗапроса - 1 ;
Пока Позиция >= 1 Цикл
Если Сред ( ТекстДоНачалаЗапроса , Позиция , 1 ) = Символы . LF Тогда
Прервать;
КонецЕсли;
Позиция = Позиция - 1 ;
КонецЦикла;
СтрокаОтступа = Сред ( ТекстДоНачалаЗапроса , Позиция + 1 , ДлинаТекстаДоНачалаЗапроса - Позиция - 1 );
ДлинаСтрокиОтступа = СтрДлина ( СтрокаОтступа );
СтрокаОтступаИзПробеловИТабуляций = "" ;
Для К = 1 To ДлинаСтрокиОтступа Цикл
Если Сред ( СтрокаОтступа , К , 1 ) = Символы . Tab Тогда
СтрокаОтступаИзПробеловИТабуляций = СтрокаОтступаИзПробеловИТабуляций + Символы . Tab ;
Иначе
СтрокаОтступаИзПробеловИТабуляций = СтрокаОтступаИзПробеловИТабуляций + " " ;
КонецЕсли;
КонецЦикла;
6) Теперь у нас есть текст запроса на языке запросов. Нужно преобразовать его в строку на встроенном языке 1С. Добавляем символы вертикальной черты и отступы, преобразуем одинарные кавычки в двойные:
//БЛОК №6 - ОБРАБАТЫВАЕМ РЕЗУЛЬТАТ, ЗАМЕНЯЕМ ОДИНАРНЫЕ КАВЫЧКИ НА ДВОЙНЫЕ,
//ДОБАВЛЯЕМ ОТСТУП И ВЕРТИКАЛЬНУЮ ЧЕРТУ СТРОКАМ ЗАПРОСА НАЧИНАЯ СО ВТОРОЙ
ТекстЗапроса = СтрЗаменить ( ТекстЗапроса , Кавычка , ДвойнаяКавычка );
КоличествоСтрокВТексте = СтрЧислоСтрок ( ТекстЗапроса );
ТекстЗапросаССимвовамиВертикальнойЧерты = СтрПолучитьСтроку ( ТекстЗапроса , 1 );
Для К = 2 To КоличествоСтрокВТексте Цикл
ТекстЗапросаССимвовамиВертикальнойЧерты = ТекстЗапросаССимвовамиВертикальнойЧерты +
Символы . LF + СтрокаОтступаИзПробеловИТабуляций + "|" + СтрПолучитьСтроку ( ТекстЗапроса , К );
КонецЦикла;
7) Задача фактически решена. Склеиваем код, располагавшийся до запроса, новую строку запроса и код, располагавшийся после запроса. Загружаем получившуюся строку в поле формы и восстанавливаем позицию курсора:
//ЗАГРУЖАЕМ НОВЫЙ КОД В ТЕКСТОВОЕ ПОЛЕ И УСТАНАВЛИВАЕМ КУРСОР НА ПРЕЖНЮЮ ПОЗИЦИЮ
ИтоговыйКод = ТекстДоНачалаЗапроса + ТекстЗапросаССимвовамиВертикальнойЧерты + ТекстПослеКонцаЗапроса ;
ЭлементПоля . УстановитьТекст ( ИтоговыйКод );
НоваяКолонка = СтрДлина ( СтрокаОтступаИзПробеловИТабуляций )+ 2 ;
ЭлементПоля . УстановитьГраницыВыделения ( НачалоСтроки , НоваяКолонка , НачалоСтроки , НоваяКолонка );
ЭтаФорма . ТекущийЭлемент = ЭлементПоля ;
Для применения этого метода в своих разработках вам достаточно заменить в коде имя одного элемента формы - поля текстового документа.
К публикации прилагается обработка с реализацией этого алгоритма, в которой есть обычная и управляемая форма. Обработка предназначена для работы в толстом клиенте управляемого или обычного приложения. При работе с управляемой формой есть незначительные отличия в коде. Например, восстанавливать положение курсора приходится через отложенный вызов процедуры, через обработчик ожидания.
Алгоритм был создан с целью применения в новой версии универсальной подсистемы Динамические подписки на события v.3 . Не проходите мимо этой разработки, она может облегчить поддержку ваших баз:
Только ленивый, по-моему, не писал еще о вариантах вырезания гланд через анус автогеном запросами. Ну и я поделюсь.
К сожалению, возможности запросов 1С в отношении строковых переменных крайне малы. Практически они исчерпываются одной функцией и одним оператором. Тем не менее, постоянно всплывают темы в духе «а как мне сделать это прямо в запросе?». Конечно, большинство задач решаются в СКД, оставшаяся часть решается пост-обработкой результата, но чисто в качестве разминки для ума, кое-что в запросе сделать можно.
Во всех примерах я буду использовать следующие временные таблицы:
ВЫБРАТЬ
"_" КАК Симв ,
1 КАК КолСимв
ПОМЕСТИТЬ тзКоличествоСимволов9
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
"__" ,
2
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
"___" ,
3
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
"____" ,
4
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
"_____" ,
5
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
"______" ,
6
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
"_______" ,
7
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
"________" ,
8
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
"_________" ,
9
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
"" ,
0
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
тзКоличествоСимволов9_Лев . Симв + тзКоличествоСимволов9_Лев . Симв + тзКоличествоСимволов9_Лев . Симв + тзКоличествоСимволов9_Лев . Симв + тзКоличествоСимволов9_Лев . Симв + тзКоличествоСимволов9_Лев . Симв + тзКоличествоСимволов9_Лев . Симв + тзКоличествоСимволов9_Лев . Симв + тзКоличествоСимволов9_Лев . Симв + тзКоличествоСимволов9_Лев . Симв + тзКоличествоСимволов9_Прав . Симв КАК Симв ,
тзКоличествоСимволов9_Лев . КолСимв * 10 + тзКоличествоСимволов9_Прав . КолСимв КАК КолСимв
ПОМЕСТИТЬ тзКоличествоСимволов100
ИЗ
тзКоличествоСимволов9 КАК тзКоличествоСимволов9_Лев ,
тзКоличествоСимволов9 КАК тзКоличествоСимволов9_Прав
;
////////////////////////////////////////////////////////////////////////////////
Для приведенных примеров их вполне хватит, смысл, думаю, понятен, так что не будем заострять внимание на оптимальности их построения.
Так же рекомендую экспериментировать с приведенными запросами в файловых базах – серверные более нежные и работать автогеном в таком грязном месте не любят. :)
Тут всё очень просто
ВЫБРАТЬ
Номенклатура . Наименование ,
КоличествоСимволов . КолСимв
ИЗ
Справочник . Номенклатура КАК Номенклатура
ЛЕВОЕ СОЕДИНЕНИЕ тзКоличествоСимволов100 КАК КоличествоСимволов
ПО ( Номенклатура . Наименование ПОДОБНО КоличествоСимволов . Симв )
Всё. Теперь можно отрезать последний пробел, например:
ВЫБРАТЬ
Номенклатура . Наименование ,
КоличествоСимволов . КолСимв ,
ВЫБОР
КОГДА Наименование подобно "% "
ТОГДА ПОДСТРОКА ( Номенклатура . Наименование , 1 , КоличествоСимволов . КолСимв - 1 )
ИНАЧЕ Номенклатура . Наименование
КОНЕЦ КАК НаименованиеБезПробела
ИЗ
Справочник . Номенклатура КАК Номенклатура
ЛЕВОЕ СОЕДИНЕНИЕ тзКоличествоСимволов100 КАК КоличествоСимволов
ПО ( Номенклатура . Наименование ПОДОБНО КоличествоСимволов . Симв )
2. Разбить строку
Здесь чуть сложнее. Но теми же граблями.
Задача: в некоторой номенклатуре в наименовании записан некоторый текст в скобках. Надо вытащить этот текст в отдельное поле.
Для простоты договоримся, что скобочки в наименовании у нас один раз открываются и один раз закрываются.
ВЫБРАТЬ Различные
Номенклатура . Ссылка ,
Выразить ( ПОДСТРОКА ( Номенклатура . Наименование , КоличествоСимволовДоОткрытия . КолСимв + 2 , КоличествоСимволовДоЗакрытия . КолСимв - КоличествоСимволовДоОткрытия . КолСимв - 1 ) как строка ( 100 )) КАК ТекстВСкобках
ИЗ
Справочник . Номенклатура КАК Номенклатура
ЛЕВОЕ СОЕДИНЕНИЕ тзКоличествоСимволов100 КАК КоличествоСимволовДоОткрытия
ПО ( Номенклатура . Наименование ПОДОБНО КоличествоСимволовДоОткрытия . Симв + &СимволОткрытия + "%" )
ЛЕВОЕ СОЕДИНЕНИЕ тзКоличествоСимволов100 КАК КоличествоСимволовДоЗакрытия
ПО ( Номенклатура . Наименование ПОДОБНО КоличествоСимволовДоЗакрытия . Симв + &СимволЗакрытия + "%" )
ГДЕ
Номенклатура . Наименование ПОДОБНО "%" + &СимволОткрытия + "%" + &СимволЗакрытия + "%"
Тут &СимволОткрытия, понятно «(»,&СимволЗакрытия соответственно «)». Находим позицию символов и вытаскиваем подстроку. Помним, что запросы тошнит от строк неограниченной длины, поэтому используем ВЫРАЗИТЬ.
3. Сложное соединение по строке.
Ну и совсем извращение, но пример взят из реальной темы.
Существуют две таблицы:
В одной номера договоров в формате: «Номер-постфикс»
В другой номера тех же договоров, но дополненные неким доп-индексом в формате: «Номер/Индекс-постфикс».
Необходимо связать. Номер, индекс и постфикс могут быть разной длины, ориентироваться можно только на «/» и «-».
И начнем выпендриваться.
//Выделим из номеров те части, по которым сможем связывать
Выбрать
тз1сРазбиением . ВнутреннийНомер ,
Подстрока ( тз1сРазбиением . ВнутреннийНомер , 1 , КоличествоСимволовДоТире . КолСимв ) как ДоСлэша ,
Подстрока ( тз1сРазбиением . ВнутреннийНомер , КоличествоСимволовДоТире . КолСимв + 2 , СтрДлина . КолСимв ) как ПослеТире
поместить тз1сРазбиением
из тз1 как тз1сРазбиением
ЛЕВОЕ СОЕДИНЕНИЕ тзКоличествоСимволов100 КАК КоличествоСимволовДоТире
ПО ( тз1сРазбиением . ВнутреннийНомер ПОДОБНО КоличествоСимволовДоТире . Симв + "-%" )
ЛЕВОЕ СОЕДИНЕНИЕ тзКоличествоСимволов100 КАК СтрДлина
ПО ( тз1сРазбиением . ВнутреннийНомер ПОДОБНО СтрДлина . Симв )
;
Выбрать
тз2сРазбиением . ВнутреннийНомер ,
Подстрока ( тз2сРазбиением . ВнутреннийНомер , 1 , КоличествоСимволовДоСлэша . КолСимв ) как ДоСлэша ,
Подстрока ( тз2сРазбиением . ВнутреннийНомер , КоличествоСимволовДоТире . КолСимв + 2 , СтрДлина . КолСимв ) как ПослеТире
поместить тз2сРазбиением
из тз2 как тз2сРазбиением
ЛЕВОЕ СОЕДИНЕНИЕ тзКоличествоСимволов100 КАК КоличествоСимволовДоСлэша
ПО ( тз2сРазбиением . ВнутреннийНомер ПОДОБНО КоличествоСимволовДоСлэша . Симв + "/%" )
ЛЕВОЕ СОЕДИНЕНИЕ тзКоличествоСимволов100 КАК КоличествоСимволовДоТире
ПО ( тз2сРазбиением . ВнутреннийНомер ПОДОБНО КоличествоСимволовДоТире . Симв + "-%" )
ЛЕВОЕ СОЕДИНЕНИЕ тзКоличествоСимволов100 КАК СтрДлина
ПО ( тз2сРазбиением . ВнутреннийНомер ПОДОБНО СтрДлина . Симв )
;
ВЫБРАТЬ Различные
тз11 . ВнутреннийНомер ,
тз22 . ВнутреннийНомер
ИЗ
тз1сРазбиением КАК тз11
Левое СОЕДИНЕНИЕ тз2сРазбиением КАК тз22
ПО тз11 . ДоСлэша Подобно тз22 . ДоСлэша
и тз11 . ПослеТире Подобно тз22 . ПослеТире
Для любителей возмущающаться напомню, что целью было отвлечься от работы J Если кому-то пригодится в практических целях, буду рада.
Оформление текстов запросов
Область применения: управляемое приложение, мобильное приложение, обычное приложение.
1. Все ключевые слова языка запросов пишутся заглавными буквами.
Методическая рекомендация (полезный совет)
2. Рекомендуется указывать и необязательные конструкции запроса, прежде всего - явно назначать псевдонимы полям, в целях повышения наглядности текста запроса и "устойчивости" использующего его кода. Например, если в алгоритме используется запрос с полем, объявленным как
при изменении имени реквизита нужно будет также изменить и код, осуществляющий обращение по имени свойства Валюта к выборке из результата запроса. Если же поле будет объявлено как
Касса.Валюта КАК Валюта
то изменение имени реквизита приведет только к изменению текста запроса.
2а. Особенно внимательно следует относиться к автоматически присваиваемым псевдонимам для полей – реквизитов других полей, типа ". Касса.Валюта.Наименование. ". В приведенном выше примере поле получит автоматический псевдоним ВалютаНаименование , а не Наименование .
2б. Следует обязательно указывать ключевое слово КАК перед псевдонимом поля источника.
3. Текст запроса должен быть структурирован, не следует писать запрос в одну строку, даже короткий. Текст запроса должен быть нагляден, поскольку это существенно улучшает его понимание другими разработчиками.
4. В запросы, сложные для понимания, в которых используются вложенные запросы, объединения или соединения рекомендуется вставлять комментарии. Комментарии, например, могут объяснять для получения каких данных используется та или иная таблица в соединении или объединении.
При этом необходимо иметь в виду, что при использовании конструктора запросов, все комментарии в запросе удаляются автоматически без предупреждения.
5. При создании объекта Запрос рекомендуется указывать комментарии, для получения какой информации или каких иных целей будет использован данный запрос.
6.1 При программной "сборке" текста запроса рекомендуется комментировать все этапы его сборки.
6.2. Нужно стараться, чтобы каждая часть формируемого запроса могла быть открыта с помощью конструктора запросов
- это позволяет осуществить экспресс-проверку корректности синтаксиса запроса
- это упрощает разработку и сопровождение кода конфигурации, в том числе сторонними разработчиками
Типичные случаи программной модификации текста запроса
Изменение имени поля выборки или таблицы
"ВЫБРАТЬ
| Номенклатура.Наименование КАК Наименование ,
| Номенклатура. " + ИмяПоляКод + " КАК КодАртикул
|ИЗ
| Справочник.Номенклатура КАК Номенклатура";
ТекстЗапроса =
"ВЫБРАТЬ
| Номенклатура.Наименование КАК Наименование,
| &ИмяПоляКод КАК КодАртикул
|ИЗ
| Справочник.Номенклатура КАК Номенклатура ;
ТекстЗапроса = СтрЗаменить(ТекстЗапроса , "&ИмяПоляКод ", "Номенклатура." + ИмяПоляКод);
или аналогично для имени таблицы
"ВЫБРАТЬ
| ТаблицаСправочника.Наименование КАК Наименование,
| ТаблицаСправочника.Код КАК Код
|ИЗ
| &ТаблицаСправочника КАК ТаблицаСправочника";
ТекстЗапроса = СтрЗаменить(ТекстЗапроса , "&ТаблицаСправочника", "Справочник." + ИмяСправочника);
или еще один вариант для имени таблицы
Конкатенация нескольких текстов запросов в пакет
Если ИспользоватьУпаковки Тогда
ТекстЗапроса = ТекстЗапроса +
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка
|ИЗ
| Справочник. Номенклатура КАК Номенклатура";
Если ИспользоватьУпаковки Тогда
"ВЫБРАТЬ
| Упаковки.Ссылка КАК Ссылка
|ИЗ
| Справочник.Упаковки КАК Упаковки";
ТекстЗапроса = ТекстЗапроса +
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка
|ИЗ
| Справочник.Номенклатура КАК Номенклатура";
ТекстыЗапросовПакета = Новый Массив;
ТекстЗапроса =
"ВЫБРАТЬ
| Упаковки.Ссылка КАК Ссылка
|ИЗ
| Справочник.Упаковки КАК Упаковки";
ТекстЗапроса =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка
|ИЗ
| Справочник.Номенклатура КАК Номенклатура ";
ТекстыЗапросовПакета.Добавить(ТекстЗапроса);
ТекстЗапроса = СтрСоединить(ТекстыЗапросовПакета, Разделитель);
Войдите как ученик, чтобы получить доступ к материалам школы
Язык запросов 1С 8.3 для начинающих программистов: функции и операторы для работы с типами (ТИПЗНАЧЕНИЯ, ТИП, ССЫЛКА, ЕСТЬNULL, ВЫРАЗИТЬ)
Автор уроков и преподаватель школы: Владимир Милькин
Давайте вспомним, что каждый реквизит (свойство, поле) справочника, документа или любого другого прикладного объекта имеет свой тип . И этот тип мы можем посмотреть в конфигураторе:
В языке запросов существует целый класс функций и операторов для работы с типами реквизитов. Давайте рассмотрим их.
Функция ТИПЗНАЧЕНИЯ
Эта функция принимает один параметр (значение) и возвращает его тип. Для описанного на картинке (выше) реквизита Вкус справочника Еда вернётся следующее:
Если мы запросим тип поля Наименование, то, как и ожидается, получим Строка:
А теперь давайте рассмотрим реквизит ОтличительныйПризнак у справочника Города:
Вы видите, что этот реквизит может иметь один из нескольких типов: Строка, Справочник.Вкусы, Справочник.Цвета. Такой тип реквизитов называется СОСТАВНЫМ .
Если мы попытаемся заполнить значение такого реквизита в режиме 1С:Предприятие, то система спросит нас, какого типа будет вводимое значение:
И только после нашего выбора позволит ввести значение выбранного типа.
Таким образом, элементы справочника одного вида (Справочник.Города) смогут хранить в одном и том же реквизите (ОтличительныйПризнак) значения разных типов (Строка, Цвета или Вкусы).
Вы можете убедиться в этом сами пощёлкав по элементам справочника Города в режиме 1С:Предприятие. Вы читаете ознакомительную версию урока, полноценные уроки находятся здесь.
Здесь значение отличительного признака является элементом справочника Вкусы:
А здесь вообще элементом справочника Цвета:
Вот какие возможности открывает перед нами составной тип данных!
Интересно, как поведёт себя функция ТИПЗНАЧЕНИЯ на реквизите ОтличительныйПризнак, имеющий составной тип данных:
Это уже очень интересно. Давайте разбираться с каждой строкой в отдельности.
Тип значения отличительного признака для элемента Россия равен NULL. Мы впервые сталкиваемся с этим типом. Значения данного типа используются исключительно для определения отсутствующего значения при работе с базой данных.
Так и есть, ведь элемент Россия является группой, а не обычным элементом справочника Города, поэтому у него отсутствует поле ОтличительныйПризнак. А тип у отсутствующего значения, как мы прочитали выше, всегда равен NULL.
Тип значения отличительного признака для Перми равен Вкусы. Так и есть, ведь значение отличительного признака забитое в базе для города Пермь является ссылкой на элемент справочника Вкусы.
Для Красноярска тип признака равен Цвета, потому что значение выбранное в базе является ссылкой на элемент справочника Цвета.
Для Воронежа тип признака равен Строка, потому что значение введенное в базе является обычной строкой.
Индия снова группа, поэтому значение отсутствует. А тип у отсутствующего значения, как мы помним, равен NULL.
Далее всё аналогично, кроме Сан-Паулу. Это не группа, а обычный элемент справочника (город), но тип его значения пустой. Как так?
А дело вот в чём. Если вы зайдёте в элемент справочника Города с наименованием Сан-Паулу, то увидите, что поле ОтличительныйПризнак совершенно никак не заполнено. Оно пустое. А все незаполненные поля составного типа имеют специальное значение НЕОПРЕДЕЛЕНО .
С НЕОПРЕДЕЛЕНО мы также сталкиваемся впервые.
Значение НЕОПРЕДЕЛЕНО применяется, когда необходимо использовать пустое значение, не принадлежащее ни к одному другому типу. Это как раз наша ситуация.
А тип для значения, которое не принадлежит ни к одному из типов, как вы уже наверное догадались отсутствует.
Функция ТИП
Она принимает всего один параметр - имя примитивного типа (СТРОКА, ЧИСЛО, ДАТА, БУЛЕВО), либо имя таблицы, тип ссылки которой нужно получить.
Результатом данной конструкции будет значение типа Тип для указанного типа.
Звучит туманно, не правда ли?
Давайте рассмотрим применение данной конструкции и всё сразу станет на свои места.
Пусть нам требуется отобрать все записи справочника Города, у которых составной реквизит ОтличительныйПризнак имеет значение типа СТРОКА:
Теперь давайте отберём все записи, у которых значения реквизита ОтличительныйПризнак являются ссылками на элементы справочника Цвета (таблица Справочник.Цвета):
Отступление
Как вы помните, некоторые элементы справочника Города не имеют реквизита ОтличительныйПризнак. Функция ТИПЗНАЧЕНИЯ для таких элементов выдаёт NULL.
Как можно сделать отбор таких элементов в запросе? Для этого предусмотрен специальный логический оператор ЕСТЬ NULL (не путать с функцией ЕСТЬNULL, которую мы рассмотрим ниже). Вы читаете ознакомительную версию урока, полноценные уроки находятся здесь.
Вот пример его использования:
Но есть и такие элементы (Сан-Паулу), у которых реквизит ОтличительныйПризнак (составного типа) просто не заполнен и равен специальному значению НЕОПРЕДЕЛЕНО.
Чтобы отобрать такие записи следует использовать другую конструкцию:
Но сравнение с НЕОПРЕДЕЛЕНО для определения пустых (не заполненных) реквизитов будет работать только для составных типов.
Кстати, у логического оператора ЕСТЬ NULL форма отрицания выглядит следующим образом:
Логический оператор ССЫЛКА
Оператор ССЫЛКА позволяет проверить, является ли значение выражения, указанного слева от него, ссылкой на таблицу , указанную справа.
К примеру, давайте выберем из справочника Города только те записи, у которых значение составного реквизита ОтличительныйПризнак являются ссылкой на элемент справочника Вкусы:
Как вы помните, эту же задачу мы могли бы решить используя ТИПЗНАЧЕНИЯ и ТИП:
Функция ЕСТЬNULL
Функция предназначена для замены значения NULL на другое значение.
Мы помним, что значение NULL возвращается в том случае, если запрашиваемый реквизит (поле, свойство) не существует.
Как например, реквизит ОтличительныйПризнак для групп справочника Города:
Функция ЕСТЬNULL поможет нам вывести другое значение в том случае, если это значение равно NULL. Вы читаете ознакомительную версию урока, полноценные уроки находятся здесь. Пусть в данном случае это будет строка "Такого реквизита нет!":
Получается, что если первый параметр функции ЕСТЬNULL не равен NULL, то возвращается он. Если же он равен NULL, то возвращается второй параметр.
Функция ВЫРАЗИТЬ
Эта функция предназначена только для полей , имеющих составной тип . Отличным примером такого поля является свойство ОтличительныйПризнак у элементов справочника Города.
Как мы помним, составные поля могут быть одного из нескольких типов, указанных в конфигураторе.
Для поля ОтличительныйПризнак такими допустимыми типами являются СТРОКА, Справочник.Цвета и Справочник.Вкусы.
Иногда возникает необходимость привести значения составного поля к какому-либо определенному типу.
Давайте приведём все значения поля ОтличительныйПризнак к типу Справочник.Цвета:
В результате, все значения элементов, которые имели тип Справочник.Цвета, остались заполненными и оказались приведенными к указанному типу. Все значения других типов (СТРОКА, Справочник.Вкусы) теперь стали равны NULL. В этом состоит особенность приведения типа при помощи функции ВЫРАЗИТЬ.
Приводить тип можно или к примитивному типу (БУЛЕВО, ЧИСЛО, СТРОКА, ДАТА) или к ссылочному типу. Вы читаете ознакомительную версию урока, полноценные уроки находятся здесь. Но тип, к которому делается приведение, обязательно должен входить в список типов для данного составного поля, иначе система выдаст ошибку.
Читайте также: