Способы прочтения списка строк табличного поля, в котором установлен отбор записей. Автор статьи: PR | Редакторы: TormozIT, Neco, Гений 1С, xzorkiix



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


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

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

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

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

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

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

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

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

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

Код 1c:
ПостроительОтчета = Новый ПостроительОтчета;
ПостроительОтчета.ИсточникДанных = Новый ОписаниеИсточникаДанных(СправочникСписок);


Правда, здесь есть ряд досадных моментов, затрудняющих использование этого способа.

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

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

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

TormozIT

Универсальный способ получения списка строк табличного поля списка.
Привожу схематичный алгоритм.

Код 1c:
Функция ЛксПолучитьПостроительЗапросаСпискаТабличногоПоля(пТабличноеПоле) Экспорт
 
    МетаданныеЗначения = ЛксПолучитьМетаданные(пТабличноеПоле.Значение);
    ПостроительЗапроса = Новый ПостроительЗапроса;
    ТекстЗапроса = "ВЫБРАТЬ РАЗРЕШЕННЫЕ * ИЗ " + МетаданныеЗначения.ПолноеИмя() + " КАК 
Таблица";
 
        // Для получения списка в иерархическом режиме. Если нужна точная копия содержимого 
        // табличного поля, то закомментируйте этот фрагмент. 
    Если Истина
        И ЛксЛиМетаданныеИерархическогоОбъекта(МетаданныеЗначения)
        И пТабличноеПоле.ИерархическийПросмотр Тогда
      ТекстЗапроса = ТекстЗапроса + "
                      |ГДЕ (НЕ Таблица.ЭтоГруппа) 
                      |ИТОГИ ПО
                      |   Ссылка ИЕРАРХИЯ";
    КонецЕсли;
 
    ПостроительЗапроса.Текст = ТекстЗапроса;
    ПостроительЗапроса.ЗаполнитьНастройки();
    ЛксСкопироватьПорядок(ПостроительЗапроса.Порядок, пТабличноеПоле.Значение.Порядок);
    ЛксСкопироватьОтбор(ПостроительЗапроса.Отбор, пТабличноеПоле.Значение.Отбор);
    Если Истина
        И ЛксЛиМетаданныеИерархическогоОбъекта(МетаданныеЗначения)
        И пТабличноеПоле.ИерархическийПросмотр
    Тогда
        ПостроительЗапроса.Отбор.Добавить("Родитель");
        Если пТабличноеПоле.ТекущийРодитель <> Неопределено Тогда 
            ПостроительЗапроса.Отбор.Родитель.Установить
(пТабличноеПоле.ТекущийРодитель);
        КонецЕсли;
    КонецЕсли;
    Возврат ПостроительЗапроса;
 
КонецФункции // ЛксПолучитьПостроительЗапросаСпискаТабличногоПоля()