Примеры программирования с таблицей значений в системе 1С:Предприятие 8
Доброго времени суток, уважаемые читатели! На этом сайте уже были описаны примеры работы с таблицей значений. Например, было написано как объединить две таблицы значений. Сегодня я поделюсь ещё некоторыми примерами программирования с таблицей значений в системе 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; КонецЕсли; КонецЦикла; КонецПроцедуры
Подобная процедура для правильного удаления строк текстового файла описана здесь.
Вот! Это то что мне надо! Я давно искала хорошие примеры по таблице значений в 1С 8, но все никак не могла найти доступные, понятные. Везде все так заумно. А тут все так просто, я без проблем сделала нужные мне вещи. Да и вообще в голове хоть какая то ясность появилась!
Спасибо, Яна!
Таблица значений у меня всегда вызывала большие вопросы, я не понимал, как с ней работать, учебники мне не помогали. Ваши примеры помогли, и я знаю почему. Они написаны русскими словами. так понять смысл намного проще!
1С:Предприятие 8 только начал изучать, возникли проблемы с выборкой из таблицы значений по типу значения колонки или поля. Честно, пытался больше недели понять в чем дело, ладно, хоть еще не сессия, есть время.. В итоге пошел искать помощь, нашел вас. Ваш пример меня спас. Даже стыдно, что сам не понял этого..
Спасибо, Артём! Думаю со временем у вас получиться использовать книги по встроенному языку 1С как справочник.
Таблица значений для меня была дремучим лесом, честное слово. Но теперь я понимаю ее лучше всех в группе. Просто преподаватель не так все объяснял, как у вас в статье намного понятнее.
Westik: Очень хорошо, что вы не сдались, а продолжали работать с таблицы значений!
Марина, спасибо! Я старался объяснить как можно понятнее, что такое таблица значений в 1С8.
Подскажите пожалуйста, есть форма со значениями нужно по значению ИНН в этой форме, заполнить наименование контрагента из справочника в базе 1с. Если возможно поподробнее.