Получить идентификатор строки динамического списка 1с

Обновлено: 02.07.2024

Как известно, в последних версиях конфигураций 1С, работающих в режиме управляемого приложения, широко используется объект ДинамическийСписок. В частности, динамические списки используются для вывода списков справочников, документов и т.п.

Иногда возникает задача полностью обойти весь динамический список и провести с его строками какие-то операции. Но тут возникает проблема: динамический список нигде не хранится целиком (на то он и динамический). Строки динамического списка подгружаются постепенно, порциями. Таким образом, у динамического списка нет итератора, с помощью которого можно было бы его обойти целиком, итоговое количество строк также неизвестно.

Решить эту проблему можно выполнив запрос, аналогичный тому, который выполняется динамическим списком. Но в этом случае, в дополнение к тексту запроса, нужно еще получить и учесть все отборы, сортировки и прочие параметры, которые установил пользователь.

К счастью, начиная с версии платформы 1С:Предприятие 8.3.6.1977, доступен более простой способ.

  • Список — элемент управляемой формы, в который выводится динамический список.
  • Функция должна преобразовать динамический список в таблицу значений.
  • Функция должна выполняться на сервере.

&НаСервере
Функция ДинамическийСписокВТаблицуЗначений ( )

//Получаем схема компановки данных (здесь хранится текст запроса)
Схема = Элементы . Список . ПолучитьИсполняемуюСхемуКомпоновкиДанных ( ) ;

//Получаем настройки пользователя (отборы, сортировки и т.п.)
Настройки = Элементы . Список . ПолучитьИсполняемыеНастройкиКомпоновкиДанных ( ) ;

//Выводим динамический список в таблицу значений
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных ( ) ;
МакетКомпоновки = КомпоновщикМакета . Выполнить ( Схема , Настройки , , , Тип ( "ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений" ) ) ;

ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных ;
ПроцессорКомпоновки . Инициализировать ( МакетКомпоновки ) ;

ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений ;
Результат = ПроцессорВывода . Вывести ( ПроцессорКомпоновки ) ;

//Возвращаем полученную таблицу значений
Возврат Результат ;

Вот и все. Кстати, еще один плюс данного метода в том, что он работает довольно быстро, даже если строк в динамическом списке много.

Как программно выделить все строки динамического списка?

В платформе “1с предприятие 8.2″ появился такой замечательный объект как “динамический список“. Данный объект я часто использую в подборах, если не нужно делать сложные расчеты, а просто показать данные и выбрать.

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

Для решения это задачи я использовал объект “WSCript.Shell“.

В процессе реализации у меня получилось 2 варианта:
Вариант №1
Определим кнопку “Выделить все строки” и в модуль обработчика добавим код:
Код 1C v 8.2 УП
С помощью данного кода выполняется нажатие клавиш “Ctrl + A“, т.е. “выделить все”.

Вариант №2
Вариант №1 не всегда срабатывал. Тогда данный код я переписал следующим образом:

Добавим реквизит формы “ПоследняяСтрокаСписка”
Для списка укажем свойство “Начальное отображение списка” = В конце списка
В процедуру “ПриОткрытии” добавим заполнение реквизита, определенного в пункте 1.
Код 1C v 8.2 УП

Определим кнопку “Выделить все строки” и в модуль обработчика добавим код:
Код 1C v 8.2 УП

С помощью данного кода выполняется нажатие клавиш “Shift + кнопка вверх“.

Хочу обратить внимание. Данное решение не будет работать на клиентах, которые запускаются на Линукс.


Похожие FAQ

Еще в этой же категории

Как на управляемой форме разместить список регистра сведений с отбором? 15
Решение рассмотрено для элемента справочника (Контрагент и регистр КонтактнаяИнформация) 1. Создание реквизита: Добавляем новый реквизит формы (. не путать с реквизитом справочника . ) с типом " ДинамическийСписок" В поле " Основная табли Поле выбора

Программное создание таблицы значений с условным оформлением 6
Как создать на форме таблицу и сделать для нее подсветку содержимого колонки в строке по условию? Итак для начала нам надо добавить реквизиты в форму. Для этого у нас есть метод: ИзменитьРеквизиты(). Перед тем как его использовать мы сформируем ма Посмотреть все в категории Работа с Формой (Диалог) и её элементами

