Книга знаний

1С:Предприятие / v8

v8: Прочтение списка строк табличного поля

Способы прочтения списка строк табличного поля, в котором установлен отбор записей.Автор статьи: PR | Редакторы: TormozIT, Neco, Гений 1С,
Последняя редакция №4 от 09.02.07 | История
URL: http://kb.mista.ru/article.php?id=471

Ключевые слова: Прочитать, список, табличное, поле, отбор.


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

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

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

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

Сложности начинаются тогда, когда в табличном поле установлен отбор по каким-либо полям.

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

Ниже приведен пример, позволяющий сделать запрос с отбором, аналогичным текущему отбору в табличном поле "СправочникСписок", отображающем какой-либо список, к примеру справочник "Контрагенты".
Запрос = Новый Запрос();
    
ТекстОтбора = "";
    
Для Каждого ЭлементНастройкиОтбора Из ЭлементыФормы.СправочникСписок.НастройкаОтбора Цикл
        
    Если СправочникСписок.Отбор[ЭлементНастройкиОтбора.Имя].Использование Тогда
            
        ВидСравненияЭлементаОтбора = СправочникСписок.Отбор[ЭлементНастройкиОтбора.Имя].ВидСравнения;
            
        Если ВидСравненияЭлементаОтбора = ВидСравнения.Больше Тогда
            ТекстОтбора = ТекстОтбора + Символы.ПС + "    И Контрагенты." + ЭлементНастройкиОтбора.Имя + " > &ЗначениеПараметра";
            Запрос.УстановитьПараметр("ЗначениеПараметра", СправочникСписок.Отбор[ЭлементНастройкиОтбора.Имя].Значение);
        ИначеЕсли ВидСравненияЭлементаОтбора = ВидСравнения.БольшеИлиРавно Тогда
            ТекстОтбора = ТекстОтбора + Символы.ПС + "    И Контрагенты." + ЭлементНастройкиОтбора.Имя + " >= &ЗначениеПараметра";
            Запрос.УстановитьПараметр("ЗначениеПараметра", СправочникСписок.Отбор[ЭлементНастройкиОтбора.Имя].Значение);
        ИначеЕсли ВидСравненияЭлементаОтбора = ВидСравнения.ВИерархии Тогда
            ТекстОтбора = ТекстОтбора + Символы.ПС + "    И Контрагенты." + ЭлементНастройкиОтбора.Имя + " В ИЕРАРХИИ(&ЗначениеПараметра)";
            Запрос.УстановитьПараметр("ЗначениеПараметра", СправочникСписок.Отбор[ЭлементНастройкиОтбора.Имя].Значение);
        ИначеЕсли ВидСравненияЭлементаОтбора = ВидСравнения.ВСписке Тогда
            ТекстОтбора = ТекстОтбора + Символы.ПС + "    И Контрагенты." + ЭлементНастройкиОтбора.Имя + " В (&ЗначениеПараметра)";
            Запрос.УстановитьПараметр("ЗначениеПараметра", СправочникСписок.Отбор[ЭлементНастройкиОтбора.Имя].Значение);
        ИначеЕсли ВидСравненияЭлементаОтбора = ВидСравнения.ВСпискеПоИерархии Тогда
            ТекстОтбора = ТекстОтбора + Символы.ПС + "    И Контрагенты." + ЭлементНастройкиОтбора.Имя + " В ИЕРАРХИИ(&ЗначениеПараметра)";
            Запрос.УстановитьПараметр("ЗначениеПараметра", СправочникСписок.Отбор[ЭлементНастройкиОтбора.Имя].Значение);
        ИначеЕсли ВидСравненияЭлементаОтбора = ВидСравнения.Интервал Тогда
            ТекстОтбора = ТекстОтбора + Символы.ПС + "    И Контрагенты." + ЭлементНастройкиОтбора.Имя + " > &ЗначениеПараметра1";
            ТекстОтбора = ТекстОтбора + Символы.ПС + "    И Контрагенты." + ЭлементНастройкиОтбора.Имя + " < &ЗначениеПараметра2";
            Запрос.УстановитьПараметр("ЗначениеПараметра1", СправочникСписок.Отбор[ЭлементНастройкиОтбора.Имя].ЗначениеС);
            Запрос.УстановитьПараметр("ЗначениеПараметра2", СправочникСписок.Отбор[ЭлементНастройкиОтбора.Имя].ЗначениеПо);
        ИначеЕсли ВидСравненияЭлементаОтбора = ВидСравнения.ИнтервалВключаяГраницы Тогда
            ТекстОтбора = ТекстОтбора + Символы.ПС + "    И Контрагенты." + ЭлементНастройкиОтбора.Имя + " >= &ЗначениеПараметра1";
            ТекстОтбора = ТекстОтбора + Символы.ПС + "    И Контрагенты." + ЭлементНастройкиОтбора.Имя + " <= &ЗначениеПараметра2";
            Запрос.УстановитьПараметр("ЗначениеПараметра1", СправочникСписок.Отбор[ЭлементНастройкиОтбора.Имя].ЗначениеС);
            Запрос.УстановитьПараметр("ЗначениеПараметра2", СправочникСписок.Отбор[ЭлементНастройкиОтбора.Имя].ЗначениеПо);
        ИначеЕсли ВидСравненияЭлементаОтбора = ВидСравнения.ИнтервалВключаяНачало Тогда
            ТекстОтбора = ТекстОтбора + Символы.ПС + "    И Контрагенты." + ЭлементНастройкиОтбора.Имя + " >= &ЗначениеПараметра1";
            ТекстОтбора = ТекстОтбора + Символы.ПС + "    И Контрагенты." + ЭлементНастройкиОтбора.Имя + " < &ЗначениеПараметра2";
            Запрос.УстановитьПараметр("ЗначениеПараметра1", СправочникСписок.Отбор[ЭлементНастройкиОтбора.Имя].ЗначениеС);
            Запрос.УстановитьПараметр("ЗначениеПараметра2", СправочникСписок.Отбор[ЭлементНастройкиОтбора.Имя].ЗначениеПо);
        ИначеЕсли ВидСравненияЭлементаОтбора = ВидСравнения.ИнтервалВключаяОкончание Тогда
            ТекстОтбора = ТекстОтбора + Символы.ПС + "    И Контрагенты." + ЭлементНастройкиОтбора.Имя + " > &ЗначениеПараметра1";
            ТекстОтбора = ТекстОтбора + Символы.ПС + "    И Контрагенты." + ЭлементНастройкиОтбора.Имя + " <= &ЗначениеПараметра2";
            Запрос.УстановитьПараметр("ЗначениеПараметра1", СправочникСписок.Отбор[ЭлементНастройкиОтбора.Имя].ЗначениеС);
            Запрос.УстановитьПараметр("ЗначениеПараметра2", СправочникСписок.Отбор[ЭлементНастройкиОтбора.Имя].ЗначениеПо);
        ИначеЕсли ВидСравненияЭлементаОтбора = ВидСравнения.Меньше Тогда
            ТекстОтбора = ТекстОтбора + Символы.ПС + "    И Контрагенты." + ЭлементНастройкиОтбора.Имя + " < &ЗначениеПараметра";
            Запрос.УстановитьПараметр("ЗначениеПараметра", СправочникСписок.Отбор[ЭлементНастройкиОтбора.Имя].Значение);
        ИначеЕсли ВидСравненияЭлементаОтбора = ВидСравнения.МеньшеИлиРавно Тогда
            ТекстОтбора = ТекстОтбора + Символы.ПС + "    И Контрагенты." + ЭлементНастройкиОтбора.Имя + " <= &ЗначениеПараметра";
            Запрос.УстановитьПараметр("ЗначениеПараметра", СправочникСписок.Отбор[ЭлементНастройкиОтбора.Имя].Значение);
        ИначеЕсли ВидСравненияЭлементаОтбора = ВидСравнения.НеВИерархии Тогда
            ТекстОтбора = ТекстОтбора + Символы.ПС + "    И (НЕ Контрагенты." + ЭлементНастройкиОтбора.Имя + " В ИЕРАРХИИ(&ЗначениеПараметра))";
            Запрос.УстановитьПараметр("ЗначениеПараметра", СправочникСписок.Отбор[ЭлементНастройкиОтбора.Имя].Значение);
        ИначеЕсли ВидСравненияЭлементаОтбора = ВидСравнения.НеВСписке Тогда
            ТекстОтбора = ТекстОтбора + Символы.ПС + "    И (НЕ Контрагенты." + ЭлементНастройкиОтбора.Имя + " В (&ЗначениеПараметра))";
            Запрос.УстановитьПараметр("ЗначениеПараметра", СправочникСписок.Отбор[ЭлементНастройкиОтбора.Имя].Значение);
        ИначеЕсли ВидСравненияЭлементаОтбора = ВидСравнения.НеВСпискеПоИерархии Тогда
            ТекстОтбора = ТекстОтбора + Символы.ПС + "    И (НЕ Контрагенты." + ЭлементНастройкиОтбора.Имя + " В ИЕРАРХИИ(&ЗначениеПараметра))";
            Запрос.УстановитьПараметр("ЗначениеПараметра", СправочникСписок.Отбор[ЭлементНастройкиОтбора.Имя].Значение);
        ИначеЕсли ВидСравненияЭлементаОтбора = ВидСравнения.НеРавно Тогда
            ТекстОтбора = ТекстОтбора + Символы.ПС + "    И Контрагенты." + ЭлементНастройкиОтбора.Имя + " <> &ЗначениеПараметра";
            Запрос.УстановитьПараметр("ЗначениеПараметра", СправочникСписок.Отбор[ЭлементНастройкиОтбора.Имя].Значение);
        ИначеЕсли ВидСравненияЭлементаОтбора = ВидСравнения.НеСодержит Тогда
            ТекстОтбора = ТекстОтбора + Символы.ПС + "    И (НЕ Контрагенты." + ЭлементНастройкиОтбора.Имя + " ПОДОБНО &ЗначениеПараметра)";
            Запрос.УстановитьПараметр("ЗначениеПараметра", СправочникСписок.Отбор[ЭлементНастройкиОтбора.Имя].Значение);
        ИначеЕсли ВидСравненияЭлементаОтбора = ВидСравнения.Равно Тогда
            ТекстОтбора = ТекстОтбора + Символы.ПС + "    И Контрагенты." + ЭлементНастройкиОтбора.Имя + " = &ЗначениеПараметра";
            Запрос.УстановитьПараметр("ЗначениеПараметра", СправочникСписок.Отбор[ЭлементНастройкиОтбора.Имя].Значение);
        ИначеЕсли ВидСравненияЭлементаОтбора = ВидСравнения.Содержит Тогда
            ТекстОтбора = ТекстОтбора + Символы.ПС + "    И Контрагенты." + ЭлементНастройкиОтбора.Имя + " ПОДОБНО &ЗначениеПараметра";
            Запрос.УстановитьПараметр("ЗначениеПараметра", СправочникСписок.Отбор[ЭлементНастройкиОтбора.Имя].Значение);
        КонецЕсли;
            
    КонецЕсли;
        
КонецЦикла;
    
Если ТекстОтбора <> "" Тогда
    ТекстОтбора = "ГДЕ" + Символы.ПС + "    " + Сред(ТекстОтбора, 4);
КонецЕсли;
    
ТекстЗапроса =
"ВЫБРАТЬ
|    Контрагенты.Ссылка
|ИЗ
|    Справочник.Контрагенты КАК Контрагенты
|" + ТекстОтбора;
    
Запрос.Текст = ТекстЗапроса;


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


Вы спросите, как лучше?
Конечно же через построитель отчета, то есть вторым способом!

Вы спросите, почему я вам морочил голову первым вариантом и заставил разбираться в куче строк программного кода?
Ну, во-первых какие же вы программисты, если вы не понимаете сути работы программы?
А во-вторых люблю я это дело, головы морочить :))

TormozIT:


Задача достаточно нетривиальная, на самом деле. Описанный способ через источник данных построителя отчета имеет ряд серьезных недостатков. Например, он устанавливает типы не у всех доступных полей. Также в случае иерархического просмотра списка он вернет неполный порядок и отбор. И этим список недостатков не ограничивается...

Правильный же алгоритм построения запроса, который бы вадывал отображаемый список (тот же отбор и тот же порядок), занимает по крайней мере 300 строк кода. Привести его пока затруднительно, т.к. вместе с ним придется вытаскивать немаленькое дерево методов.

Описание | Рубрикатор | Поиск | ТелепатБот | Захваченные статьи | Установки | Форум
© Станислав Митичкин (Волшебник), 2005-2025 | Mista.ru

Яндекс.Метрика