Таблица значений. Основные приемы работы.
рубрики: Язык программирования 1С | Дата: 13 июля, 2017 Скачать обработку с примерами из статьи: ValueTable.epfПлатформа: 8.3; Тип формы: управляемая.
В процессе разработки и отладки кода 1С очень часто используется такой объект как Таблица значений. Визуально его можно представить как обычную двумерную таблицу. Поэтому он очень легок для человеческого восприятия. А свойства и методы этого объекта позволяют работать как с его строками, так и с колонками. В этой статье рассмотрим как можно создавать таблицу значений средствами языка программирования 1С, а также наиболее часто встречающиеся приемы работы с ней.
В качестве примера давайте создадим простейшую таблицу значений в которой будет отображаться приход товара на склад.
Дата Наименование товара Количество 01.07.2017 Ручка 10 02.07.2017 Карандаш 7 03.07.2017 Карандаш 8 04.07.2017 Лампа 2
А потом рассмотрим различные приемы работы с ней.
Ограничение использования
Если открыть синтакс-помощник и посмотреть где доступна таблица значений, то мы увидим, что она недоступна на тонком клиенте. Соответственно при использовании управляемых форм мы сможем работать с ней только на сервере, т.е. в процедурах и функциях перед которыми установлена директива компиляции &НаСервере.
И конечно же мы не сможем вернуть таблицу значений из серверной функции в клиентскую.
Создание таблицы значений
Для программного создания таблицы значений нам необходимо с помощью конструктора создать сам объект, потом создать необходимые колонки, и наконец заполнить ее строками. Вот код функции которая создаст и вернет нам таблицу, которая приведена выше:
Обход строк таблицы значений
Очень часто при работе с таблицами значений возникает задача обхода всех ее строк. Делается это с помощью циклов. Причем можно это делать как с использованием коллекции строк таблицы значений, когда мы последовательно получаем строки таблицы значений из коллекции строк, так и с использованием счетчика, когда мы получаем строку таблицы по ее индексу. Как правило используется первый способ — с обходом коллекции строк:
Второй способ применяется гораздо реже, как правило когда первый не подходит по каким то причинам. Пример рассмотрим позднее, когда будем говорить про удаление строк из таблицы значений.
Поиск значения
Метод Найти(ИскомоеЗначение, [СписокКолонок]) возвращает строку таблицы в которой есть поле с нужным нам значением. Если значение не найдено, возвращается Неопределено. Список колонок в которых будет производиться поиск указывать необязательно, в этом случае поиск будет производиться во всех полях таблицы значений. Данный метод как правило используется для проверки наличия в таблице строки с искомым значением. Например, в момент обхода в цикле какой-то коллекции, мы формируем таблицу значений в которой значения некоторого поля не должны повторяться дважды. Тогда мы с помощью метода Найти() проверяем наличие строки с этим значением, и если получили Неопределено, тогда добавляем новую строку, в противном случае не делаем ничего. Применительно к нашему примеру давайте сделаем поиск строки со значением «Карандаш»:
В исходной таблице у нас две строки с товаром «Карандаш», но найдена будет только первая из них. Поэтому данный метод не представляет особой ценности, если нам надо получить все строки с заданным значением. Следует понимать, что найденная строка — это по сути ссылка на строку таблицы значений, и если мы проделаем с ее полями какие-либо манипуляции, то это отразится на исходной таблице. Например если выполнить вот такой код:
то мы обнаружим, что во второй строке нашей исходной таблицы соответствующим образом изменилось количество товара:
Дата Наименование товара Количество 01.07.2017 Ручка 10 02.07.2017 Карандаш 100 03.07.2017 Карандаш 8 04.07.2017 Лампа 2
Поиск нескольких строк по условию
В отличие от предыдущего метода, метод НайтиСтроки(СтруктураПоиска) возвращает не одну, а сразу все строки таблицы значений, которые удовлетворяют условию поиска. Точнее возвращается массив, каждый элемент которого представляет собой ссылку на строку таблицы значений. В качестве параметра метод использует структуру, где ключом является имя колонки, а значением — искомое значение. Удобно использовать, когда нам надо выбрать несколько строк по определенному условию, и проделать с ними какие-то действия. Допустим, нам надо в нашей таблице заменить наименование «Карандаш» на «Карандаш автоматический». В этом случае нам поможет следующий код:
Структура для поиска может быть и более сложной. Например, мы можем добавить еще одно условие по колонке Дата:
Удаление строк из таблицы значений
Очевидно, что мы будем рассматривать удаление строк из таблицы значений по какому-то условию. В противном случае у нас произойдет просто очистка всей таблицы, что не имеет особого смысла. И на первый взгляд эта операция кажется достаточно простой. Первое, что приходит в голову — это перебор в цикле всех строк, проверка на выполнение условия, и если условие выполняется, то удаление текущей строки. Но на самом деле такой способ не всегда отрабатывает корректно. Давайте убедимся в этом на нашем примере. Удалим из таблицы все записи с наименованием «Карандаш»:
Но в итоге мы наблюдаем следующую картину
Дата Наименование товара Количество 01.07.2017 Ручка 10 03.07.2017 Карандаш 8 04.07.2017 Лампа 2
То есть у нас удалилась только одна строка вместо двух. Такое происходит когда строки, удовлетворяющие условию, следуют сразу же одна за другой. В этом случае при удалении первой строки, которая удовлетворяет условию, происходит сдвиг всех следующих за ней строк на одну вверх. Но курсор в выборке уже установлен на следующей строке, поэтому строка следующая за удаленной и занявшая ее место никак не обрабатывается. Что же делать в таком случае? Я обычно использую также обход строк в цикле, но не сверху вниз, а наоборот — снизу вверх. В этом случае сдвиг строк не страшен, т.к. нижние строки уже обработаны. При этом приходится вместо обхода коллекции строк использовать получение строки по индексу в цикле со счетчиком. Вот таким образом:
И наконец попробуем с помощью метода НайтиСтроки() сразу получить все нужные строки, и удалить их поочередно:
И в результате получаем:
Дата Наименование товара Количество 01.07.2017 Ручка 10 04.07.2017 Лампа 2
То есть такой метод тоже работает.
Группировка
Допустим, что нас больше не интересует дата, и мы хотим получить по каждому наименованию общее количество. То есть привести исходную таблицу вот к такому виду:
Наименование товара Количество Ручка 10 Карандаш 15 Лампа 2
В этом случае нам надо сгруппировать строки таблицы. Напомню, что группировка в языке запросов также активно используется. А в таблице значений для этого используется метод Свернуть(КолонкиГруппировок, КолонкиСуммирования). В общем то, чтобы достигнуть результата нам потребуется всего одна строчка кода:
Сериализация таблиц значений
Таблица значений может сериализоваться с помощью объекта СериализаторXDTO. Проще говоря таблицу значений можно записать в формате XML или JSON, что открывает широкие возможности для передачи таблиц значений в качестве параметров при обмене данными. В том числе и через веб-сервисы.Рассмотрим использование обоих форматов.
Сериализация с использованием XMLВ качестве примера выгрузим таблицу значений в строку XML, а потом создадим копию таблицы выполнив загрузку из строки XML:
Сериализация с использованием JSONНачиная с версии платформы 8.3.7.1759 появилась возможность сериализации прикладных типов 1С:Предприятия в JSON. Принцип использования тот же, что и для XML:
Хочу обратить внимание на параметр НазначениеТипаXML.Явное в методе ЗаписатьJSON без кот орого при чтении из строки будет выдаваться ошибка, либо надо будет при чтении указать тип объекта.