Как организовать перебор строк динамического списка (например, СправочникСписок или ДокументСписок)?

Это можно сделать с помощью построителя отчетов, например:

Построитель = Новый ПостроительОтчета; Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(ДокументСписок); Выборка = Построитель.Результат.Выбрать(); Пока Выборка.Следующий() Цикл

Замечание: в выборку попадут строки в соответствии с установленным в текущий момент отбором.

Как в форме списка реализовать сортировку по своему реквизиту?

Если реквизит примитивного типа, то достаточно установить для свойства реквизита Индексировать значение Индексировать или Индексировать с доп. упорядочиванием (не доступно для реквизитов типа ХранилищеЗначения).

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

Достаточно долгое время единственным уникальным ключом позиции в динамическом списке (далее ДС) являлась или ссылка, или конструкт вроде ключа записи регистра, чей состав и уникальность поддерживались платформой непрозрачно для разработчика. 1С сама транслировала ссылки и ключи в данные, однозначно идентифицирующие каждую подгружаемую, кэшируемую и выводимую строку динамического списка. Принципы подгрузки с сервера (при пролистывании, позиционировании, отборах), кэширования и обновления кэша, принципы показа и программного обращения - всё это было единообразно, но скрыто и нам недоступно.

Ситуация изменилась в релизе 8.3.14, где платформа стала поддерживать разные варианты ключей при работе с ДС, в т.ч. для произвольных запросов без основной таблицы. Это хорошо описано в Зазеркалье и на других ресурсах. Мы получили удобный инструмент решения коллизий дублирования ключевых полей, оптимизацию, прозрачность и управляемость (хотя бы фактом кэширования). Поведение системы в целом осталось тем же - контроль реальной уникальности ключа, каким бы он ни был, поддержка возможностей ДС, клиент-серверное взаимодействие и т.д., и при этом интерактивное добавление, удаление, открытие; т.е. то, что раньше было возможно лишь при наличии основной таблицы.

Тем не менее, есть нюансы поведения ДС при отсутствии основной таблицы и, тем более, с разными видами ключей.

Не весь функционал ДС с основной таблицей унаследован для ДС с произвольными запросами, даже для случаев, когда, казалось бы, построение ключа и поведение системы ровно то же. Так, "Уведомление не влияет на динамические списки, у которых не задана основная таблица" (с) СП, т.е. мы не можем рассчитывать на обновление ДС и очистку кэша форм выбора при вызове "ОповеститьОбИзменении" и при работе аналогичных стандартных команд. Приходится делать вручную, как и ранее.

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

Также, неработоспособен параметр формы "ТекущаяСтрока". Он автодобавляется при указании ДС, с любым видом ключа, как основного реквизита формы (что видно в подсказке при наборе кода), и поддерживает все возможные содержания при видах ключей, и передаётся, и читается программно, но свою основную задачу - позиционирование, особенно при открытии - не выполняет, игнорируется.

