Таблица значений в 1С

Таблица значений — это универсальная коллекция 1С, которая предназначена для хранения данных в табличном виде. Таблица значений хранит ссылки на объект типа СтрокаТаблицыЗначений. Помимо строк у таблицы есть колонки. Таблица значений не может существовать на клиенте.

Создание таблицы значений

Для создания таблицы значений используются конструктор:

//создание таблицы без колонок
ТЗ = Новый ТаблицаЗначений;

В данной таблице не будет ни одной колонки и добавление в нее строк бессмысленно. Для добавления колонок нужно использовать свойство Колонки таблицы значений:

//добавление двух колонок
ТЗ.Колонки.Добавить("Товар");
ТЗ.Колонки.Добавить("Цена");

Теперь в таблицу можно добавить несколько строк:

//строки добавляются методом Добавить
НовСтр = ТЗ.Добавить();
//к колонкам можно обращаться через ее имя
НовСтр.Товар = "Диван";
НовСтр.Цена = 1000;
 
НовСтр.Товар = "Кресло";
НовСтр.Цена = 500;

Типы колонок таблицы значений

В таблицу были добавлены 2 колонки. Тип не был определен и поэтому в эту колонку можно поместить любой тип данных, тип будет определяться в зависимости от типа данных значения в колонке. В примере выше тип колонки Товар — строка, а колонки Цена — число. Если добавить еще одну строку с другим типом, то тип колонки станет составным:

НовСтр.Товар = Истина;
НовСтр.Цена = Ложь;
//теперь каждая колонка составного типа
//Товар - строка и булево
//Цена - число и булево

Тип можно указать при добавлении новой колонки, тогда в нее можно будет помещать значения только данного типа, для всех остальных значений будет выполняться преобразование типа:

ТЗ = Новый ТаблицаЗначений;
//колонка с типом Строка
ТЗ.Колонки.Добавить("Товар", Новый ОписаниеТипов("Строка"));
//колонка с типом Число
ТЗ.Колонки.Добавить("Цена", Новый ОписаниеТипов("Число"));
 
НовСтр = ТЗ.Добавить();
НовСтр.Товар = Истина; //в колонке будет строка "Истина"
НовСтр.Цена = Ложь; //в колонке будет 0

Работа с колонками таблицы значений

Для проверки наличия необходимой колонки в таблице можно выполнить поиск в коллекции колонок. Если такой колонки нет, то метод Найти() вернет Неопределено:

ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Товар", Новый ОписаниеТипов("Строка"));
ТЗ.Колонки.Добавить("Цена", Новый ОписаниеТипов("Число"));
 
НовСтр = ТЗ.Добавить();
 
//проверка что есть колонка Товар
Если ТЗ.Колонки.Найти("Товар") <> Неопределено Тогда
	НовСтр.Товар = "Диван";	
КонецЕсли;
 
//проверка что есть колонка Цена
Если ТЗ.Колонки.Найти("Цена") <> Неопределено Тогда
	НовСтр.Цена = 1000;	
КонецЕсли;

Колонку можно переименовать. При этом, значения в данной колонке сохранятся. Изменить тип колонки нельзя.

//получаем колонку
КолонкаТовар = ТЗ.Колонки.Найти("Товар");
Если КолонкаТовар <> Неопределено Тогда
	//меняем имя колонки
	КолонкаТовар.Имя = "Номенклатура";	
КонецЕсли;

Колонки можно удалять, соответственно будут удалены и все значения в данной колонке:

//удаление колонки Цена
ТЗ.Колонки.Удалить("Цена");
 
//удаление всех колонок
ТЗ.Колонки.Очистить();

Изменение значений в существующих строках

К строкам таблицы значений можно обращаться через оператор индексации [ ]. Индексация строк начинается с нуля, чтобы изменить значение в первой строке нужно использовать индекс 0:

//меняем значение в первой строке в колонке Товар
Стр[0].Товар = "Телевизор";

Перебор строк таблицы

//через цикл Для Каждого
Для Каждого Стр Из ТЗ Цикл
	Сообщить(Стр.Товар);
	//можно менять значения колонок
	Стр.Цена = Стр.Цена * 1.1; 
КонецЦикла;	
 
//через цикл Для
//метод Количество() вернет количество строк таблицы
Для ё = 0 По ТЗ.Количество()-1 Цикл
	Сообщить(ТЗ[0].Товар);
	//можно менять значения колонок
	ТЗ[0].Цена = ТЗ[0].Цена * 1.1;	
КонецЦикла;

Удаление строк

//удаление первой строки
ТЗ.Удалить(0);
 
//параметром можно передать ссылку на строку
НовСтр = ТЗ.Добавить();
ТЗ.Удалить(НовСтр);
 
//удаление всех строк
ТЗ.Очистить();

Иногда нужно удалить несколько строк из таблицы по условию. Например, все строки, где цена меньше 100. На первый взгляд это можно сделать так:

//создаем таблицу
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Товар", Новый ОписаниеТипов("Строка"));
ТЗ.Колонки.Добавить("Цена", Новый ОписаниеТипов("Число"));
 
//добавим 4 строки
НовСтр = ТЗ.Добавить();
НовСтр.Товар = "Диван";
НовСтр.Цена = 1000;
 
НовСтр = ТЗ.Добавить();
НовСтр.Товар = "Ручка";
НовСтр.Цена = 50;
 
НовСтр = ТЗ.Добавить();
НовСтр.Товар = "Линейка";
НовСтр.Цена = 80;
 
НовСтр = ТЗ.Добавить();
НовСтр.Товар = "Кресло";
НовСтр.Цена = 2000;
 
Для Каждого Стр Из ТЗ Цикл
	Если Стр.Цена < 100 Тогда
		ТЗ.Удалить(Стр);
	КонецЕсли;	
КонецЦикла;	
 
Для Каждого Стр Из ТЗ Цикл
	Сообщить(Стр.Товар);
КонецЦикла;
//в таблице остались
//диван
//линейка
//кресло

Однако после удаления линейка осталась в таблице, хотя ее цена равна 80. Почему так произошло? При удалении строки, таблица как бы сжимается. То есть на первой итерации цикла мы получили первую строку с диваном, его цена больше 100, поэтому строка осталась. Получаем вторую строку с ручкой за 50. Так как цена меньше 100, строка была удалена. И после удаления все строки сдвинулись, третья строка переместилась на вторую позицию, четвертая на третью и т.д. На следующей итерации мы получаем третью строку, а там уже кресло за 2000. Линейка была пропущена, цикл даже не проверял ее цену.

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

//создаем таблицу
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Товар", Новый ОписаниеТипов("Строка"));
ТЗ.Колонки.Добавить("Цена", Новый ОписаниеТипов("Число"));
 
//добавим 4 строки
НовСтр = ТЗ.Добавить();
НовСтр.Товар = "Диван";
НовСтр.Цена = 1000;
 
НовСтр = ТЗ.Добавить();
НовСтр.Товар = "Ручка";
НовСтр.Цена = 50;
 
НовСтр = ТЗ.Добавить();
НовСтр.Товар = "Линейка";
НовСтр.Цена = 80;
 
НовСтр = ТЗ.Добавить();
НовСтр.Товар = "Кресло";
НовСтр.Цена = 2000;
 
//получаем индекс максимальной строки
Инд = ТЗ.Количество() - 1;
Пока Инд >= 0 Цикл
	//получаем строку по индексу и проверяем цену
	Если ТЗ[Инд].Цена < 100 Тогда
		//удаляем строку
		ТЗ.Удалить(Инд);
	КонецЕсли;	
	//уменьшаем индекс
	Инд = Инд - 1;
КонецЦикла;		
 
Для Каждого Стр Из ТЗ Цикл
	Сообщить(Стр.Товар);
КонецЦикла;
//в таблице остались
//диван
//кресло

Другой способ — это сначала поместить все строки в массив, а потом обойти массив и удалить эти строки:

//создаем таблицу
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Товар", Новый ОписаниеТипов("Строка"));
ТЗ.Колонки.Добавить("Цена", Новый ОписаниеТипов("Число"));
 
//добавим 4 строки
НовСтр = ТЗ.Добавить();
НовСтр.Товар = "Диван";
НовСтр.Цена = 1000;
 
НовСтр = ТЗ.Добавить();
НовСтр.Товар = "Ручка";
НовСтр.Цена = 50;
 
НовСтр = ТЗ.Добавить();
НовСтр.Товар = "Линейка";
НовСтр.Цена = 80;
 
НовСтр = ТЗ.Добавить();
НовСтр.Товар = "Кресло";
НовСтр.Цена = 2000;
 
//массив для удаляемых строк
Массив = Новый Массив;
Для Каждого Стр Из ТЗ Цикл
	Если Стр.Цена < 100 Тогда
		//добавляем строки, которые будем удалять
		Массив.Добавить(Стр);	
	КонецЕсли;	
КонецЦикла;
 
//обходим массив
Для Каждого Строчка Из Массив Цикл
	//и удаляем строки
	ТЗ.Удалить(Строчка);
КонецЦикла;
 
Для Каждого Стр Из ТЗ Цикл
	Сообщить(Стр.Товар);
КонецЦикла;
//в таблице остались
//диван
//кресло

Групповое изменение значений в таблице

Можно загрузить значения из массива в одну из колонок таблицы значений:

//создаем таблицу
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Товар", Новый ОписаниеТипов("Строка"));
ТЗ.Колонки.Добавить("Цена", Новый ОписаниеТипов("Число"));
 
//добавим 4 строки, но без цены
НовСтр = ТЗ.Добавить();
НовСтр.Товар = "Диван";
 
НовСтр = ТЗ.Добавить();
НовСтр.Товар = "Ручка";
 
НовСтр = ТЗ.Добавить();
НовСтр.Товар = "Линейка";
 
НовСтр = ТЗ.Добавить();
НовСтр.Товар = "Кресло";
 
МассивЦен = Новый Массив;
МассивЦен.Добавить(1000);
МассивЦен.Добавить(50);
МассивЦен.Добавить(80);
МассивЦен.Добавить(2000);
ТЗ.ЗагрузитьКолонку(МассивЦен, "Цена");
 
//Диван = 1000
//Ручка = 50
//Линейка = 80
//Кресло = 2000

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

МассивТоваров = ТЗ.ВыгрузитьКолонку("Товар");

Можно заполнить какую-то колонку во всех строках одним значением:

ТЗ.ЗаполнитьЗначения(300, "Цена");
//цена во всех строках будет = 300

Сортировка таблицы значений

//по возрастанию цены
ТЗ.Сортировать("Цена");
 
//по убыванию цены
ТЗ.Сортировать("Цена Убыв");
 
//сначала по возрастанию цены, потом по возрастанию наименованию товара
ТЗ.Сортировать("Цена, Товар");

Итоги по таблице

Итоги можно получить по числовым колонкам таблицы. Для этого можно использовать методы Итог и Свернуть:

//создаем таблицу
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Товар", Новый ОписаниеТипов("Строка"));
ТЗ.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число"));
 
//добавим 2 строки
НовСтр = ТЗ.Добавить();
НовСтр.Товар = "Диван";
НовСтр.Сумма = "1000";
 
НовСтр = ТЗ.Добавить();
НовСтр.Товар = "Диван";
НовСтр.Сумма = "2000";
 
//Метод Итог вернет сумму по колонке
Сумма = ТЗ.Итог("Сумма"); //3000
 
//Метод свернуть свернет таблицу
//первым параметром указывается список колонок группировки
//вторым список колонок суммирования
ТЗ.Свернуть("Товар", "Сумма");
//в таблице будет одна строка
//Товар = Диван
//Сумма = 3000
 
//если какая-то колонка не указана, то она будет удалена
//из результирующей таблицы
ТЗ.Свернуть("Товар");
//в таблице будет только одна колонка Товар
//с одной строка Диван

Копирование таблицы значений

Для создания полной копии таблицы можно использовать метод Скопировать. Для создания новой пустой таблицы с такими же колонками — метод СкопироватьКолонки:

//создаем таблицу
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Товар", Новый ОписаниеТипов("Строка"));
ТЗ.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число"));
 
//добавим 2 строки
НовСтр = ТЗ.Добавить();
НовСтр.Товар = "Диван";
НовСтр.Сумма = "1000";
 
НовСтр = ТЗ.Добавить();
НовСтр.Товар = "Диван";
НовСтр.Сумма = "2000";
 
//в Копия1 будет полная копия ТЗ
Копия1 = ТЗ.Скопировать();
 
//копирование только колонки Товар
Копия2 = ТЗ.Скопировать(, "Товар");
 
//копирование определенных строк
Отбор = Новый Структура("Сумма", 2000);
//в Копия3 будет только одна строка, где Сумма = 2000
Копия3 = ТЗ.Скопировать(Отбор);
 
//пустая копия таблицы с такими же колонками
НоваяТЗ = ТЗ.СкопироватьКолонки();
 
//можно указать список колонок для новой таблицы
НоваяТЗ = ТЗ.СкопироватьКолонки("Товар");

Поиск в таблице значений

Для поиска в таблице значений используются 2 метода: Найти и НайтиСтроки. Метод Найти вернет первую строку с найденным значением, то есть если в таблице 2 строки с таким значением, то будет найдена только первая из них. Метод НайтиСтроки возвращает массив найденных строк и может использоваться для поиска неуникальных значений:

//создаем таблицу
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Товар", Новый ОписаниеТипов("Строка"));
ТЗ.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число"));
 
//добавим 3 строки
НовСтр = ТЗ.Добавить();
НовСтр.Товар = "Диван";
НовСтр.Сумма = "1000";
 
НовСтр = ТЗ.Добавить();
НовСтр.Товар = "Диван";
НовСтр.Сумма = "2000";
 
НовСтр = ТЗ.Добавить();
НовСтр.Товар = "Кресло";
НовСтр.Сумма = "1500";
 
//1 параметр - что ищем
//2 параметр - список колонок для поиска
НайдСтр = ТЗ.Найти("Кресло", "Товар");
//в НайдСтр будет 3 строка с креслом за 1500
 
НайдСтр = ТЗ.Найти("Диван", "Товар");
//в НайдСтр будет 1 строка с диваном за 1000
 
НайдСтр = ТЗ.Найти("Комод", "Товар");
//НайдСтр = Неопределено, ничего не найдено
 
//ключ структуры - имя колонки
//значение структуры - значение для поиска
Отбор = Новый Структура("Товар", "Диван");
НС = ТЗ.НайтиСтроки(Отбор);
//в НС будет массив с двумя первыми строками
 
//можно искать сразу по нескольким колонкам
Отбор = Новый Структура;
Отбор.Вставить("Товар", "Диван");
Отбор.Вставить("Сумма", 2000);
НС = ТЗ.НайтиСтроки(Отбор);
//в НС будет массив с одной строкой, Даван за 2000
 
Отбор = Новый Структура;
Отбор.Вставить("Товар", "Комод");
НС = ТЗ.НайтиСтроки(Отбор);
//в НС будет пустой массив, ничего не найдено

Индексы таблицы значений

Если в таблице значений миллион строк, то поиск методами Найти и НайтиСтроки может выполняться очень долго. Для ускорения поиска можно использовать индексы. Индексы должны быть созданы по тем колонкам, по которым будет выполняться поиск. Если поиск выполняется сразу по нескольким колонкам, то должен быть создан составной индекс.

//добавление индексов
ТЗ.Индексы.Добавить("Товар");
ТЗ.Индексы.Добавить("Сумма");
//будут созданы 2 индекса
//при поиске по колонке Товар или по колонке Сумма
//будет использоваться индекс
//если выполнить поиск сразу по двум колонкам
//методом НайтиСтроки, то индекс не будет использоваться
//Для этого нужен составной индекс
ТЗ.Индексы.Добавить("Товар, Сумма");

Рейтинг
( Пока оценок нет )
Понравилась статья? Поделиться с друзьями: