Глава 5. Коллекции значений
Коллекция представляет собой не хранящуюся в базе данных совокупность значений или объектов — элементов коллекции. В 1С:Предприятии 8.0 работа с коллекциями была унифицирована: добавление, удаление и обход элементов всех коллекций производится однотипным образом.
Некоторые коллекции называются универсальными, потому что разработчик может их создавать средствами встроенного языка для решения своих задач.
> К универсальным коллекциям значений относятся следующие:
• массив,
• список значений,
• таблица значений,
• дерево значений,
• структура,
• соответствие.
Общее у этих объектов то, что они содержат несколько значений (элементов коллекции), позволяют добавлять и удалять значения. Они не хранятся в базе данных, а используются для работы с временными наборами данных для вспомогательной обработки, группировки и анализа информации.
Все эти объекты создаются средствами встроенного языка с помощью ключевого слова Новый. Массив, структура и соответствие имеют конструкторы с параметрами, которые определяют начальное состояние объекта, например, количество элементов в массиве.
Для универсальных коллекций значений доступен обход элементов с помощью конструкции «Для Каждого». Также возможно обращение к элементу с помощью оператора [...] (квадратные
Разработка в системе 1С:Предприятие 8.0
скобки), куда в качестве аргумента обычно передается индекс элемента, а для структуры или соответствия — ключ элемента коллекции.
Внимание! Индексация элементов коллекций всегда начинается с 0.
В системе 1С:Предприятие 8.0 есть и другие коллекции, которые являются свойствами объектов. Такие коллекции называются специализированными или коллекциями-свойствами. Их нельзя создать с помощью ключевого слова Новый, а можно только использовать.
Например, свойство Колонки элемента управления Табличное-Поле представляет собой коллекцию колонок. Разработчик может средствами встроенного языка добавлять или удалять колонки, менять их порядок, изменять заголовок и т.д.
Если коллекция-свойство является фиксированной, то не допускается редактировать список ее элементов.
Ниже будут рассмотрены только универсальные коллекции значений.
Массив
Массивы представляют собой пронумерованную совокупность значений любого типа. К элементу массива можно обращаться по индексу через оператор [...], причем индекс первого элемента равен 0. В качестве значений элементов массива могут быть другие массивы, что, в частности, позволяет организовывать многомерные массивы.
Продемонстрируем на примерах возможности работы с массивами:
Создание нового массива производится следующим образом:
Мае = Новый Массив; //одномерный массив без элементов
Мас2 = Новый Массив(10); //одномерный массив из 10 элементов
МасЗ = Новый Массив(4,5); //массив с двумя измерениями
При указании нескольких параметров конструктора фактически создается массив, элементами которого являются другие массивы, что является аналогом многомерного массива.
Для добавления и удаления элементов массива можно использовать методы объекта Массив:
Мае = Новый Массив; //одномерный массив без элементов Мае.Добавить("Иванов"); //элемент будет иметь индекс О Мае.Добавить("Петров"); //индекс 1 Мае.Добавить("Сидоров"); //индекс 2
//после вставки нового элемента Иванов и Петров будут сдвинуты ниже Мас2.Вставить(0,"Сидоров");
//удаляем Сидорова (Иванов и Петров сдвигаются обратно) Мае2.Удалить(0);
Мас2 = Новый Массив(4,5); //массив с двумя измерениями Мас2[0][0] = "Иванов";
Мас2[0][1] = "Петров";
//после вставки нового элемента Иванов и Петров будут сдвинуты ниже Мас2[0].Вставить(0,"Сидоров");
//следующий элемент будет относиться ко 2-му измерению //и будет являться 6-м (индекс = 5)
//при создании массива во 2-м измерении
//было создано 5 элементов, имеющих значение Неопределено Мас2[1].Добавить{"Петров");
Разработка в системе 1С:Предприятие 8.0
Перебор элементов массива возможен с использованием оператора [...] или цикла «Для Каждого»:
//1-й вариант
Для Каждого эл Из Мае Цикл Сообщить(эл);
КонецЦикла;
//2-й вариант
Для н = 0 По Мае. ВГраница () Цикл Сообщить(Мае[н]);
КонецЦикла;
У объекта Массив есть следующие методы:
ВГраница
Возвращает наибольший индекс в массиве, равный количество элементов минус 1. Если количество элементов массива равно 0, возвращается -1 (минус единица).
Количество
Возвращает количество элементов массива.
Добавить
Добавляет элемент в конец массива.
Вставить
Вставляет значение в массив по указанному индексу.
Удалить
Удаляет значение из массива по указанному индексу.
I Очистить
Удаляет все значения из массива.
В 1С:Предприятии 8.0 в массив можно загружать данные или выгружать данные из него в другие коллекции значений. Это реализуется с помощью соответствующих методов других коллекций значений. Например, объект СписокЗначений имеет методы ВыгрузитьЗначения и ЗагрузитьЗначения, которые работают с массивом. Аналогично действуют методы ВыгрузитьКолонку и ЗагрузитьКолонку объекта ТаблицаЗначений.
Структура и соответствие
Структура и соответствие являются динамическими наборами данных — коллекциями значений. Каждый элемент такой коллекции представляет собой пару «ключ» и «значение». Ключи структуры и соответствия уникальны, поэтому они однозначно идентифицируют элемент коллекции.
Внимание! В структуре ключи могут быть только строковые и должны подчиняться правилам именования переменных. В соответствиях ключи могут быть почти любого типа.
Структуры часто применяются в методах объектов для указания отборов, например:
= Новый Структура("Цена", 100);
ВыйрЩка = Справочники.Номенклатура . Выбрать (,Отбор) ;
Структуры можно использовать для передачи списка параметров (в версии 7.7 для этой цели часто применялся список значений и его методы Установить и Получить):
Параметры = Новый Структура(”ДатаНач,ДатаКон”);
Параметры.ДатаНач = ВыбДата;
Параметры.ДатаКон = ДобавитьМесяц(ВыбДата,1);
Если ВыбТипОтчета о 0 Тогда
Параметры.Вставить(”ТипОтчета”,ВыбТипОтчета);
КонецЕсли;
глСформироватьОбороты(Параметры);
Можно перебрать элементы структуры или соответствия с помощью конструкции «Для Каждого». Каждый элемент коллекции является объектом специального типа КлючИЗначение:
Для Каждого парам Из Параметры Цикл ИмяПараметра = парам.Ключ;
Значение - парам.Значение;
КонецЦикла;
Для структуры можно обращаться к элементам коллекции через точку, поскольку ключи являются свойствами структуры:
НачДата = парам.ДатаНач; КонДата = парам.ДатаКон;
Разработка в системе 1 С:Предприятие 8.0
Для соответствия такое обращение через точку невозможно, так как ключи соответствия могут быть самого разнообразного типа.
С помощью метода Свойство можно получить значение заданного ключа или убедиться, что его в структуре нет, например:
Найдено = парам.Свойство(
мТипОтчета
м/ВыбТипОтчета);
Если Найдено Тогда
СформироватьПользовательскийОтчет(ВыбТипОтчета);
Иначе
СформироватьОтчетПоУмолчанию();
КонецЕсли;
У соответствия нет метода Свойство и обращение производится с помощью оператора [...] или метода Получить:
ТоварАналог = соотвАналоги[Товар].Значение;
Список значений
Список значений — это аналог одномерного массива, который предназначен в основном для решения интерфейсных задач, например, при использовании элементов управления СписокВыбора и ПолеВыбора.
В списке значения могут храниться значения разных типов, хотя можно наложить ограничение с помощью свойства ТипЗначения. Список значений создается в памяти и не сохраняется в базе данных, т.е. это временный набор данных.
Список значений можно представить себе как таблицу, содержащую следующие колонки:
• Значение — собственно хранимое значение.
• Представление — пользовательское представление значения, которое будет показано при выводе значения на экран, например, в диалоге выбора значения из списка. Если представление не указано, то оно формируется системой автоматически.
• Пометка - пометка (флажок), связанная со значением. Может быть использована для отметки некоторых значений из списка.
• Картинка — графическое изображение, связанное с данным значением.
В 1 С:Предприятии 8.0 объект СписокЗначений состоит из объектов типа ЭлементСпискаЗначений, которые имеют свойства Значение, Представление, Пометка и Картинка.
Создание новых списков значений производится с помощью ключевого слова Новый:
сзСотр = Новый СписокЗначений;
Ниже демонстрируются приемы добавления и удаления элементов списка значений:
«Сотр. Очистить О; //удалим все элементы
//У следующего элемента индекс 0, представление "Иванов Иван” сзСо!р.Добавить("Иванов","Иванов Иван");
//У следующего элемента будет индекс 1, представление "Петров Петр"
//и установлена пометка
Разработка в системе 1 С: Предприятие 8.0 сзСотр.Добавить("Петров","Петров Петр”, Истина);
сзСотр.Удалить(І); //удалить 2-й элемент, т.е. Петрова сзСотр.Вставить(0,"Сидоров"); //Иванов сдвигается ниже сзСотр.Сдвинуть(1,-1); //сдвинем Иванова обратно к началу
Обращение к элементу списка значений производится по индексу через оператор [...] или с помощью метода Получить, например:
сзСотр[0].Значение = "Кузнецов";
Перебор элементов списка значений производится следующим образом:
//1-й вариант
Для Каждого эл Из сзСотр Цикл Сообщить(Эл.Значение);
КонецЦикла;
//2-й вариант
Для н = 0 По сзСотр.Количество()-1 Цикл Сообщить(сзСотр[н].Значение);
КонецЦикла;
В списке значений можно искать заданное значение:
НайденныйЭлементСписка = сзСотр.НайтиПоЗначению("Иванов");
Если НайденныйЭлементСписка о Неопределено Тогда Сообщить("Элемент найден!");
КонецЕсли;
Как уже говорилось выше, в списке значений могут быть пометки, которые представляют собой флажки (значения типа «булево»). С помощью пометок несколько значений списка могут быть выделены, и тем самым они будут отличаться от остальных. Назначение пометок определяется проектной логикой.
Разработчик может программно считывать и устанавливать пометки у элементов списка значений:
сзСотр = Новый СписокЗначений;
сзСотр.Добавить("Иванов",.Истина); //пометка установлена сзСотр.Добавить("Петров"); //пометка не установлена сзСотр.Добавить("Сидоров"); //пометка не установлена
ВыборПроизведен = сзСотр.ОтметитьЭлементы("Укажите сотрудников");
Если ВыборПроизведен Тогда
Для Каждого эл Из сзСотр Цикл Если эл.Пометка Тогда
Сообщить("Отмечен сотрудник " + эл.Значение);
КонецЕсли;
КонецЦикла;
КонецЕсли;
Методы ВыбратьЭлемент и ОтметитьЭлементы открывают диалоговое окно для пользователя, в котором он может выбрать один элемент или расставить пометки, тем самым выбрав несколько элементов.
Элементы списка значений могут быть легко отсортированы по значению или по представлению:
сзСотр.СортироватьПоЗначению(НаправлениеСортировки.Возр); сзСотр.СортироватьПоПредставлению(НаправлениеСортировки.Убыв);
В список значений можно загрузить значения из массива и выгрузить значения в массив, например:
мае = Новый Массив; мае.Добавить("Иванов"); мае.Добавить(’’Якушин") ; мае.Добавить("Сидоров"};
сзСотр.ЗагрузитьЗначения(мае); сзСотр.СортироватьПоЗначению(); мас2 = сзСотр.ВыгрузитьЗначения();
При размещении в форме поля списка автоматически создается новый реквизит формы типа СписокЗначений. Через этот реквизит можно управлять содержимым списка, добавлять или удалять элементы, расставлять пометки, задавать картинки. Следует понимать, что ПолеСписка — это не список значений, а элемент управления, имеющий собственный набор свойств и методов.
Со списком значений также тесно связан элемент управления ПолеВыбора. Его свойство СписокВыбора представляет собой список значений, из которого пользователь может выбрать одно значение.
Разработка в системе 1 С: Предприятие 8.0
Таблицазначений
Таблица значений — это не сохраняемый в базе данных объект, предназначенный для создания динамических наборов данных. Таблица значений состоит из строк и колонок. В отличие от списка значений, таблица значений имеет структуру, которую определяет разработчик.
Объект ТаблицаЗначений имеет много полезных методов для обработки данных. Разработчик средствами встроенного языка может добавлять и удалять строки и колонки, перебирать строки, искать значение, сортировать по любым колонкам и выполнять другие операции.
При создании новой таблицы значений в нее обычно добавляются колонки:
тзТовары = Новый ТаблицаЗначений; тзТовары.Колонки.Добавить("Ссылка"); тзТовары.Колонки.Добавить("Наименование"); тзТовары.Колонки.Добавить("Цена"); тзТовары.Колонки.Добавить("Количество");
У таблицы значений есть свойство Колонки, которое представляет собой коллекцию колонок и позволяет добавлять, удалять и менять их порядок.
По умолчанию в таблице значений могут храниться значения разных типов. Но в 1 С:Предприятии 8.0 для колонки можно задать список возможных типов значений. Это делается следующим образом (для повышения наглядности нам понадобится вспомогательная функция СоздатьОписаниеТипов):
Функция СоздатьОписаниеТипов(НазваниеТипа,Длина,Точность="") мае = Новый Массив; мае.Добавить(Тип(НазваниеТипа));
Если Точность = "" Тогда
КваяифСтроки = Новый КвалификаторыСтроки(Длина,
ДопустимаяДлина.переменная)•
Иначе
КвалифЧисла = Новый КвалификаторыЧисла(ДопустимыйЗнак.Любой,
Длина,Точность);
КонецЕсли;
Возврат Новый ОписаниеТипов(мае, квалифСтроки, КвалифЧисла); КонецФункции
тзТовары = Новый ТаблицаЗначений;
ТипКолСсылка = СоздатьОписаниеТипов("СправочникСписок.Номенклатура"); тзТовары.Колонки.Добавить ("Ссылка", ТипКолСсылка, "Товар" ,5);
ТипКолНаим = СоздатьОписаниеТипов("Строка",50); тзТовары.Колонки.Добавить("Наименование", ТипКолНаим);
ТипКолЦена = СоздатьОписаниеТипов("Строка",15,2); тзТовары.Колонки.Добавить("Цена", ТипКолЦена, "Цена",15);
ТипКолКолич = СоздатьОписаниеТипов("Строка",15,4); тзТовары.Колонки.Добавить("Количество",ТипКолКолич,"Кол-во",15);
При работе со строками таблицы значений необходимо понимать, что строка — это объект типа СтрокаТаблицыЗначений. Поэтому добавление строк в таблицу значений производится следующим образом:
//удаляем все строки из таблицы (колонки остаются) тзТовары.Очистить ();
СпрВыборка = Справочники.Номенклатура.Выбрать();
Пока СпрВыборка.Следующий() Цикл
НовСтрока = тзТовары.Добавить();
НовСтрока.Ссылка = СпрВыборка.Ссылка;
НовСтрока.Наименование = СпрВыборка.Наименование;
НовСтрока.Цена = СпрВыборка.Цена;
КонецЦикла
Чтобы удалить колонки из таблицы значений нужно применить метод Очистить для свойства-коллекции Колонки:
тзТовары.Колонки.Очистить();
По индексу можно удалить строку:
тзТовары.Удалить(0); //удалить 1-ю строку с индексом О тзТовары.Удалить(1); //удалить 2-ю строку с индексом 1
Перебор строк таблицы значений обычно реализуется с помощью конструкции «Для Каждого», при этом в переменной цикла будет содержаться не номер строки, а вся строка целиком как объект СтрокаТаблицыЗначений:
Для Каждого стр Из тзТовары Цикл Сообщить(стр.Наименование);
Сообщить(стр.Цена);
КонецЦикла;
Допускается также обращение к строке по индексу, при этом также возвращается объект типа СтрокаТаблицыЗначений. При работе с индексами необходимо всегда помнить, что индексация строк таблицы значений начинается с 0.
Для н=0 По тзТовары.Количество()-1 Цикл Сообщить(тзТоаары[н].Наименование);
Сообщить(тзТовары[н].Цена) ;
КонецЦикла;
Часто возникает необходимость найти значение в таблице значений. Для решения этой задачи предназначены методы Найти и НайтиСтроки. В метод Найти передается искомое значение и список колонок, которые нужно просматривать. Если значение найдено, то возвращается строка таблицы значений, иначе — значение Неопределено.
НайденнаяСтрока = тзТовары.Найти (100 , "Цена") ;
Если НайденнаяСтрока о Неопределено Тогда
Сообщить("Товар с такой ценой найден! " +
НайденнаяСтрока.Наименование);
КонецЕсли;
Метод НайтиСтроки позволяет найти сразу несколько строк таблицы значений, удовлетворяющих заданному условию. В параметрах этого метода передается структура, задающая условия отбора. Ключ структуры определяет имя колонки, а ее значение — искомое значение. Метод НайтиСтроки возвращает массив, содержащий ссылки на найденные строки таблицы значений:
Отбор = Новый Структура !"Цена"Д0 0);
МассивСтрок = тзТовары.НайтиСтроки(Отбор);
Сообщить("Найдено " + МассивСтрок.Количество() +
" товаров с такой ценой");
Внимание! Массив, возвращаемый методом НайтиСтроки, содержит строки таблицы значений (не их копии, а сами строки). При изменении какой-либо строки в таблице значений это отразится в массиве, и наоборот.
Таблица значений позволяет упорядочить содержащиеся в ней данные, для чего предназначен метод Сортировать:
тзТовары.Сортировать("Наименование Возр"); тзТовары.Сортировать("Цена Убыв");
тзТовары.Сортировать("Цена Убыв, Наименование Возр");
Таблица значений имеет очень полезную возможность группировки строк и подсчета итогов по группе, что реализуется методом Свернуть, имеющим следующие параметры:
Свернуть(<Колонки группировок^, <Колонки суммирования>)
Этот метод осуществляет свертку таблицы значений по указанным колонкам группировки. Строки, у которых совпадают значения в колонках, указанных в первом параметре, сворачиваются в одну строку. Значения по этим строкам, хранящиеся в колонках, указанных во втором параметре, суммируются.
Внимание! Списки колонок для метода Свернуть не должны пересекаться. Колонки, не вошедшие ни в один из списков колонок, после выполнения метода удаляются из таблицы значений.
|
Например, у нас есть таблица значений со следующими данными: |
|
Сотрудник |
Год |
Месяц |
Доход |
|
Иванов |
2003 |
Январь |
15000 |
|
Иванов |
2003 |
Февраль |
14000 |
|
Петров |
2003 |
Январь |
15000 |
|
Петров |
2003 |
Февраль |
12000 |
|
В следующем примере эта таблица сворачивается по колонкам Сотрудник и Год с подсчетом суммы по колонке Доход:
//подсчитаем годовой доход по каждому сотруднику тзДоходыСотр.Свернуть("Сотрудник,Год","Доход");
Разработка в системе 1С:Предприятие 8.0
В результате мы получим следующую таблицу значений:
|
Сотрудник |
Год |
Доход |
|
Иванов |
2003 |
29000 |
|
Петров |
2003 |
27000 |
Если исходная таблица значений вам понадобится в дальнейшем, то лучше сделать копию таблицы значений и сворачивать уже ее:
"МаДоходыПоГодам = тзДоходыСотр.Скопировать(); -МЦоходыПоГодам.Свернуть("Сотрудник,Год","Доход");
Таблица значений позволяет подсчитать итог по колонке числового типа, например:
ВсегоДоход = тзДоходыСотр.Итог("Доход");
ВсегоНДС = тзСостав.Итог("НДС");
И последнее, о чем хотелось рассказать, из таблицы значений можно выгрузить целую колонку в массив и загрузить ее из массива:
МИ1сивЦен = тзТовары. ВыгрузитьКолонку ("Цена") ;
*Щ|овары.ЗагрузитьКолонку("Количество",МассивОстаткиТоваров);
Дерево значений
Дерево значений — это объект для хранения временных наборов данных, возникающих при работе программы.
Работа с деревом значений напоминает работу с таблицей значений, за исключением того, что в дереве могут быть представлены иерархические данные (по аналогии с иерархическим справочником). Это достигается тем, что каждая строка дерева значений может иметь подчиненные строки, а те, в свою очередь, тоже могут иметь подчиненные строки и т.д.
Дерево значений предоставляет возможность обхода строк и подсчета итогов по всем строкам дерева или по текущему уровню иерархии.
Объект ДеревоЗначений имеет свойство Строки и Колонки, через которые осуществляется доступ к коллекции строк 1-го уровня и колонок дерева значений. У каждой строки дерева значения (т.е. объекта СтрокаДереваЗначений) есть свойство Строки, содержащее коллекцию подчиненных строк для данной строки дерева значений.
Следующий пример создает дерево значений и наполняет его данными:
дзОтделы = Новый ДеревоЗначений; дзОтделы.Колонки.Добавить("Отдел"); дзОтделы.Колонки.Добавить("Руководитель");
Нов = дзОтделы.Строки.Добавить(); //индекс О Нов.Отдел = "Бухгалтерия";
Нов = дзОтделы.Строки.Добавить(); //индекс 1 Нов.Отдел = "Руководство";
//детализируем отдел "Бухгалтерия"
Нов = дзОтделы.Строки[0] .Строки.Добавить (); Нов.Отдел = "Расчет зарплаты";
Нов = дзОтделы.Строки[0].Строки.Добавить(); Нов.Отдел = "Основные средства";
//детализируем руководство
Нов = дзОтделы.Строки[1] .Строки.Добавить (); Нов.Отдел = "Высшее руководство";
Нов = дзОтделы.Строки[1].Строки.Добавить(); Нов.Отдел = "Отдел маркетинга";
Так же, как и с таблицей значений, можно создать полную копию дерева значений с помощью метода Скопировать:
НОваяОргСтруктура = ДзОтделы.Скопировать();
Обход строк реализуется с помощью конструкции «Для Каждого» или оператором [...]:
//1-й вариант: обход строк 1-го уровня Для Каждого стр Из дзОтделы Цикл Сообщить(стр.Отдел);
КснецЦикла;
//2-й вариант (индексация строк начинается с 0)
Для н = 0 По дзОтделы.Строки.Количество()-1 Цикл стр = дзОтделы.Строки[н];
Сообщить(стр);
КснецЦикла;
Следующая программа с помощью рекурсивной процедуры обходит все строки дерева значений, включая подчиненные:
Процедура ПоказатьПодчиневные (СтрокаДерева,Уровень=0)
Для Каждого стр Из СтрокаДерева.Строки Цикл отступ = "";
Для н = ] По Уровень Цикл
отступ = отступ + " ";
КонецЦикла;
Сообщить(отступ + стр.Отдел);
ПоказатьПодчиненные(стр,Уровень+1);
КонецЦикла;
КонецПроцедуры
ПоказатьПодчиненные(дзОтделы);
Результат работы программы:
Бухгалтерия
Расчет зарплаты Основные средства Руководство
Выслше руководство Отдел маркетинга
Аналогично таблице значений, дерево значений позволяет искать значение с помощью метода Найти или искать сразу несколько строк методом НайтиСтроки. Принципы работы этих методов полностью идентичны рассмотренным выше для таблицы значений, за исключением последнего параметра БключатьПодчинен-ные. Если передать в него значение Истина, то поиск будет производиться в том числе и по подчиненным строкам, иначе — только по строкам текущего уровня.
Важные отличия от версии 7.7
• У массивов может быть несколько измерений, что позволяет организовывать многомерные массивы.
• Можно добавлять и удалять элементы массива, при этом его размерность будет динамически меняться.
• Введен новый объект ДеревоЗначений. Строки дерева значений могут иметь подчиненные строки, что дает возможность хранить в памяти иерархически организованные данные.
• Введены новые объекты Структура и Соответствие. Ключи соответствия могут быть любого типа.
• Обход элементов коллекции возможен через конструкцию «Для Каждого». К элементам коллекции можно также обращаться через оператор [...] (квадратные скобки). Индексация элементов коллекции начинается с 0.
• Изменилась объектная модель при работе с коллекциями значений. Каждое значение из списка значений — это объект типа ЭлементСпискаЗначений, каждая строка таблицы значений — это объект СтрокаТаблицыЗначений, а для дерева значений — СтрокаДереваЗначений. Для структуры и соответствия каждый элемент коллекции — это объект типа КлючИЗначение.
• Для списка значений, колонки таблицы или дерева значений можно указать список допустимых типов с помощью свойства ТипЗначения.
• У таблицы значений и дерева значений есть метод НайтиСтроки, возвращающий массив строк, удовлетворяющих заданному условию.
• Список значений может иметь картинки к значениям.
Разработка в системе 1С Предприятие 8.0