Есть особенности в поведении произвольных запросов с разными ключами, рассмотрим их на примере общеизвестных функций получения СКД и настроек ДС (например,

Может указываться и для произвольного запроса без основной таблицы. При этом поле значения ключа сам не очищает и не проверяет.

Если указана основная таблица, то вид ключа "Авто", а поля ключа - пустой фиксированный массив. Вроде бы всё по умолчанию. Но при этом возможна ситуация, когда поле "Ссылка" есть в Наборе, в доступных к выбору и выбранных полях настройки СКД по умолчанию, и в Выбор текущей настройки СКД, но даже при плоской детализации структуры (взятой по умолчанию) его нет в результатной выборке-таблице. Во всех прочих вариантах ключей эффект не наблюдается, поле есть. От флага "ИспользоватьВсегда" этот эффект не зависит.

Если для произвольного запроса указана основная таблица, ПоляКлюча не то что бы недоступны, а именно "не используются" (с) СП. Замечено, что поведение при обращении к полям ключа может разниться для толстого и тонкого клиентов.

Вообще, "ПоляКлюча" согласно СП это "СписокПолей" (для ВводПоСтроке и ПоляКлюча внешних источников), но, в отличие от указанного в СП, т.е., цитирую, "В качестве полей ввода по строке могут выступать такие предопределенные реквизиты, как "Код", "Наименование", "Дата", "Номер" и реквизиты объектов, имеющие примитивный тип данных, для которых свойство объекта метаданных "Индексировать" принимает значение "Индексирование" или "Индексировать с доп. упорядочиванием"." - тут выбор доступных к указанию как поля ввода явно больше - и не только примитивные типы и предопределённые значения. Программно это подтверждается, поэтому и внимания к типизации полей СКД надо больше. Особенно, как всегда, аккуратнее с определяемыми типами, характеристиками, хранилищами, неогр.строками итд.

Даёт на выбор в значениях ключа всё, все поля выборки запроса, кроме "ВерсияДанных".
ПоляКлюча - фиксированный массив строк (всегда строго один элемент), где строки это имена полей (опять же, не следует применять разыменования от полей выборки "первого уровня", даже если конструктор ДС это скушал)
ТекущаяСтрока - текущее значение поля нужного типа.

Даёт на выбор вообще всё, любые поля. Явных ограничений ни по типам, ни по составу, ни по разыменованию нет. Но, полагаю, с разыменованиями тоже не следует связываться - опять же, любое поле "через точку" как неявное соединение с другими таблицами негативно скажется на производительности.
ПоляКлюча - фиксированный массив (возможны N элементов), каждый из элементов это строка с именем поля ключа.
ТекущаяСтрока - КлючСтрокиДинамическогоСписка - коллекция из "КлючИЗначение", причём значения - нужных типов и, если был многотипный, значение уже строго одного типа, типа реального наполнения.

Выбор настройки ПолеКлюча недоступен, в т.ч. программно; платформа нумерует строки выборки сама. Причём, как показали замеры, это делается на клиенте.
ПоляКлюча - пустой фикированный массив.
ТекущаяСтрока - число (нумерация с 1), причём это не свойство строки как объекта данных, это свойство текущей позиции исключительно при текущем сеансе показе (вывода порции данных на экран), т.е. сортировка по колонке и прочие манипуляции на идентификации не сказываются - всегда идёт по натуральному ряду, и под неким номером каждый раз могут оказываться разные строки выборки.

Для всех случаев ключей нельзя использовать поля, могущие иметь значения "Неопределено" и "Null", даже потенциально. Тут платформу одолевает паранойя даже при очевидных разыменованиях и составных типах. Многотипные, в общем случае, допустимы, в т.ч. смешанные из простых и ссылочных типов.

Если ДС сгруппирован, т.е. Группировки применены, то "ТекущаяСтрока" возвращает значение типа "СтрокаГруппировкиДинамическогоСписка", и её Ключ - значение ТекущиеДанные[ТекущаяКолонока] того поля группировки, где стоит активный курсор.

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

Во всех режимах одинаково полные возможности Отбора, Порядка, Условного оформления. В режиме "НомерСтроки" отсутствует возможность Группировок; при этом возвращаемый ПолучитьОграниченияИспользованияВГруппировке() массив пуст.

Поведение самой СКД также имеет особенности. Для набора (типа "Набор запроса") стоит автозаполнение, но его Поля пусты, и поля Выбор и ДоступныеДляВыбора пусты; пусто и в СКД.НастройкиПоУмолчанию, и в основном варианте настройки. Актуальны и приоритетны именно исполняемые настройки: в Выборе пусто, а в Доступных для выбора - все нужные поля есть и корректно объявлены. Даже для вида ключа "Номер строки" в "ДоступныеПоляГруппировок" есть все поля выборки; в структуре запись детальной группировки (без групп.полей), в её выбранных - все поля выборки.

Если у ДС указаны в конфигураторе настройки, все они ровно так и отображается (отбор, порядок, группировка как структура), но искать их следует именно в исполняемых настройках, а не в НастройкиПоУмолчанию.

Получение ограничений использования (в отборе, в сортировке, в группировках) совершенно ничем не отличается от "Авто" и интереса не представляет.

Механизм автозаполнения доступных полей, механизм свойства "ПолучениеПредставленийДляНевидимыхПолей" (и соответственно кэш представлений ссылок формы) работают для всех случаев строго так же, как для обычных с основной таблицей.

И собственно функция, реализующая демонстрационную задачу

Получение текущих данных на сервере для разных видов ключей

Важно: при программной работе со свойствами ДС интерпретатор платформы не проверяет правильность и взаимную связность настроек (это делает только интерфейс настройки ДС), т.е. например "ВидКлюча" не "Авто", и принудительно указывается свойство "ОсновнаяТаблица"; конфликт может вылезти только при исполнении - при первом обращении ДС к данным БД. В лучшем случае это будет ругательный MsgBox, в худшем - захват всей таблицы, которая основная, и повисание сеанса. Следует быть внимательным, а на релизах ниже 8.3.15 вообще лучше не трогать в коде эти свойства.

Открытым остаётся вопрос о порции считывания. При установленном флаге "Динамическое считывание данных" (доступном только при указанной основной таблице произвольного запроса, т.е. только в режиме "Авто") платформа читает от 45 до 70 записей таблицы (насколько я понял, в зависимости от постраничной разбивки читаемых таблиц СУБД). А вот различается ли размер порции при других видах ключей и кэшируются ли они промежуточно по внутренним ID либо перестраиваются и перечитываются каждый раз - тема отдельного исследования. Заявленный размер порции в 1000 записей на практике соблюдается не всегда, поэтому, по-хорошему, изучить бы надо и степень горячести запроса/прогретости кэша, и способ (курсор или через темпы), и тот же пейджинг, и всё это в связке с принципом построения итогового внутреннего хеш-ключа. Словом, простор для исследований.

Затупил над простым вопросом. На УФ есть динамический список с основной таблицей в виде РС подчиненного регистратору. Надо получить значения из определенных колонок выделенных пользователем строк. В ТЧ это решается через получение ИД строк и метода:

У динамического списка такового нет. Как быть?

salt7; An-Aleksey; i.c.h; MariusUrsus; Serega-artem; Sashares; + 6 – Ответить

(19)Понятно.
Сначала надо в отдельный массив выделенные строки добавить.

А потом уже его обходить для получения данных.

(1) ВыделенныеСтроки (SelectedRows)
Использование:
Только чтение.
Описание:
Тип: Массив.
Содержит массив идентификаторов выделенных строк. (2) Так ИД получить не проблема, проблема получить данные по этим ИД. (6) Вы вопрос читали? Нет у динамического списка НайтиПоИдентификатору() ! (4) В выделенные строки заглядывали? Идентификаторами для динамического списка, основная таблица которого – РС, являются ключи записи этого РС. (11)А если убрать основную таблицу, то просто число.
Поэтому не суть что там. На УФ есть динамический список с основной таблицей в виде РС подчиненного регистратору. (13)Это я видел.
Я к тому, что из ключей ничего получить нормально нельзя. (14) Как раз из данных строки вы ничего не получите, точнее получите значения отображаемых колонок. При работе с ДС всегда следует работать с идентификаторами строк (ТекущаяСтрока / ВыделенныеСтроки). Надо получить значения из определенных колонок выделенных пользователем строк.

Именно это можно сделать из текущих данных, как предложено в (10)

При работе с ДС всегда следует работать с идентификаторами строк
Пока ничего полезного по теме вы не сказали.
Вот у вас идентификатор КлючЗаписи регистра, дальше что?

(16) Ваш вариант работает, но как-то странно: выводится информация только по части строк, причем закономерности особой не вижу! Буду копать дальше.

Про КлючЗаписи знаю, игрался долго с ним перед тем как задать вопрос на форму, но ничего путного не получил.

(19)Понятно.
Сначала надо в отдельный массив выделенные строки добавить.

А потом уже его обходить для получения данных.

(23)Сложно))
И максимум, что увижу - измерения.
А если надо ресурс или реквизит - предлагаете заново читать по ключу? (26) Вы получите Набор значений, однозначно идентифицирующих запись регистра. Этого более чем достаточно.

(27)
Если нужно получить значение из списка, который показывается пользователю на форме, считаю, что получать ключи регистра, потом по ключам читать записи регистра - не адекватное решение.

Если же нужно получить данные записей РС, которых нет в колонках списка, то ваш вариант, бесспорно, подходит.

(28) Это работает точно так же как с динамическим списком справочника или документа. Если вам понадобится получить какой-либо реквизит документа из выделенной строки списка, вы вряд ли будете его вытаскивать из данных строки – вы возьмете ссылку документа и на сервере получите его значение в запросе. Иначе вам необходимо предусмотреть наличие этой колонки в списке, пользовательскую видимость или включенное свойство реквизита ДС "Использовать всегда". (1)Если не указывать основную таблицу (если она регистр сведений), то в целом можно.

(5)Предыдущий комментарий не корректный. Извиняюсь.
Можно так:

Взять выделенные строки списка.
В цикле устанавливать текущей строкой - одну из выделенных.
Из ТекущихДанных брать значение.

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

Следует отметить, что свойство ТекущиеДанные содержит коллекцию значений текущей строки, соответствующую коллекции колонок отображаемого динамического списка, при этом если нужного поля нет в текущих данных, то его можно добавить в коллекцию полей списка используя метод Добавить() коллекции колонок списка.

Свойство ТекущиеДанные предназначено для получения значений колонок текущей строки, а свойство ТекущаяСтрока для получения и установки текущей строки табличного поля.

Следует понимать, что для объектных данных (Справочник, Документ и т.д.) в качестве значения свойства ТекущаяСтрока используется ссылка на объект базы данных. Соответственно при обращении к свойствам этого значения будет выполняться считывание объекта базы данных.

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

Рекомендуется для обращения к данным объекта использовать свойство ТекущиеДанные . Правильный фрагмент приведен ниже:

Если есть идентификатор текущей строки (т.е. свойство ТекущаяСтрока ), можно получить ТекущиеДанные . И наоборот:

Выполняет поиск элемента списка значений по идентификатору.

Синтаксис

Метод НайтиПоИдентификатору() имеет следующий синтаксис:

А также альтернативный англоязычный синтаксис:

Параметры

Описание параметров метода НайтиПоИдентификатору() :

Имя параметра Тип Описание
Идентификатор Число Идентификатор элемента списка значений.
Жирным шрифтом выделены обязательные параметры

Возвращаемое значение

Описание

Метод НайтиПоИдентификатору() выполняет поиск элемента списка значений по идентификатору. Если элемент с указанным идентификатором в списке отсутствует, будет возвращено значение Неопределено .

Доступность

Тонкий клиент, веб-клиент, мобильный клиент, сервер, толстый клиент, внешнее соединение, мобильное приложение(клиент), мобильное приложение(сервер).

Пример использования

Пример кода с использованием метода НайтиПоИдентификатору() :

В табличных частях объектов 8.2 имеется возможность создавать реквизиты типа ХранилищеЗначения но сохранеие этих реквизитов в тонком клиенте отрабатывается некорректно, разве что каждый раз после присваивания вызывать метод записи объекта Записать () , что не очень то удобно использовать каждый раз при изменении отдельной строки. Для корректной работы с реквизитами такого типа предлагаю сохранять значения в соответствия, которое в свой черед помещается в реквизит формы типа ХранилищеЗначения. Ключом соответствия является идентификатор строки табличной части

УдалитьДанныеИзСоответствия ( ДанныеСтроки . НомерСтроки );
КонецПроцедуры

Хранилище = Новый ХранилищеЗначения ( Соответствие );
КонецПроцедуры

Соответствие = Хранилище . Получить ();
Соответствие . Вставить ( Индекс , Новый ХранилищеЗначения ( Файл ));
Хранилище = Новый ХранилищеЗначения ( Соответствие );

ЗначениеВРеквизитФормы ( СправочникОбъект , "Объект" );
КонецПроцедуры

Соответствие = Хранилище . Получить ();
Соответствие . Удалить ( ИндексТекущейСтроки );
Хранилище = Новый ХранилищеЗначения ( Соответствие );
КонецПроцедуры .

Читайте также: