Примеры программирования с таблицей значений в системе 1С:Предприятие 8

Доброго времени суток, уважаемые читатели! На этом сайте уже были описаны примеры работы с таблицей значений. Например, было написано как объединить две таблицы значений. Сегодня я поделюсь ещё некоторыми примерами программирования с таблицей значений в системе 1С:Предприятие 8.

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

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

ТаблицаЗначений = Новый ТаблицаЗначений;
// Создаём нужные колонки. 
ТаблицаЗначений.Колонки.Добавить("НомерСтроки");
ТаблицаЗначений.Колонки.Добавить("Субконто");
// Строка № 1. 
НоваяСтрока = ТаблицаЗначений.Добавить();
НоваяСтрока.НомерСтроки = "1";
НоваяСтрока.Субконто = Справочники.Номенклатура.НайтиПоКоду("1");
// Строка № 2.
НоваяСтрока = ТаблицаЗначений.Добавить();
НоваяСтрока["НомерСтроки"] = 2;
НоваяСтрока["Субконто"] = Справочники.ОсновныеСредства.НайтиПоКоду("1");
// Строка № 3.
НоваяСтрока = ТаблицаЗначений.Добавить();
НоваяСтрока["НомерСтроки"] = 3;
НоваяСтрока["Субконто"] = Справочники.ОсновныеСредства.НайтиПоКоду("2");
МассивСтрок = Новый Массив;
// Добавим в массив только те строки, в которых типом значения 
// колонки «Субконто» является тип «СправочникСсылка.ОсновныеСредства»
Для каждого СтрокаТЗ ИЗ ТаблицаЗначений Цикл
    Если СтрокаТЗ.Субконто.Метаданные().Имя = "ОсновныеСредства" Тогда
        МассивСтрок.Добавить(СтрокаТЗ);
    КонецЕсли;
КонецЦикла;
// Теперь создадим таблицу значению по отбору из массива
ТаблицаОС = ТаблицаЗначений.Скопировать(МассивСтрок, "НомерСтроки,Субконто");
// Выведем результат в окно служебных сообщений
Для каждого СтрокаТЗ ИЗ ТаблицаОС Цикл
Сообщить("НомерСтроки - " + СтрокаТЗ.НомерСтроки + "; Субконто - " + СтрокаТЗ.Субконто);

В результате получим строки из таблицы значений с типом значения «ОсновныеСредства» колонки «Субконто»:

НомерСтроки - 2; Субконто - Насосы К50-32-125
НомерСтроки - 3; Субконто - Насосы К65-50-160

Как в цикле отобрать только одну строку из таблицы значений?

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

СписокНоменклатуры = Новый СписокЗначений; 
Для каждого Строка Из ТаблицаРезультатов Цикл
	// Начало какого-то кода...
	Если СписокНоменклатуры.НайтиПоЗначению(Строка.Номенклатура) = Неопределено Тогда
		// Если нет такой номенклатуры добавим в список значений и
		// продолжим работу дальше...
		СписокНоменклатуры.Добавить(Строка.Номенклатура);
	Иначе
		// Если така номенклатура встречается, то идём на начало цикла
		Продолжить;
	КонецЕсли;
	// Продолжение какого-то кода...
КонецЦикла;

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

Самый простой вариант сделать это — использовать конструкцию «Попытка Исключение», например, попытаться получить значение в строке в указанной колонке и если возникнет исключение, то это значит, что колонки нет. Можно написать следующую функцию:

Функция ПроверитьНаличиеКолонки(СтрокаТаблицы, ИмяКолонки)
	Попытка
		Значение = СтрокаТаблицы[ИмяКолонки];
		// Колонка существует
		Возврат Истина;
	Исключение
	// Колонка отсутствует
		Возврат Ложь;
	КонецПопытки;
КонецФункции

Однако использование конструкции «Попытка Исключение» не является хорошим тоном в программировании на 1С
(это вызывает трудности отладки и крушение внутри транзакций). Поэтому предлагаю другой путь:

НазваниеКолонки = "Субконто";
Если СтрокаТЗ.Владелец().Колонки.Найти(НазваниеКолонки) <> Неопределено Тогда
	Сообщить("Колонка с названием - " + НазваниеКолонки + " - существует!");
Иначе
	Сообщить("Колонка с названием - " + НазваниеКолонки + " - не существует!");
КонецЕсли;

В нашем примере переменная «СтрокаТЗ» является объектом типа «СтрокаТаблицыЗначений», у которого есть метод «Владелец()». Владельцем строки является «ТаблицаЗначений», которая имеет свойство «Колонки» с типом «КоллекцияКолонокТаблицыЗначений». Таким образом мы получаем объект типа «КоллекцияКолонокТаблицыЗначений», который содержит метод «Найти()». С помощью этого метода мы можем найти колонки таблицы значений по имени. Если указанная колонка есть, то возвращается колонка с типом «КолонкаТаблицыЗначений», но если отсутствует, то возвращается значение «Неопределено». Поэтому в нашем случае будет выведено следующее сообщение:

Колонка с названием - Субконто - существует!

Поиск в таблице значений по двум и более полям

Рассмотрим первый способ — через объекты встроенного языка системы 1С:Предприятие:

ТаблицаЗначений = Новый ТаблицаЗначений;
// Обязательно укажем тип колонки, 
// чтобы не было ошибки «Тип не может быть выбран в запросе» 
// при выполнении запроса к таблице значений
КС = Новый КвалификаторыСтроки(100);
КЧ = Новый КвалификаторыЧисла(3);
ОписаниеТиповС = Новый ОписаниеТипов("Строка",, КС);
ОписаниеТиповЧ = Новый ОписаниеТипов("Число",, КЧ);
// Создаём нужные колонки.
ТаблицаЗначений.Колонки.Добавить("Фамилия", ОписаниеТиповС);
ТаблицаЗначений.Колонки.Добавить("Возраст", ОписаниеТиповЧ);

// Сотрудник № 1. 
НоваяСтрока = ТаблицаЗначений.Добавить();
НоваяСтрока.Фамилия = "Иванов";
НоваяСтрока.Возраст = 27;

// Сотрудник № 2.
НоваяСтрока = ТаблицаЗначений.Добавить();
НоваяСтрока["Фамилия"] = "Сидоров";
НоваяСтрока["Возраст"] = 64;

// Осуществляем поиск по таблице через объекты
Отбор = Новый Структура;
Отбор.Вставить("Фамилия", "Иванов");
Отбор.Вставить("Возраст", 27);
Строки = ТаблицаЗначений.НайтиСтроки(Отбор);
// Возвращает массив
Если Строки.Количество() > 0 Тогда
	Сообщить("*** Первый способ - через объекты встроенного языка ***");
	Сообщить("Фамилия: " + Строки[0].Фамилия + " Возраст: " + Строки[0].Возраст);
КонецЕсли;

В результате по первому способу, через объекты встроенного языка, получим:

*** Первый способ - через объекты встроенного языка ***
Фамилия: Иванов Возраст: 27

Рассмотрим второй способ — через пакетные запросы системы 1С:Предприятие. Здесь воспользуемся таблицой значений, которую мы создали ранее, в первом способе:

Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ТаблицаЗначений.Фамилия,
| ТаблицаЗначений.Возраст
|ПОМЕСТИТЬ ВТ_ТаблицаЗначений
|ИЗ
| &ТаблицаЗначений КАК ТаблицаЗначений
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ВТ_ТаблицаЗначений.Фамилия,
| ВТ_ТаблицаЗначений.Возраст
|ИЗ
| ВТ_ТаблицаЗначений КАК ВТ_ТаблицаЗначений
|ГДЕ
| ВТ_ТаблицаЗначений.Фамилия = &Фамилия
| И ВТ_ТаблицаЗначений.Возраст = &Возраст";
Запрос.УстановитьПараметр("ТаблицаЗначений", ТаблицаЗначений);
Запрос.УстановитьПараметр("Фамилия", "Сидоров");
Запрос.УстановитьПараметр("Возраст", 64);

Результат = Запрос.Выполнить().Выгрузить();
// Возвращает таблицу значений
Если Результат.Количество() > 0 Тогда
	Сообщить("*** Второй способ - через запросы ***");
	Сообщить("Фамилия: " + Результат[0].Фамилия +
	" Возраст: " + Результат[0].Возраст);
КонецЕсли;

В результате по второму способу, через запросы, получим:

*** Второй способ - через запросы ***
Фамилия: Сидоров Возраст: 64

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

Почему возникает ошибка «Тип не может быть выбран в запросе» при выполнении запроса к таблице значений?

Если не задать тип значения колонки при её создании как описано в подзаголовке Поиск в таблице значений по двум и более полям, а написать так:

ТаблицаЗначений.Колонки.Добавить("Фамилия");

То тогда при выполнении запроса будет выведена ошибка:

Ошибка при вызове метода контекста (Выполнить)
	Результат = Запрос.Выполнить().Выгрузить();
по причине:
{(2, 2)}: Тип не может быть выбран в запросе
<<?>>ТаблицаЗначений.Фамилия,

Поэтому, чтобы избежать этой ошибки нужно писать так:

КС = Новый КвалификаторыСтроки(100);
ОписаниеТиповС = Новый ОписаниеТипов("Строка",, КС);
ТаблицаЗначений.Колонки.Добавить("Фамилия", ОписаниеТиповС);

Как получить номер строки таблицы значений?

Нужно использовать метод таблицы значений «Индекс» (IndexOf), которая получает индекс строки в коллекции строк таблицы значений:

ИдеиРазвития.Колонки.Вставить(0,"Номер",, "№", 1);
Для Каждого Строка Из ИдеиРазвития Цикл
	Строка.Номер = ИдеиРазвития.Индекс(Строка) + 1;
КонецЦикла;

Как правильно удалить строки из ТаблицыЗначений в 1С8?

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

Процедура УдалитьСтрокиТаблицы(Таб);
	Сч = 0;
	Пока Сч < Таб.Количество() Цикл
		Строка = Таб[Сч];
		Если Найти(Строка.Получить(1),"G") > 0 Тогда
			Таб.Удалить(Строка);
		Иначе // Благодаря этой переменной мы 
		      // не пропускаем строки в таблице значений
			Сч = Сч + 1;
		КонецЕсли;
	КонецЦикла;
КонецПроцедуры

Подобная процедура для правильного удаления строк текстового файла описана здесь.

ПОДПИСКА

9 ответы
  1. Яна говорит:

    Вот! Это то что мне надо! Я давно искала хорошие примеры по таблице значений в 1С 8, но все никак не могла найти доступные, понятные. Везде все так заумно. А тут все так просто, я без проблем сделала нужные мне вещи. Да и вообще в голове хоть какая то ясность появилась!

  2. Артём говорит:

    Таблица значений у меня всегда вызывала большие вопросы, я не понимал, как с ней работать, учебники мне не помогали. Ваши примеры помогли, и я знаю почему. Они написаны русскими словами. так понять смысл намного проще!

  3. Westik говорит:

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

  4. Softmaker говорит:

    Спасибо, Артём! Думаю со временем у вас получиться использовать книги по встроенному языку 1С как справочник.

  5. Марина говорит:

    Таблица значений для меня была дремучим лесом, честное слово. Но теперь я понимаю ее лучше всех в группе. Просто преподаватель не так все объяснял, как у вас в статье намного понятнее.

  6. Softmaker говорит:

    Westik: Очень хорошо, что вы не сдались, а продолжали работать с таблицы значений!

  7. Softmaker говорит:

    Марина, спасибо! Я старался объяснить как можно понятнее, что такое таблица значений в 1С8.

  8. maks говорит:

    Подскажите пожалуйста, есть форма со значениями нужно по значению ИНН в этой форме, заполнить наименование контрагента из справочника в базе 1с. Если возможно поподробнее.

Комментарии закрыты.