При разработке информационных систем на платформе 1С:Предприятие 8.3 часто возникает задача отображения дополнительной контактной информации, такой как телефон, мобильный телефон или электронная почта, для объектов справочников, например, «Контактные лица партнеров». Стандартный механизм хранения контактных данных в виде табличной части предоставляет гибкость, но требует специальных подходов для вывода этой информации в отдельные колонки динамического списка формы.
В этом подробном руководстве мы разберем, как получить нужные данные из табличной части «КонтактнаяИнформация» справочника «КонтактныеЛицаПартнеров» и отобразить их в виде отдельных колонок в динамическом списке. Мы будем использовать мощный механизм произвольных запросов с левыми соединениями (ЛЕВОЕ СОЕДИНЕНИЕ). Также мы коснемся нюансов работы с предопределенными значениями видов контактной информации и общих принципов использования подсистемы «Контактная информация» из Библиотеки стандартных подсистем (БСП), что позволит вам глубже понять архитектуру и разрабатывать более эффективные решения.
Прежде чем мы приступим к формированию запроса, крайне важно получить глубокое понимание того, как устроено хранение контактных данных в типовых конфигурациях 1С, использующих БСП. В большинстве таких конфигураций контактная информация не хранится в виде отдельных реквизитов объекта, а содержится в специализированной табличной части. Этот подход обеспечивает высокую гибкость и расширяемость системы.
Табличная часть «КонтактнаяИнформация»: Для объектов, которые могут иметь контактную информацию (таких как Справочник.КонтактныеЛицаПартнеров, Справочник.Организации, Справочник.Пользователи и других), предусмотрена стандартная табличная часть с именем КонтактнаяИнформация. Каждая строка этой табличной части предназначена для хранения одного вида контактных данных.
Ключевые реквизиты табличной части: Внутри табличной части КонтактнаяИнформация нас будут интересовать несколько основных реквизитов, которые определяют суть хранимых данных:
Вид: Этот реквизит является ссылкой на системный справочник ВидыКонтактнойИнформации. Именно он указывает, какой тип контактных данных хранится в данной строке: телефон, электронная почта, фактический адрес, юридический адрес и так далее. Это критически важное поле для фильтрации и идентификации данных.
Представление: В этом реквизите содержится уже сформированное, удобочитаемое значение контактной информации. Например, для телефона это будет строка "+7 (XXX) XXX-XX-XX", а для электронной почты — "example@domain.com". Именно это поле мы стремимся вывести в отдельную колонку динамического списка.
Тип: Данный реквизит представляет собой перечисление ТипыКонтактнойИнформации. Он служит для более общего категорирования контактных данных, принимая значения вроде "Адрес", "Телефон", "АдресЭлектроннойПочты". Хотя напрямую мы его не будем использовать в нашем запросе для колонок, он важен для понимания общей структуры.
Значение: В некоторых случаях здесь хранится более детальное, структурированное или "сырое" значение контактной информации, из которого впоследствии формируется Представление. Например, для адреса это могут быть отдельные поля улицы, города, дома.
Справочник «ВидыКонтактнойИнформации»: Этот справочник имеет центральное значение, поскольку его элементы определяют конкретные виды контактных данных, которые могут быть привязаны к объектам. В нем содержатся предопределенные элементы, такие как ТелефонПартнера, МобильныйТелефонПартнера, EmailКонтактногоЛицаКонтрагента, ФактическийАдресОрганизации и многие другие. Именно эти предопределенные элементы мы будем использовать в наших запросах для точной фильтрации данных.
Помимо прямого запроса к табличной части, важно знать, что Библиотека стандартных подсистем предоставляет мощные инструменты для программной работы с контактной информацией через общий модуль УправлениеКонтактнойИнформацией. Эти функции облегчают получение и изменение контактных данных в коде:
Функция КонтактнаяИнформацияОбъекта(): Эта функция позволяет нам получить контактную информацию для одного конкретного объекта. Она может вернуть как обобщенное строковое представление всех контактных данных, так и таблицу значений, содержащую детальную разбивку по видам, типам, значениям и представлениям. Ее использование особенно удобно, когда нам требуется комплексная информация об одном объекте.
Функция КонтактнаяИнформацияОбъектов(): Эта функция аналогична предыдущей, но предназначена для работы с коллекцией объектов. Она возвращает таблицу соответствия, где для каждого объекта представлены его контактные данные, что удобно для массовой обработки.
Функция СоздатьВТКонтактнаяИнформация(): При работе со сложными отчетами или обработками, где требуется многократно обращаться к контактной информации или объединять ее с другими данными, может быть полезным создать временную таблицу с контактными данными. Эта функция позволяет эффективно формировать такую временную таблицу, снижая нагрузку на базу данных и упрощая дальнейшие запросы. Однако, для нашей текущей задачи с динамическим списком, прямые соединения в основном запросе часто оказываются более подходящим решением.
Если вы разрабатываете свой собственный справочник и хотите добавить в него функциональность контактной информации, поддерживаемую БСП, вам необходимо будет выполнить несколько шагов:
Расширение типа ВладелецКонтактнойИнформации: В метаданных вашей конфигурации найдите определяемый тип ВладелецКонтактнойИнформации. В его составе необходимо добавить ссылку на ваш новый справочник. Это укажет системе, что ваш справочник может являться владельцем контактной информации.
Создание табличной части «КонтактнаяИнформация»: В вашем новом справочнике создайте табличную часть с предопределенным именем КонтактнаяИнформация. Важно, чтобы эта табличная часть содержала набор обязательных реквизитов, которые соответствуют стандарту БСП (например, Вид, Представление, Тип). Вы можете скопировать структуру реквизитов из аналогичной табличной части, например, из справочника Пользователи или Партнеры, чтобы обеспечить совместимость.
Для эффективного вывода различных видов контактной информации в отдельные колонки динамического списка, мы будем использовать подход с произвольным запросом. Этот метод дает нам полный контроль над логикой получения данных, позволяя вручную описать запрос с использованием механизма левых соединений (ЛЕВОЕ СОЕДИНЕНИЕ), что является ключевым для нашей задачи.
Начало запроса и выбор основной таблицы: Мы начинаем с выбора основной таблицы нашего динамического списка, которая будет содержать базовую информацию о контактных лицах партнеров. В нашем случае, это Справочник.КонтактныеЛицаПартнеров. Нам также потребуется выбрать все необходимые базовые поля из этого справочника.
ВЫБРАТЬ
СправочникКонтактныеЛицаПартнеров.Ссылка КАК Ссылка,
СправочникКонтактныеЛицаПартнеров.Наименование КАК Наименование,
// ... здесь будут добавлены другие базовые поля из справочника ...
NULL КАК Телефон, // Эти поля будут заполнены через соединения
NULL КАК МобильныйТелефон,
NULL КАК ЭлПочта
ИЗ
Справочник.КонтактныеЛицаПартнеров КАК СправочникКонтактныеЛицаПартнеров
Обратите внимание, что мы сразу включаем заглушки для полей, которые будут содержать контактную информацию. Это помогает структурировать запрос и подготовиться к добавлению данных.
Применение левых соединений для каждого вида контактной информации: Теперь нам предстоит "подтянуть" данные из табличной части КонтактнаяИнформация для каждого необходимого вида контактных данных (таких как обычный телефон, мобильный телефон, электронная почта) в отдельную колонку. Для этого мы последовательно используем несколько операторов ЛЕВОЕ СОЕДИНЕНИЕ, каждый из которых будет обращаться к одной и той же табличной части КонтактнаяИнформация, но с уникальным условием фильтрации по полю Вид.
Связывание таблиц: Каждое соединение должно быть связано с основной таблицей по полю-ссылке, которое является владельцем контактной информации. В нашем случае это СправочникКонтактныеЛицаПартнеров.Ссылка = Телефоны.Ссылка. Таким образом, мы связываем каждое контактное лицо с его соответствующими строками в табличной части контактной информации.
Фильтрация по Виду: Ключевым и самым важным аспектом каждого соединения является условие по полю Вид. Мы должны точно указать, какой именно вид контактной информации нас интересует в данном конкретном соединении. Для этого используется функция ЗНАЧЕНИЕ(), которая позволяет получить ссылку на предопределенный элемент справочника ВидыКонтактнойИнформации. Например, условие для обычного телефона будет выглядеть как Телефоны.Вид = ЗНАЧЕНИЕ(Справочник.ВидыКонтактнойИнформации.ТелефонКонтактногоЛицаКонтрагента).
Обработка отсутствующих данных с ЕСТЬNULL(): Важно помнить, что ЛЕВОЕ СОЕДИНЕНИЕ возвращает NULL для полей из соединяемой таблицы, если для какого-либо контактного лица отсутствует определенный вид информации (например, у него нет мобильного телефона). Чтобы в динамическом списке вместо NULL отображалась пустая строка, которая выглядит аккуратнее, мы используем функцию ЕСТЬNULL() в списке выбираемых полей. Например, ЕСТЬNULL(Телефоны.Представление, "") КАК Телефон.
Идентификация предопределенных видов контактной информации: Для корректного формирования запроса абсолютно необходимо точно знать наименования предопределенных элементов в справочнике ВидыКонтактнойИнформации, которые соответствуют нужным вам типам контактной информации. Эти наименования используются внутри функции ЗНАЧЕНИЕ(). Вы можете найти их следующими способами:
Через конфигуратор: Это самый надежный способ. Откройте конфигуратор, найдите в дереве метаданных справочник ВидыКонтактнойИнформации. Щелкните по нему правой кнопкой мыши и выберите пункт "Открыть предопределенные данные". В открывшемся окне будет представлен полный список всех предопределенных элементов этого справочника с их точными наименованиями. Обратите внимание на полные названия, которые могут включать контекст, например, ТелефонКонтактногоЛицаКонтрагента, МобильныйТелефонКонтактногоЛицаКонтрагента, EmailКонтактногоЛицаКонтрагента.
В режиме предприятия: Если у вас есть доступ к списку контактной информации для какого-либо объекта, вы можете посмотреть, какие виды там используются, например, в отчете или в карточке элемента. Хотя это может не дать точного названия для ЗНАЧЕНИЕ(), это поможет понять, какие виды данных в принципе существуют.
Всегда используйте полное имя предопределенного элемента, как оно указано в конфигураторе, чтобы избежать ошибок в запросе.
Теперь, когда мы понимаем все необходимые компоненты, давайте скомбинируем их и сформируем полный текст запроса, который вы сможете непосредственно использовать в динамическом списке. Для примера, предположим, что нам требуется получить обычный телефон, мобильный телефон и электронную почту для каждого контактного лица.
ВЫБРАТЬ
СправочникКонтактныеЛицаПартнеров.Ссылка КАК Ссылка,
СправочникКонтактныеЛицаПартнеров.ПометкаУдаления КАК ПометкаУдаления,
СправочникКонтактныеЛицаПартнеров.Наименование КАК Наименование,
СправочникКонтактныеЛицаПартнеров.Автор КАК Автор,
СправочникКонтактныеЛицаПартнеров.ДолжностьПоВизитке КАК ДолжностьПоВизитке,
СправочникКонтактныеЛицаПартнеров.Пол КАК Пол,
СправочникКонтактныеЛицаПартнеров.ДатаРождения КАК ДатаРождения,
СправочникКонтактныеЛицаПартнеров.Предопределенный КАК Предопределенный,
СправочникКонтактныеЛицаПартнеров.ИмяПредопределенныхДанных КАК ИмяПредопределенныхДанных,
СправочникКонтактныеЛицаПартнеров.ДатаРегистрацииСвязи КАК ДатаРегистрацииСвязи,
СправочникКонтактныеЛицаПартнеров.ДатаПрекращенияСвязи КАК ДатаПрекращенияСвязи,
ЕСТЬNULL(Телефоны.Представление, "") КАК Телефон,
ЕСТЬNULL(МобильныеТелефоны.Представление, "") КАК МобильныйТелефон,
ЕСТЬNULL(ЭлПочта.Представление, "") КАК ЭлПочта
ИЗ
Справочник.КонтактныеЛицаПартнеров КАК СправочникКонтактныеЛицаПартнеров
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.КонтактныеЛицаПартнеров.КонтактнаяИнформация КАК Телефоны
ПО СправочникКонтактныеЛицаПартнеров.Ссылка = Телефоны.Ссылка
И Телефоны.Вид = ЗНАЧЕНИЕ(Справочник.ВидыКонтактнойИнформации.ТелефонКонтактногоЛицаКонтрагента)
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.КонтактныеЛицаПартнеров.КонтактнаяИнформация КАК МобильныеТелефоны
ПО СправочникКонтактныеЛицаПартнеров.Ссылка = МобильныеТелефоны.Ссылка
И МобильныеТелефоны.Вид = ЗНАЧЕНИЕ(Справочник.ВидыКонтактнойИнформации.МобильныйТелефонКонтактногоЛицаКонтрагента)
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.КонтактныеЛицаПартнеров.КонтактнаяИнформация КАК ЭлПочта
ПО СправочникКонтактныеЛицаПартнеров.Ссылка = ЭлПочта.Ссылка
И ЭлПочта.Вид = ЗНАЧЕНИЕ(Справочник.ВидыКонтактнойИнформации.EmailКонтактногоЛицаКонтрагента)
Давайте еще раз проанализируем этот запрос, чтобы убедиться в понимании каждого его элемента:
Блок ВЫБРАТЬ: Здесь мы указываем все поля, которые хотим видеть в динамическом списке. Сначала идут стандартные реквизиты справочника КонтактныеЛицаПартнеров. Затем, для каждого вида контактной информации, мы используем конструкцию ЕСТЬNULL(ПсевдонимСоединения.Представление, "") КАК ИмяКолонки. Это позволяет получить значение из поля Представление из соответствующего левого соединения. Если для данного контактного лица информация указанного вида отсутствует, функция ЕСТЬNULL гарантирует, что в колонке отобразится пустая строка вместо NULL.
Блок ИЗ: Здесь мы указываем основную таблицу запроса — Справочник.КонтактныеЛицаПартнеров, давая ей псевдоним СправочникКонтактныеЛицаПартнеров для удобства.
Блоки ЛЕВОЕ СОЕДИНЕНИЕ: Это самый важный элемент нашего запроса. Мы используем три отдельных ЛЕВОЕ СОЕДИНЕНИЕ. Каждое соединение обращается к одной и той же табличной части — Справочник.КонтактныеЛицаПартнеров.КонтактнаяИнформация, но получает свой уникальный псевдоним (Телефоны, МобильныеТелефоны, ЭлПочта). Это позволяет нам рассматривать данные для каждого вида информации как из отдельной таблицы.
Блок ПО в каждом соединении: Условие соединения всегда состоит из двух частей, объединенных оператором И:
СправочникКонтактныеЛицаПартнеров.Ссылка = ПсевдонимСоединения.Ссылка: Эта часть связывает основную запись справочника (контактное лицо) с соответствующими строками его табличной части КонтактнаяИнформация. То есть, мы говорим системе: "Найди все строки контактной информации, которые относятся к этому контактному лицу".
ПсевдонимСоединения.Вид = ЗНАЧЕНИЕ(Справочник.ВидыКонтактнойИнформации.ИмяПредопределенногоВида): Эта вторая часть фильтрует строки табличной части по конкретному виду контактной информации. ЗНАЧЕНИЕ() позволяет получить ссылку на предопределенный элемент справочника ВидыКонтактнойИнформации. Крайне важно: убедитесь, что вы используете точные и актуальные для вашей конфигурации наименования предопределенных видов контактной информации (например, ТелефонКонтактногоЛицаКонтрагента, МобильныйТелефонКонтактногоЛицаКонтрагента, EmailКонтактногоЛицаКонтрагента). Ошибки в этом месте являются наиболее частой причиной того, что данные не выводятся.
Благодаря использованию ЛЕВОГО СОЕДИНЕНИЯ, мы гарантируем, что в списке будут присутствовать все контактные лица, даже если для некоторых из них отсутствуют определенные виды контактной информации. Если бы мы использовали ВНУТРЕННЕЕ СОЕДИНЕНИЕ, то в списке остались бы только те контактные лица, у которых есть все три вида контактной информации (телефон, мобильный, почта), что, как правило, не соответствует требованиям.
После того как вы успешно сформировали и протестировали запрос (например, в консоли запросов), следующим шагом будет интеграция его в динамический список на форме вашего справочника КонтактныеЛицаПартнеров. Этот процесс включает несколько важных действий:
Установка произвольного запроса: Откройте форму списка справочника КонтактныеЛицаПартнеров в конфигураторе. В дереве элементов формы найдите ваш динамический список (обычно он имеет имя, оканчивающееся на "Список"). Перейдите в окно свойств динамического списка. В поле "Основная таблица" измените значение с автоматического выбора (например, Справочник.КонтактныеЛицаПартнеров) на опцию "Произвольный запрос". После этого вставьте подготовленный текст SQL-запроса в появившееся поле для текста запроса. Это позволит динамическому списку использовать вашу, а не автоматически сгенерированную платформой логику выборки данных.
Добавление полей на форму: После того как запрос установлен, перейдите на вкладку "Данные" динамического списка. Убедитесь, что в списке доступных полей появились новые поля, которые вы определили в запросе (например, Телефон, МобильныйТелефон, ЭлПочта). Теперь вы можете перетащить эти поля из списка доступных полей в элементы формы (таблицу списка) в нужные вам места. Они будут отображаться как отдельные колонки, содержащие соответствующую контактную информацию для каждого элемента списка.
Параметризация запроса (дополнительная возможность): Если возникает необходимость динамически изменять, какие виды контактной информации отображать, например, в зависимости от настроек пользователя или контекста формы, вы можете использовать параметры в запросе. Это значительно увеличивает гибкость решения.
Параметр в запросе: В вашем запросе условие по виду будет выглядеть так:
И Телефоны.Вид = &ВидТелефона
где &ВидТелефона — это имя параметра.
Установка значения параметра программно: Затем, в обработчике события формы, например, ПриСозданииНаСервере или ПриОткрытии, вы устанавливаете значение этого параметра для динамического списка:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Предполагаем, что ваш динамический список называется "Список"
Список.Параметры.УстановитьЗначениеПараметра("ВидТелефона", Справочники.ВидыКонтактнойИнформации.ТелефонКонтактногоЛицаКонтрагента);
КонецПроцедуры
Для каждого вида контактной информации, который вы параметризуете, потребуется свой уникальный параметр и соответствующее условие в запросе, если вы используете несколько левых соединений. Этот подход позволяет управлять содержимым колонок динамического списка без изменения самого текста запроса в конфигураторе.
При работе с контактной информацией и динамическими списками, особенно в крупных и высоконагруженных системах, всегда держите в уме вопросы производительности и удобства дальнейшего сопровождения. Следующие рекомендации помогут вам создавать более эффективные и поддерживаемые решения:
Оптимизация запросов и кэширование: Запросы с большим количеством левых соединений, особенно к табличным частям, могут замедлять работу динамического списка, если объем данных значителен. Если вы сталкиваетесь с проблемами производительности, рассмотрите возможность создания регистров сведений, в которых часто используемая контактная информация будет кэшироваться в "плоском" виде. Например, можно создать периодический регистр, который будет хранить последний актуальный телефон и email для каждого контактного лица. Это позволит значительно упростить запрос динамического списка, обращаясь не к табличной части, а к готовым данным регистра.
Индексирование полей: Убедитесь, что поля, используемые в условиях соединения и фильтрации (в нашем случае это Ссылка и Вид табличной части КонтактнаяИнформация), проиндексированы. Индексы существенно ускоряют выполнение запросов, особенно при работе с большими объемами данных. Платформа 1С обычно автоматически индексирует стандартные поля, но для пользовательских или специфических настроек может потребоваться ручная проверка или добавление индексов.
Использование стандартных отчетов БСП: Во многих конфигурациях на БСП предусмотрены типовые отчеты, которые уже умеют работать с контактной информацией. Например, может существовать отчет типа "Контактная информация контактных лиц". Прежде чем писать собственный запрос, всегда проверяйте наличие и функциональность таких стандартных отчетов. Они часто позволяют выбрать необходимые реквизиты, произвести отбор по партнерам и сформировать данные без необходимости написания какого-либо кода или запросов.
Программная обработка групповых данных: Если ваша задача не просто вывести данные в список, а получить контактную информацию для большого количества объектов и затем выполнить над ней какие-либо сложные программные действия (например, экспорт, анализ, массовое изменение), более эффективным может быть использование программных механизмов БСП. Функции типа УправлениеКонтактнойИнформацией.КонтактнаяИнформацияОбъектов() или работа с временными таблицами, созданными через УправлениеКонтактнойИнформацией.СоздатьВТКонтактнаяИнформация(), могут обеспечить лучшую производительность и управляемость по сравнению с попытками выполнить все в одном сложном SQL-запросе к динамическому списку.
Вывод различных видов контактной информации в отдельные колонки динамического списка 1С является распространенной и важной задачей, которая эффективно решается с помощью произвольного запроса, использующего левые соединения. Глубокое понимание структуры хранения контактной информации, знание предопределенных элементов справочника ВидыКонтактнойИнформации и правильное построение запроса являются ключевыми факторами для создания гибких, функциональных и производительных форм. Всегда стремитесь к оптимизации запросов, используйте индексирование и активно применяйте стандартные механизмы Библиотеки стандартных подсистем там, где это возможно, для обеспечения высокой производительности и удобства дальнейшего развития вашей информационной системы.