что такое динамический список
Особенности реализации динамических списков в пользовательских интерфейсах
В интерфейсе каждого современного приложения в том или ином виде присутствуют списки объектов. При работе с ними у пользователя часто возникают потребности в однотипных действиях вроде сортировки, фильтраций, экспорта и так далее. Реализация этих операций часто осложняется тем, что списки могут быть “динамическими”. В этом случае данные будут по мере необходимости считываться не только с сервера на клиент, но и с сервера базы данных на сервер приложений.
В открытой и бесплатной платформе lsFusion все списки по умолчанию являются динамическими и добавляются на любую форму в несколько строк кода. В этой статье я расскажу некоторые технические подробности их реализации, а также возможности в интерфейсе, которые автоматически предоставляются пользователю при работе с любым списком на любой форме.
Создание
В этом случае в таблице будут показываться все возможные пары объектов классов Item и Stock.
Колонки в список добавляются инструкцией PROPERTIES:
В таблицу могут быть добавлены как простые реквизиты объекта, так и любые выражения с группировками, партиционированием, рекурсией и так далее.
По умолчанию, в списке будут показаны все объекты, находящиеся в базе данных. Чтобы ограничить их можно использовать инструкцию FILTERS:
В условии фильтра можно использовать любое выражение, зависимое от любых объектов на форме.
Навигация
Когда пользователь открывает форму, платформа автоматически определяет количество видимых записей в зависимости от размеров таблицы. Для простоты изложения предположим, что таких записей — 50. В каждый момент времени платформа будет хранить и на клиенте, и на сервере по 150 записей. При этом текущий активный объект должен находиться в середине этого “окна”: с 50й по 99ю запись. Записей может быть меньше, если текущий объект находится либо в самом начале, либо в конце списка.
Если при открытии формы необходимо сделать активной какую-то конкретную запись, то к серверу базы данных делается два запроса, каждый из которых считывает по 75 записей с каждой стороны от нужной записи. Затем из их результатов склеивается общий список. В случае, когда нужно инициализировать список с начала или конца, то делается один запрос на 100 записей, а активной устанавливается первая или последняя полученная запись. То же самое происходит, если пользователь нажимает в списке CTRL+HOME или CTRL+END, чтобы перейти в начало или конец списка.
Как только пользователь делает активной запись за пределами середины текущего окна (до 50й или после 99й), то платформа считывает дополнительные записи таким образом, чтобы текущая запись оказалась в самом “центре” нового окна.
Особенность такой реализации динамического списка заключается в том, что текущий объект не может быть за пределами середины окна. Поэтому при скроллировании списка происходит автоматическое перемещение текущего объекта в видимую область.
Считывание данных в списке всегда происходит в два запроса. Первым запросом считываются только ключи нужных записей во временную таблицу. Вторым запросом считываются значения всех колонок по уже считанным ключам. Так сделано по той причине, что в колонках могут быть любые выражения, которые могут быть скомпилированы в подзапросы или другие сложные SQL конструкции. В этом случае платформа сама проталкивает эти ключи в подзапросы, чтобы расчет значений этих колонок шел не по всей базе данных, а только по нужным ключам. Это создает небольшой overhead, так как делается два запроса вместо одного, но защищает от случайного “попадания” в неэффективный план сервера базы данных.
Фильтрация
Записи в списке на форме могут быть отфильтрованы на основе следующих вариантов:
Сортировка
По умолчанию, записи в списках отсортированы по возрастанию внутренних идентификаторов объектов. Эти идентификаторы автоматически генерируются по возрастанию при создании объектов (при этом глобально уникальны в рамках всех классов), и по ним всегда построены индексы.
Сортировка в списке может быть изменена следующим образом:
В условие WHERE запроса будет добавлено выражение вида: column1 > value1 OR (column1 = value1 AND column2 > value2) OR (column1 = value1 AND column2 = value2 AND key > value). Также при считывании ключей в запрос будет добавлена инструкция LIMIT с необходимым количеством считываемых записей. При считывании записей “вверх” порядок в ORDER BY и выражение в WHERE будут соответственно “перевернуты”, чтобы считывать записи в обратную сторону.
Следует отметить, что сложность выполнения этих запросов будет относительно небольшой при наличии соответствующего индекса (так как будет осуществляться пробег по индексу, начиная от текущего ключа вверх или вниз только на заданное количество записей). Поэтому для ускорения работы с динамическим списком при сортировке по колонкам column1, column2 рекомендуется построить следующий индекс:
В случае, если сортировка идет по вычисляемой колонке, то ее можно сделать постоянно хранимой, как описано в этой статье, а затем по ней построить индекс.
Одной из особенностей подобной реализации является отсутствие “честного” скроллбара. При считывании записей осуществляется чтение только нужного их количества. Запрос на получение общего количества рядов в списке через COUNT(*) с нужным фильтром может привести к полному прогону по таблице или индексу, что негативно скажется на производительности. Та же самая проблема будет и при считывании записей через конструкцию OFFSET. Кроме того, следует учитывать, что при навигации по списку количество записей в нем может изменяться другими пользователями путем внесения новых изменений.
Редактирование
Удивительно, но в некоторых даже коммерческих платформах не смогли реализовать возможность редактирования в динамических списках. Основная сложность реализации такого механизма заключается в том, что на сервере и клиенте хранится только видимое окно, а изменения могут быть сделаны в рамках всего списка.
В lsFusion нет какого-то специфического механизма, который реализует непосредственно редактирование в списке. Эта функциональность реализована в рамках общего механизма сессий.
Все изменения, сделанные в текущей сессии изменений, сохраняются во временных таблицах. Когда пользователь что-то редактирует на форме (в том числе и значение в одной из записей), то новые значения записываются во временные таблицы с подходящими ключами. Затем, когда вторым запросом (после получения ключей) идет считывание значений колонок, то в запрос просто добавляется JOIN с соответствующими временными таблицами с изменениями.
При сохранении сессии изменений выполняется запрос, который в одной транзакции записывает все значения из временных таблиц в базу данных.
Групповая корректировка
Достаточно часто у пользователя возникает необходимость изменить значение колонки сразу для всех отобранных объектов в списке. Для этого в тулбаре каждого списка есть специальная кнопка (с горячей клавишей F12). При ее нажатии включается обычный режим редактирования ячейки, но изменения применяются не для текущей записи, а для всех отобранных.
Такой механизм позволяет быстро редактировать большое количество объектов по заданным критериям:
Также, как и при обычном редактировании, изменения не сразу сохраняются в базу данных, а записываются во временные таблицы. Затем пользователю нужно будет нажать кнопку Сохранить для записи их в базу данных. Недостатком такого подхода может быть то, что пользователь случайно изменит лишние данные. Но тут, как говорится, работает принцип: “with great power comes great responsibility”.
Итоги по списку
Для получения этих данных будет автоматически сформирован запрос с выражением COUNT(*) или SUM, в WHERE которого будет добавлено выражение текущего отбора. При помощи этой возможности можно быстро получать итоги по спискам, не прибегая к формированию отчетов.
В десктоп-версии клиента также есть возможность считать суммы по выделенным ячейкам по аналогии с Excel:
Copy / Paste
Точно так же можно из буфера обмена вставить таблицу в любой редактируемый список на любой форме:
Такая возможность часто является альтернативой разработке специализированного импорта.
Настройка таблицы
Можно изменить состав колонок, их размеры, заголовки, маски и так далее. Сохранить настройки таблицы можно как для текущего пользователя, так и для всех пользователей (если у текущего пользователя есть нужные права).
Следует отдельно отметить параметр Размер страницы. При помощи него можно изменять размер “окна”, описанного в начале статьи. Например, вместо автоматических 50 записей можно указать большее значение. Тогда на клиент и сервер будет загружаться больший объем данных, но запросы будут происходить реже. Установка значения этого параметра в 0 сделает из любого динамического списка обычный, то есть всегда будут считываться все записи списка. Величину размера окна можно также указать непосредственно в коде при помощи параметра pageSize инструкции DESIGN.
Экспорт в Excel
При этом учитываются текущие отборы, сортировки, а также только видимые колонки, указанные в настройке таблицы.
Pivoting
При небольшом количестве записей в списке работа с данными будет происходить непосредственно на клиенте. Как только количество данных превышает определенный порог, то для группировки данных будут использоваться автоматически сгенерированные запросы к базе данных на сервере.
Альтернатива
Возникает резонный вопрос. Каким образом решают проблему редактирования динамических списков в платформах, где такая возможность не поддерживаются. Чаще всего делают простой список, заставляя пользователь какими-то отборами ограничивать количество записей (например, указывать фильтры по категориям, поставщикам или другим связанным справочникам).
Однако этот подход имеет одну серьезную проблему. Даже при установленных отборах нет никакой гарантии, что в выборке не окажется значительное количество записей. Вычислить заранее количество получаемых значений невозможно, так как часто сложность такой операции сравнима непосредственно со сложностью получения всех данных. Соответственно, в некоторых случаях в список будет добавлено большое количество записей, что приведет к большому потреблению ресурсов на сервере или клиенте, а также значительному снижению производительности.
Заключение
Реализация динамического списка в современной разработке является не самой тривиальной задачей, поскольку в нее вовлечены как клиентская, так и серверная часть. В мире существует достаточно мало библиотек с открытым исходным кодом и открытой лицензией, позволяющих быстро и удобно реализовать эту функциональность.
В открытой и бесплатной платформе lsFusion динамические списки создаются в несколько строк кода и предоставляют пользователю большое количество возможностей по работе с ними. В сочетании с возможностью редактирования таких списков платформа позволяет очень быстро работать с документами на сотни тысяч строк, организовывать удобную работу по подбору записей в документы, проводить групповые изменения справочников и многое другое.
Использование динамических списков позволяет значительно снизить потребление процессорного времени и памяти на сервере и клиенте за счет работы с ограниченным набором данных, а также уменьшить загрузку канала связи между сервером и клиентом. За счет такой высокой эффективности на решениях на базе платформы lsFusion в Беларуси осуществляют свою основную операционную деятельность пять из восьми крупнейших розничных сетей.
Работа с динамическим списком в 1С 8.3 (8.2)
Наконец-то осуществилась мечта любого «семерошника». Как часто пользователи программы 7.7 просили сделать нормальный подбор номенклатуры. Чтобы и остатки можно было видеть, и цены, и установить фильтры. Приходилось придумывать разные хитрости, вплоть до написания внешних компонентов. В 1С 8.2 появились динамические списки. Предлагаю рассмотреть, что это такое и что они нам могут дать в 1С 8.3.
Создание формы выбора
За основу возьмем некую тестовую конфигурацию 1С:»Бухгалтерия предприятия 3.0″. Не будем сейчас делать подбор, просто в справочнике «Номенклатура» добавим еще одну форму выбора и сделаем ее временно основной:
При создании система по умолчанию добавит на форму табличное поле с типом «Динамический список».
Зайдем в его свойства и посмотрим, что там.
В первую очередь нас интересует флажок «Произвольный запрос». Он-то и откроет нам все преимущества динамического списка. У нас появится возможность написать собственный запрос, причем с параметрами. Устанавливаем флажок и нажимаем ссылку «Открыть»:
Откроется окно с уже готовым кодом на языке запросов. Пока что там просто перечислены все поля справочника «Номенклатура».
Как видим, имеется кнопка вызова «Конструктора запроса» и флажок, который дает возможность динамически изменять содержимое списка. То есть когда другой пользователь меняет что-то в справочнике, в нашем списке это тоже изменится. Кроме того, имеется закладка «Настройки», но ее мы коснемся позже.
Собственный запрос в динамическом списке
Сначала создадим нужный нам запрос с остатками и ценами. Примерно так:
Закладка «Настройки»
И вот теперь самое вкусное! Переходим на закладку «Настройки». И сразу видим, что на первой вкладке мы можем делать любые отборы по любому полю в запросе:
Программная установка параметров запроса в динамическом списке 1С 8.3
Не забываем, что в запросе у нас присутствуют два параметра: «Период» и «Тип цен». Мы должны передать их в запрос, иначе будет ошибка.
Пропишем эти параметры в параметрах формы, а в модуле формы добавим следующие строки:
Значения параметров можно передать из объекта, откуда вызывается форма, либо другие, установленные по умолчанию.
Далее на форму с «Динамическим списком» можно добавить таблицу значений, куда будут при двойном клике передаваться строки с выбранным товаром и затем переноситься в документ.
Также на форму можно добавить флажок «Запрашивать количество».
В этом случае мы получаем уже простенький подбор товаров, однако с достаточно расширенными возможностями.
Если Вы начинаете изучать 1С программирование, рекомендуем наш бесплатный курс (не забудьте подписаться на YouTube — регулярно выходят новые видео):
К сожалению, мы физически не можем проконсультировать бесплатно всех желающих, но наша команда будет рада оказать услуги по внедрению и обслуживанию 1С. Более подробно о наших услугах можно узнать на странице Услуги 1С или просто позвоните по телефону +7 (499) 350 29 00. Мы работаем в Москве и области.
Динамические списки в 1С на примере справочника «Контрагенты»
Обновим 1С с гарантией сохранности базы
Поможем с 1С 24/7, без выходных
Установим сервисы 1С бесплатно
Оперативно решим любые задачи по 1С
Рассмотрим работу с динамическими списками на примере конфигурации 1С.Управление торговлей. Для примера разберем динамический список для справочника «Контрагенты».
Запустим 1С в режиме «Конфигуратор».
В конфигурации найдем справочник «Контрагенты».
Откроем форму «Форма Списка».
Рассмотрим форму списка справочника. Реквизит «Список» имеет тип «ДинамическийСписок».
Двойным щелчком откроем свойства реквизита.
Нас интересует свойство «Произвольный запрос». Если для данного свойства установлен флаг, то для вывода информации в динамический список мы можем использовать собственный запрос.
Нажмем теперь «Открыть» у свойства «Настройка списка».
Перед нами открывается окно настройки запроса динамического списка. Первая вкладка «Запрос».
Мы можем ка написать запрос вручную в поле «Запрос», так и воспользоваться кнопкой «Конструктор запросов».
На данной вкладке так же стоит обратить внимание на флаги «Динамическое считывание данных» и «Автозаполнение доступных полей».
Флаг «Динамическое считывание данных» определяет размер «части» возвращаемых запросом данных. Т.е. Если флаг установлен, то «части» имеют не большой размер, но при прокрутке динамического списка может происходить небольшое подвисания из-за до получения «частей». Если флаг не установлен, то возвращаемые данные мы получаем большими «частями». Это означает, что первоначально запрос может отрабатывать дольше, но подвисаний в процессе прокрутки не будет.
Флаг «Автозаполнение доступных полей» определяет поля доступные для отбора. Если флаг установлен, то поля верхней выборки становятся доступными для установки отбора.
Вторая вкладка «Настройки».
На данной вкладке мы можем установить некоторые отборы. Стоит обратить внимание на флаг «Включать в пользовательские настройки».
Если мы установили отбор и флаг, то пользователь сможет самостоятельно отключить отбор, воспользовавшись командой «Настроить список».
Так же на вкладке «Настройки» мы можем задавать «Порядок», «Группировки» и «Условное оформление.
В случае, если мы в запросе использовали какие-либо параметры, то необходимо заполнить их значения. Установим значение параметров в модуле формы в процедуре «ПриСозданииНаСервере». Для этого воспользуемся стандартным кодом для установки параметров.
Как оптимизировать работу с программой?
В работе с 1С периодически можно столкнуться с вопросами, который не в состоянии решить обыкновенный пользователь. Если у вас в штате нет специалистов 1С или они решают более стратегические задачи, от которых отвлекать их попросту нерационально, мы приглашаем обратиться за помощью к команде профессионалов.
Вы еще не внедрили 1С или необходимо установить программу в новый филиал компании? Обратитесь за внедрением и настройкой к нам — вы сэкономите свое время и избежите возможных ошибок и проблем в дальнейшем.
Позвоните по номеру телефона, указанному на сайте или заполните форму обратной связи, чтобы наши сотрудники сориентировали по стоимости работ, подобрали оптимальное решение и рассказали, как начать сотрудничество. Ждем вас!
Программирование в 1С для всех
Динамический список 1С предназначен для вывода на форму любых данных в произвольном виде. Эти данные могут быть представлены в виде списка, таблицы или дерева. Динамический список позволяет делать сортировку выводимых данных, отбор, группировку, условное оформление и т.д. Причём, отбор, группировку и прочее может делать как разработчик, так и пользователь.
Динамический список 1С можно создать в качестве реквизита управляемой формы. Для этого достаточно, типу реквизита присвоить значение ДинамическийСписок.
В моем примере динамический список создан на основной форме обработки.
Для того, чтобы динамический список выводил какие-то данные, нам следует или указать основную таблицу в свойствах динамического списка, или написать произвольный запрос на языке запросов 1С.
Динамический список 1С — основная таблица
Динамическому списку можно назначить основную таблицу. Основная таблица – это произвольный объект метаданных (документ, справочник, регистр значения и т.д.), данные которого должны отобразиться в динамическом списке.
Например, в качестве основной таблицы выберем справочник Номенклатура.
И поместим динамический список на форму в виде таблицы, не забыв добавить колонки при размещении.
Если мы сейчас откроем обработку в пользовательском режиме 1С: Предприятия, то на основной форме обработки будет номенклатура в виде иерархического списка.
Можно сделать отображение списка в виде дерева. Для этого можно изменить режим просмотра таблицы на форме в пользовательском режиме.
Либо, поменять значение свойства Отображение таблицы формы, в которой был размещен динамический список.
После этого, динамический список на форме будет в виде дерева.
Произвольный запрос динамического списка 1С
Помимо использования основной таблицы, можно также динамический список сделать на основании запроса. Причем, можно взять за основу основную таблицу. Для примера, выведем вместе с номенклатурой цены, которые хранятся в периодическом регистре сведений Цены номенклатуры. Если мы в свойстве Произвольный запрос динамического списка установим флаг, при уже выбранной основной таблице, то у нас основная таблица будет взята за основу при формировании запроса.
Чтобы посмотреть на запрос, следует нажать на гиперссылку Открыть свойства НастройкаСписка.
В случае произвольного запроса мы можем изменить набор данных, который должен отображаться в динамическом списке. Но в этом случае все равно рекомендуется указывать основную таблицу, необходимо это делать для того, чтобы платформа могла определить, какая информация в этом динамическом списке главная, а какая второстепенная, и исходя из этого настроить стандартные команды. В том случае, если у Вас несколько таблиц и они связаны каким-то соединением, то все равно рекомендуется всегда указывать основную таблицу, потому что в противном случае производительность основного списка будет желать лучшего.
Свяжем справочник Номенклатура с виртуальной таблицей срез последних регистра сведений Цены номенклатуры.
Для этого, вызовем конструктор запроса из окна динамического списка, и добавим в список таблиц запроса виртуальную таблицу СрезПоследних. У виртуальной таблицы выберем ресурс Цена, который поместим в список полей, применив к этому полю функцию ЕстьNULL.
Свяжем левым соединением таблицу номенклатуры с виртуальной таблицей СрезПоследних регистра сведений.
И исправим имя поля Цена.
Поскольку, мы переделывали существующий динамический список, то поле цена в таблице формы не отобразилось. Добавим это поле.
После такой доработки динамического списка, на в таблице на форме будут отображаться цены у номенклатуры.
Очень подробно работа с динамическими списками дается в моей книге «Основы разработки в 1С: Такси».
В этой книге вы научитесь:
У вас, как у читателя блога, есть скидка 15 % по промо-коду: 48PVXHeYu
Более подробно о работе с другими интересными объектами языка программирования в 1С читайте в моей книге «Программировать в 1С за 11 шагов»
Изучайте программирование в 1С в месте с моей книги «Программировать в 1С за 11 шагов»
Отличное пособие по разработке в управляемом приложении 1С, как для начинающих разработчиков, так и для опытных программистов.
Промо-код на скидку в 15% — 48PVXHeYu
Если Вы всё еще «плаваете» в конструкциях языка запросов, и у Вас вызывают трудности даже самые простые запросы, то рекомендую вам мой курс «Запросы в 1С от новичка до профи». Где эти и многие другие вопросы рассматриваются более подробно.
В чем особенность этого курса:
• Курс рассчитан на тех, кто не знаком с языком запросов в 1С;
• Учебный материал грамотно скомпонован и прост в освоении;
• Несколько десятков уроков;
• Полезные практические примеры;
• Все уроки изложены понятным и простым языком
Для моих читателей, купон на скидку 25%: hrW0rl9Nnx
Если Вам помог этот урок решить какую-нибудь проблему, понравился или оказался полезен, то Вы можете поддержать мой проект, перечислив любую сумму:
можно оплатить вручную:
Яндекс.Деньги — 410012882996301
Вступайте в мои группы: