1с таблица значений удалить дубликаты
Таблица значений часто применяется при программировании на 1С, потому что имеет множество полезных возможностей и работает очень быстро. Таблица значений создается в памяти и не сохраняется в базе данных, т.е. это временный набор данных.
//можно указать тип данных каждой колонки
//если тип данных колонки не указан, то можно хранить данные любого типа
Синтаксис: НоваяКолонка(, , , , , , , )
Добавление строк в таблицу значений
Перебор строк таблицы значений
Сортировка таблицы значений
Поиск в таблице значений
Синтаксис: НайтиЗначение(,,)
Возвращает число: 0 - значение не найдено; 1 - значение найдено
Если указан параметр , то поиск производится только по заданной строке
Если указан параметр , то поиск производится только по заданной колонке
Итоги и группировка таблицы значений
//часто требуется группировать строки и подсчитывать итоги по группам,
//в этом случае применяется метод Свернуть
Удаление строк и колонок из таблицы значений
ВНИМАНИЕ
Часто требуется удалить строки, удовлетворяющие определенному условию.
Так как при удалении строки из таблицы значений следующая строка становится текущей,
то указанная ниже программа может удалить НЕ ВСЕ необходимые строки.
В этом случае я рекомендую использовать следующий прием:
А вот еще один правильный алгоритм, предложенный Wlad:
Замечание(Туц). Предыдущий вариант не совсем правильный. Случай, когда последняя строка попадает под условие и в условии идёт обращение к строке таблицы, приводит к ошибке. Т.е. происходит попытка чтения для строки 0.
И ещё вариант, предложенный Туц:
Замечание (vligm). А я использую такой алгоритм (это, собственно говоря, шаблон):
Таблица значений как элемент диалога
Таблица значений может использоваться в экранных формах как элемент диалога с пользователем.
Методы УстановитьЗначение и ПолучитьЗначение
Эти методы позволяют обращаться к данным в таблице значений для чтения и записи.
Они могут пригодиться в особых случаях при написании универсальных программ (мастеры отчетов и т.д.).
Быстрое удаление дублей строк в таблице значений по списку колонок.
Нужно пару слов про идею и алгоритм написать, а не только текст процедуры. Чем Ваш вариант лучше того, что я сейчас сяду и напишу за 10 минут на коленке?
Алгоритм писателя на 1С 77. Проще всего:
ВЫБРАТЬ * ПОМЕСТИТЬ ВременнаяТаблица ИЗ &Таблица КАК ВременнаяТаблица;
ВЫБРАТЬ РАЗЛИЧНЫЕ * ИЗ ВременнаяТаблица
(6) В данном случае речь шла о таблице значений, которую на клиенте Вы никак не сможете получить. Использование метода "Скопировать" доступно только для универсальных коллекций значений, которые не могут существовать на клиенте. Иными словами сам код обработки предполагает серверный вызов.
(8) CagoBHuK, я и не спорю относительно серверного (сервера 1С) вызова, добавится вызов именно SQL сервера.
(4) CagoBHuK, это при условии что все поля строк одинаковые.
Если, например, в таблице 4 колонки и дубли удалять надо только по 3 колонкам, то вариант стар как мир и даже описан в синтакс-помощнике (осторожно, код в стиле "капитан очевидность"):
Предложу свой вариант, немного улучшенный (12) больше универсальности, про быстродействие так же не могу сказать, тесты не проводил:
Можно использовать и запрос, спорить не буду. Таблицу нужно будет подготовить - описать типы колонок, и также добавить колонку, по которой будет происходить суммирование.
Далее почти по тексту, только нужно будет выбирать не различные, а группировать по нужному списку колонок (строить запрос динимически), и добавить в запрос условие "Имеющие сумма(КолонкаСуммирования) = 1". (просто различные использовать нельзя из-за значений в других колонках таблицы). Далее эту сгруппированную временную таблицу нужно будет джойнить с первоначальной временной таблицей, в условиях связи прописывать равенство по выбранным полям (строить условие динамически), плюс нужно будет в случае если нужно не удалить все дублирующие строки, а оставить по одной из удаляемых тоже это предусмотреть.
Хотел еще сказать, что этот способ расчитан, на большое количество строк в таблице, и малое количество строк с дублями, для других случаев можно это делать быстрее другим способом.
Вариант написанный на коленке возможно будет эффективнее, если предоставится возможность, хотел бы на него посмотреть и возможно использовать с Вашего разрешения.
МассивДублей = Новый Массив;
МассивСотрудников = Новый Массив; // проверяемое на дубль значение
Для каждого Строка Из ТЗНачисления Цикл
Если Строка.СпособРасчета = Перечисления.СпособыРасчетаОплатыТруда.СдельныйЗаработок Тогда // критерий сравнения на дубль, может быть любой
Если Элем = Неопределено Тогда // это первое вхождение проверяемого на дубль сотрудника
Иначе // а это - уже мы дубль встретили, по данному сотруднику и по данному критерию проверки на дубль
Столкнулся с задачей удаления дублей строк в таблице значений, при этом важным критерием для меня является производительность, из-за большых размеров таблиц значений. Написал процедуру, возможно эта процедура кому-нибудь еще будет полезной.
Специальные предложения
Нужно пару слов про идею и алгоритм написать, а не только текст процедуры. Чем Ваш вариант лучше того, что я сейчас сяду и напишу за 10 минут на коленке?
Алгоритм писателя на 1С 77. Проще всего:
ВЫБРАТЬ * ПОМЕСТИТЬ ВременнаяТаблица ИЗ &Таблица КАК ВременнаяТаблица;
ВЫБРАТЬ РАЗЛИЧНЫЕ * ИЗ ВременнаяТаблица
(6) В данном случае речь шла о таблице значений, которую на клиенте Вы никак не сможете получить. Использование метода "Скопировать" доступно только для универсальных коллекций значений, которые не могут существовать на клиенте. Иными словами сам код обработки предполагает серверный вызов.
(8) CagoBHuK, я и не спорю относительно серверного (сервера 1С) вызова, добавится вызов именно SQL сервера.
(4) CagoBHuK, это при условии что все поля строк одинаковые.
Если, например, в таблице 4 колонки и дубли удалять надо только по 3 колонкам, то вариант стар как мир и даже описан в синтакс-помощнике (осторожно, код в стиле "капитан очевидность"):
Предложу свой вариант, немного улучшенный (12) больше универсальности, про быстродействие так же не могу сказать, тесты не проводил:
Можно использовать и запрос, спорить не буду. Таблицу нужно будет подготовить - описать типы колонок, и также добавить колонку, по которой будет происходить суммирование.
Далее почти по тексту, только нужно будет выбирать не различные, а группировать по нужному списку колонок (строить запрос динимически), и добавить в запрос условие "Имеющие сумма(КолонкаСуммирования) = 1". (просто различные использовать нельзя из-за значений в других колонках таблицы). Далее эту сгруппированную временную таблицу нужно будет джойнить с первоначальной временной таблицей, в условиях связи прописывать равенство по выбранным полям (строить условие динамически), плюс нужно будет в случае если нужно не удалить все дублирующие строки, а оставить по одной из удаляемых тоже это предусмотреть.
Хотел еще сказать, что этот способ расчитан, на большое количество строк в таблице, и малое количество строк с дублями, для других случаев можно это делать быстрее другим способом.
Вариант написанный на коленке возможно будет эффективнее, если предоставится возможность, хотел бы на него посмотреть и возможно использовать с Вашего разрешения.
МассивДублей = Новый Массив;
МассивСотрудников = Новый Массив; // проверяемое на дубль значение
Для каждого Строка Из ТЗНачисления Цикл
Если Строка.СпособРасчета = Перечисления.СпособыРасчетаОплатыТруда.СдельныйЗаработок Тогда // критерий сравнения на дубль, может быть любой
Если Элем = Неопределено Тогда // это первое вхождение проверяемого на дубль сотрудника
Иначе // а это - уже мы дубль встретили, по данному сотруднику и по данному критерию проверки на дубль
1С 8.3 Удаление дублирующих строк в Таблице значений
Данная функция принимает таблицу значений (с любой структурой), а возвращает обработанную таблицу с удаленными одинаковыми строками. В параметр КолонкиТЗ можно передать колонки (через запятую), по которым нужно выполнять проверку и удаление строк-дублей. Если параметр пустой, то метод сворачивает ТЗ по всем колонкам.
Функция УдалениеДублирующихСтрокТЗ ( ТЗ , КолонкиТЗ = "" ) Экспорт
Если ПустаяСтрока ( КолонкиТЗ ) Тогда // свертка ТЗ по всем колонкам
Для Каждого ТЗКолонка Из ТЗ . Колонки Цикл
КолонкиТЗ = КолонкиТЗ + ?( ПустаяСтрока ( КолонкиТЗ ), "" , "," ) + ТЗКолонка . Имя ;
КонецЦикла;
КопияТЗ = ТЗ . Скопировать ();
КопияТЗ . Свернуть ( КолонкиТЗ );
КолонкиЗапроса = "ТЗ." + СтрЗаменить ( КолонкиТЗ , "," , ",ТЗ." );
Запрос = Новый Запрос ;
Запрос . Текст = "ВЫБРАТЬ
| " + КолонкиЗапроса + "
|ПОМЕСТИТЬ ВТ_ТЗ
|ИЗ
| &ТЗ КАК ТЗ
|;
|
|//////////////////
|ВЫБРАТЬ РАЗЛИЧНЫЕ
| " + СтрЗаменить ( КолонкиЗапроса , "ТЗ." , "ВТ_ТЗ." ) + "
|ИЗ
| ВТ_ТЗ КАК ВТ_ТЗ
|" ;
Запрос . УстановитьПараметр ( "ТЗ" , ТЗ );
РезультатЗапроса = Запрос . Выполнить ();
Если Не РезультатЗапроса . Пустой () Тогда
ТаблицаЗапроса = РезультатЗапроса . Выгрузить ();
КопияТЗ = ТЗ . СкопироватьКолонки ();
Для Каждого СтрокаТЗ Из ТаблицаЗапроса Цикл
ОтборСтруктура = Новый Структура ( КолонкиТЗ );
ЗаполнитьЗначенияСвойств ( ОтборСтруктура , СтрокаТЗ );
ОтборТЗ = ТЗ . НайтиСтроки ( ОтборСтруктура );
Для Каждого СтрокаОтбораТЗ Из ОтборТЗ Цикл
НоваяСтрокаТЗ = КопияТЗ . Добавить ();
ЗаполнитьЗначенияСвойств ( НоваяСтрокаТЗ , СтрокаОтбораТЗ );
Прервать;
КонецЦикла;
КонецЦикла;
Иначе
КопияТЗ = ТЗ ;
КонецЕсли;
ТЗ = Новый ТаблицаЗначений ;
// Добавляем колонки в таблицу значений
КвалификаторыСтроки = Новый КвалификаторыСтроки ( 50 );
НовСтрока = Новый ОписаниеТипов ( "Строка" , , КвалификаторыСтроки );
ТЗ . Колонки . Добавить ( "Животное" , НовСтрока );
ТЗ . Колонки . Добавить ( "Размер" , НовСтрока );
ТЗ . Колонки . Добавить ( "Цвет" , НовСтрока );
// Добавляем строки в таблицу значений
Стр = ТЗ . Добавить ();
Стр . Животное = "Слон" ;
Стр . Размер = "большой" ;
Стр . Цвет = "зеленый" ;
Стр = ТЗ . Добавить ();
Стр . Животное = "Слон" ;
Стр . Размер = "маленький" ;
Стр . Цвет = "желтый" ;
Стр = ТЗ . Добавить ();
Стр . Животное = "Слон" ;
Стр . Размер = "маленький" ;
Стр . Цвет = "красный" ;
Стр = ТЗ . Добавить ();
Стр . Животное = "Тигр" ;
Стр . Размер = "здоровый" ;
Стр . Цвет = "розовый" ;
Стр = ТЗ . Добавить ();
Стр . Животное = "Тигр" ;
Стр . Размер = "огромный" ;
Стр . Цвет = "черный" ;
Стр = ТЗ . Добавить ();
Стр . Животное = "Тигр" ;
Стр . Размер = "здоровый" ;
Стр . Цвет = "фиолетовый" ;
УдалениеДублирующихСтрокТЗ ( ТЗ , "Животное,Цвет" );
ТЗ = Новый ТаблицаЗначений ;
// Добавляем колонки в таблицу значений
КвалификаторыСтроки = Новый КвалификаторыСтроки ( 50 );
НовСтрока = Новый ОписаниеТипов ( "Строка" , , КвалификаторыСтроки );
ТЗ . Колонки . Добавить ( "Животное" , НовСтрока );
ТЗ . Колонки . Добавить ( "Размер" , НовСтрока );
ТЗ . Колонки . Добавить ( "Цвет" , НовСтрока );
// Добавляем строки в таблицу значений
Стр = ТЗ . Добавить ();
Стр . Животное = "Слон" ;
Стр . Размер = "большой" ;
Стр . Цвет = "зеленый" ;
Стр = ТЗ . Добавить ();
Стр . Животное = "Слон" ;
Стр . Размер = "маленький" ;
Стр . Цвет = "желтый" ;
Стр = ТЗ . Добавить (); //дубль
Стр . Животное = "Слон" ;
Стр . Размер = "маленький" ;
Стр . Цвет = "желтый" ;
Стр = ТЗ . Добавить ();
Стр . Животное = "Тигр" ;
Стр . Размер = "здоровый" ;
Стр . Цвет = "розовый" ;
Стр = ТЗ . Добавить ();
Стр . Животное = "Тигр" ;
Стр . Размер = "огромный" ;
Стр . Цвет = "черный" ;
Стр = ТЗ . Добавить (); //дубль
Стр . Животное = "Тигр" ;
Стр . Размер = "огромный" ;
Стр . Цвет = "черный" ;
УдалениеДублирующихСтрокТЗ ( ТЗ , "Животное,Цвет" );
ТЗ = Новый ТаблицаЗначений ;
// Добавляем колонки в таблицу значений
КвалификаторыСтроки = Новый КвалификаторыСтроки ( 50 );
НовСтрока = Новый ОписаниеТипов ( "Строка" , , КвалификаторыСтроки );
ТЗ . Колонки . Добавить ( "Животное" , НовСтрока );
ТЗ . Колонки . Добавить ( "Размер" , НовСтрока );
ТЗ . Колонки . Добавить ( "Цвет" , НовСтрока );
// Добавляем строки в таблицу значений
Стр = ТЗ . Добавить ();
Стр . Животное = "Слон" ;
Стр . Размер = "большой" ;
Стр . Цвет = "зеленый" ;
Стр = ТЗ . Добавить ();
Стр . Животное = "Слон" ;
Стр . Размер = "маленький" ;
Стр . Цвет = "желтый" ;
Стр = ТЗ . Добавить (); //дубль
Стр . Животное = "Слон" ;
Стр . Размер = "маленький" ;
Стр . Цвет = "желтый" ;
Стр = ТЗ . Добавить ();
Стр . Животное = "Тигр" ;
Стр . Размер = "здоровый" ;
Стр . Цвет = "розовый" ;
Стр = ТЗ . Добавить ();
Стр . Животное = "Тигр" ;
Стр . Размер = "маленький" ;
Стр . Цвет = "черный" ;
Стр = ТЗ . Добавить (); //дубль т.к. размер не учитывается
Стр . Животное = "Тигр" ;
Стр . Размер = "огромный" ;
Стр . Цвет = "черный" ;
Таблица значений в 1С 8.3 это универсальная коллекция, которая максимально моделирует двумерную таблицу базы данных. Она имеет колонки различных типов (число, строка, дата, булево), в т.ч. неопределённого типа, строки с различным содержимым, свойства и методы для работы с колонками и строками. Таблицу значений можно заполнять произвольным кодом, из наборов регистров, или по результатам работы запроса, построителя запроса, процессора СКД, загружать из других табличных частей, заполнять массивами. Её можно использовать для заполнения табличных частей документов, справочников, наборов регистров, как источник данных в запросах, построителях запросов, построителях отчётов и наборах данных СКД. В Таблице значений есть выгрузка журнала регистрации и результатов поиска ссылок.
// Создаем таблицу значений
ТЗ = Новый ТаблицаЗначений ;
// Добавляем колонки в таблицу значений
ТЗ . Колонки . Добавить ( "Овощь" );
ТЗ . Колонки . Добавить ( "Цвет" );
ТЗ . Колонки . Добавить ( "Вкус" );
// Добавляем строки в таблицу значений
Стр = ТЗ . Добавить ();
Стр . Овощь = "Дыня" ;
Стр . Цвет = "Желтая" ;
Стр . Вкус = "Сладкая" ;
Стр = ТЗ . Добавить ();
Стр . Овощь = "Лук" ;
Стр . Цвет = "Зеленый" ;
Стр . Вкус = "Горький" ;
Стр = ТЗ . Добавить ();
Стр . Овощь = "Помидор" ;
Стр . Цвет = "Красный" ;
Стр . Вкус = "Сочный" ;
// Добавляем в таблицу значений колонку с описанием типа и заголовка
ОписаниеВеса = Новый ОписаниеТипов ( "Число" , Новый КвалификаторыЧисла ( 14 , 2 ));
ТЗ . Колонки . Добавить ( "ВесОвоща" , ОписаниеВеса , "Вес овоща в граммах" );
ТЗ [ 0 ]. ВесОвоща = 2500. 50 ;
ТЗ [ 1 ]. ВесОвоща = 39. 07 ;
ТЗ [ 2 ]. ВесОвоща = 90. 45 ;
// Перечисляем все строки в таблице значений
Для Каждого Стр Из ТЗ Цикл
Сообщить ( Стр . Овощь + " " + Стр . Цвет + " " + Стр . Вкус + " " + Стр . ВесОвоща );
КонецЦикла;
// Перечисляем все колонки в таблице значений
Для Каждого Колонка Из ТЗ . Колонки Цикл
Сообщить ( Колонка . Имя );
КонецЦикла;
// Выгружаем колонку названий таблицы значений в массив
МассивОвощей = ТЗ . ВыгрузитьКолонку ( "Овощь" );
// Ничего не измениться, так как массив не менялся
ТЗ . ЗагрузитьКолонку ( МассивОвощей , "Овощь" );
// Заполнение значения в колонке для всех строк таблицы. Обнулим вес во всех строках
ТЗ . ЗаполнитьЗначения ( 0 , "ВесОвоща" );
// Перезапишем на новые веса
ТЗ [ 0 ]. ВесОвоща = 2500 ;
ТЗ [ 1 ]. ВесОвоща = 40 ;
ТЗ [ 2 ]. ВесОвоща = 90 ;
// Расчет итогов по колонке в таблице значений
ИтогПоКолонке = ТЗ . Итог ( "ВесОвоща" ); // Общий вес овощей = 2630
// Поиск строки в Таблице значений - найдём строчку с яблоком и покажем его цвет
СтрокаПоиска = ТЗ . Найти ( "Помидор" );
Если СтрокаПоиска <> Неопределено Тогда
Сообщить ( СтрокаПоиска . Цвет ); // Красный
КонецЕсли;
// Ищем строку в таблице значений поиском значения в определенных колонках
// будем искать по слову "Сочный" в колонках "Вкус" и "Цвет"
СтрокаПоиска = ТЗ . Найти ( "Сочный" , "Вкус, Цвет" );
Если СтрокаПоиска <> Неопределено Тогда
Сообщить ( СтрокаПоиска . Овощь ); // Помидор
КонецЕсли;
// Добавляем ещё один красный овощь Перец, Вариант №1
Стр = ТЗ . Добавить ();
Стр . Овощь = "Перец" ;
Стр . Цвет = "Красный" ;
Стр . Вкус = "Сладкий" ;
Стр . ВесОвоща = 120 ;
// Добавляем ещё один красный овощь Перец, Вариант №2
Стр = ТЗ . Добавить ();
Стр [ "Овощь" ] = "Перец" ;
Стр [ "Цвет" ] = "Красный" ;
Стр [ "Вкус" ] = "Сладкий" ;
Стр [ "ВесОвоща" ] = 120 ;
// Выполняем поиск в Таблице Значений (неуникальные значения)
Отбор = Новый Структура ;
Отбор . Вставить ( "Цвет" , "Красный" );
Строки = ТЗ . НайтиСтроки ( Отбор );
Для Каждого Стр Из Строки Цикл
Сообщить ( Стр . Овощь ); // Помидор Перец
КонецЦикла;
// Сдвигаем первую строку Таблицы Значений на одну позицию вперёд
ТЗ . Сдвинуть ( 0 , 1 );
// Возвращаем обратно строку Таблицы Значений
ТЗ . Сдвинуть ( 1 , - 1 );
// Скопировать (выгрузить) табличную часть документа/справочника/. в Таблицу Значений
ТЗ = ТабличнаяЧастьN . Выгрузить ();
// Создаем полную копию Таблицы Значений
КопияТЗ = ТЗ . Скопировать ();
// Создаем копию таблицы значений по нужным колонкам - будет только две колонки Овощь и Цвет
КопияТЗ = ТЗ . СкопироватьКолонки ( "Овощь, Цвет" );
// Создаем полную копию Таблицы Значений по отбору
Отбор = Новый Структура ;
Отбор . Вставить ( "Овощь" , "Помидор" );
// Таблица Значений будет содержать только строчку с помидором
КопияТЗ = ТЗ . Скопировать ( Отбор );
// Таблица Значений будет содержать цвет и вес помидора
КопияТЗ = ТЗ . Скопировать ( Отбор , "Цвет, ВесОвоща" );
// Сворачиваем Таблицу значений по колонке "Вкус", просуммируем по весу
ТЗ . Свернуть ( "Вкус" , "ВесОвоща" );
// Отсортируем Таблицу Значений по колонке
ТЗ . Сортировать ( "ВесОвоща Возр" );
// Отсортируем Таблицу Значений по нескольким колонкам
ТЗ . Сортировать ( "ВесОвоща Возр, Вкус Убыв" );
// Удаляем строку из Таблицы Значений (по индексу или по значению)
ТЗ . Удалить ( 0 );
// Очистим (удалим) все строки из Таблицы Значений
ТЗ . Очистить ();
Читайте также: