//////////////////////////////////////////////////////////////////////////////// // Обработка: A1sDP_VT // Назначение: Fluent Interface для работы с таблицами значений // Версия: 2.1.0 //////////////////////////////////////////////////////////////////////////////// #Область ОписаниеПеременных Перем мТаблица; // ТаблицаЗначений — рабочая таблица #КонецОбласти #Область Инициализация /// ✦ Init — Инициализация обработки с таблицей значений /// ➤ Исходная (ТаблицаЗначений, Строка, Неопределено) — Таблица, строка колонок или пусто /// ⬅ A1sDP_VT — ЭтотОбъект для цепочки вызовов Функция Init(Знач Исходная = Неопределено) Экспорт Если Исходная = Неопределено Тогда мТаблица = Новый ТаблицаЗначений; ИначеЕсли ТипЗнч(Исходная) = Тип("ТаблицаЗначений") Тогда // Создаем копию, чтобы не мутировать исходную мТаблица = Исходная.Скопировать(); ИначеЕсли ТипЗнч(Исходная) = Тип("Строка") Тогда // Делегируем парсинг строки статическому модулю мТаблица = A1sVT.Of(Исходная); ИначеЕсли ТипЗнч(Исходная) = Тип("Структура") Тогда // Делегируем парсинг структуры статическому модулю (если поддерживается или через OfColumns+AddRow) // В A1sVT.Of нет прямого приема структуры как описания колонок, но это легко сделать. // Пока просто создаем пустую и добавляем колонки, если это структура. // TODO: Если A1sVT.Of поддерживает структуру как описание типов, использовать её. // В текущей версии A1sVT.OfStructureArray принимает массив структур, а не описание колонок. // Поэтому здесь придется реализовать добавление колонок вручную или использовать A1sVT.OfColumns со строкой. // Проще всего: мТаблица = Новый ТаблицаЗначений; Для Каждого КлючЗначение Из Исходная Цикл Если ТипЗнч(КлючЗначение.Значение) = Тип("Строка") Тогда мТаблица.Колонки.Добавить(КлючЗначение.Ключ, A1sVT._ПолучитьТипПоИмени(КлючЗначение.Значение)); КонецЕсли; КонецЦикла; Иначе мТаблица = Новый ТаблицаЗначений; КонецЕсли; Возврат ЭтотОбъект; КонецФункции #КонецОбласти #Область МетодыТрансформаторы /// ✦ AddRow — Добавить строку в таблицу /// ➤ ЗначенияСтроки (Структура, Массив) — Данные для новой строки /// ⬅ A1sDP_VT — ЭтотОбъект для цепочки вызовов Функция AddRow(Знач ЗначенияСтроки) Экспорт // Делегируем добавление строки статическому модулю A1sVT.AddRow(мТаблица, ЗначенияСтроки); Возврат ЭтотОбъект; КонецФункции /// ✦ AddRows — Добавить несколько строк в таблицу /// ➤ МассивСтрок (Массив) — Массив структур или массивов со значениями /// ⬅ A1sDP_VT — ЭтотОбъект для цепочки вызовов Функция AddRows(Знач МассивСтрок) Экспорт Если ТипЗнч(МассивСтрок) = Тип("Массив") Тогда Для Каждого ДанныеСтроки Из МассивСтрок Цикл AddRow(ДанныеСтроки); КонецЦикла; КонецЕсли; Возврат ЭтотОбъект; КонецФункции /// ✦ Filter — Оставить только строки по условию (мутирует таблицу) /// ➤ КолонкиИЗначения (Структура) — Условие фильтрации /// ⬅ A1sDP_VT — ЭтотОбъект для цепочки вызовов Функция Filter(Знач КолонкиИЗначения) Экспорт Если КолонкиИЗначения = Неопределено Тогда Возврат ЭтотОбъект; КонецЕсли; // Используем оптимизированный метод удаления // Находим строки, которые НЕ соответствуют фильтру, и удаляем их. // Таблица.НайтиСтроки возвращает соответствующие. СтрокиДляУдаления = Новый Массив; Для Каждого Строка Из мТаблица Цикл Удалить = Ложь; Для Каждого КлючЗначение Из КолонкиИЗначения Цикл Если Строка[КлючЗначение.Ключ] <> КлючЗначение.Значение Тогда Удалить = Истина; Прервать; КонецЕсли; КонецЦикла; Если Удалить Тогда СтрокиДляУдаления.Добавить(Строка); КонецЕсли; КонецЦикла; Для Каждого Строка Из СтрокиДляУдаления Цикл мТаблица.Удалить(Строка); КонецЦикла; Возврат ЭтотОбъект; КонецФункции /// ✦ Sort — Сортировать таблицу /// ➤ Колонки (Строка) — Колонки для сортировки /// ⬅ A1sDP_VT — ЭтотОбъект для цепочки вызовов Функция Sort(Знач Колонки) Экспорт мТаблица.Сортировать(Колонки); Возврат ЭтотОбъект; КонецФункции /// ✦ Clear — Очистить все строки таблицы /// ⬅ A1sDP_VT — ЭтотОбъект для цепочки вызовов Функция Clear() Экспорт мТаблица.Очистить(); Возврат ЭтотОбъект; КонецФункции /// ✦ DeleteRows — Удалить строки по условию /// ➤ КолонкиИЗначения (Структура) — Условие поиска строк для удаления /// ⬅ A1sDP_VT — ЭтотОбъект для цепочки вызовов Функция DeleteRows(Знач КолонкиИЗначения) Экспорт НайденныеСтроки = мТаблица.НайтиСтроки(КолонкиИЗначения); Для Каждого Строка Из НайденныеСтроки Цикл мТаблица.Удалить(Строка); КонецЦикла; Возврат ЭтотОбъект; КонецФункции /// ✦ GroupBy — Сгруппировать таблицу с агрегацией /// ➤ КолонкиГруппировки (Строка) — Колонки для группировки через запятую /// ➤ КолонкиСуммирования (Строка) — Колонки для суммирования через запятую /// ⬅ A1sDP_VT — ЭтотОбъект для цепочки вызовов Функция GroupBy(Знач КолонкиГруппировки, Знач КолонкиСуммирования = "") Экспорт мТаблица.Свернуть(КолонкиГруппировки, КолонкиСуммирования); Возврат ЭтотОбъект; КонецФункции /// ✦ CreateIndex — Создать индекс для быстрого поиска /// ➤ Колонки (Строка) — Колонки индекса через запятую /// ⬅ A1sDP_VT — ЭтотОбъект для цепочки вызовов Функция CreateIndex(Знач Колонки) Экспорт мТаблица.Индексы.Добавить(Колонки); Возврат ЭтотОбъект; КонецФункции /// ✦ AddColumn — Добавить колонку в таблицу /// ➤ ИмяКолонки (Строка) — Имя новой колонки /// ➤ Тип (Строка, ОписаниеТипов) — Тип колонки (необязательно) /// ➤ ЗначениеПоУмолчанию (Произвольный) — Значение для всех существующих строк /// ⬅ A1sDP_VT — ЭтотОбъект для цепочки вызовов Функция AddColumn(Знач ИмяКолонки, Знач Тип = Неопределено, Знач ЗначениеПоУмолчанию = Неопределено) Экспорт ОписаниеТипа = Неопределено; Если ТипЗнч(Тип) = Тип("Строка") И НЕ ПустаяСтрока(Тип) Тогда ОписаниеТипа = A1sVT._ПолучитьТипПоИмени(Тип); ИначеЕсли ТипЗнч(Тип) = Тип("ОписаниеТипов") Тогда ОписаниеТипа = Тип; КонецЕсли; Если ОписаниеТипа <> Неопределено Тогда мТаблица.Колонки.Добавить(ИмяКолонки, ОписаниеТипа); Иначе мТаблица.Колонки.Добавить(ИмяКолонки); КонецЕсли; // Заполняем значением по умолчанию Если ЗначениеПоУмолчанию <> Неопределено Тогда Для Каждого Строка Из мТаблица Цикл Строка[ИмяКолонки] = ЗначениеПоУмолчанию; КонецЦикла; КонецЕсли; Возврат ЭтотОбъект; КонецФункции /// ✦ RemoveColumn — Удалить колонку из таблицы /// ➤ ИмяКолонки (Строка) — Имя удаляемой колонки /// ⬅ A1sDP_VT — ЭтотОбъект для цепочки вызовов Функция RemoveColumn(Знач ИмяКолонки) Экспорт Колонка = мТаблица.Колонки.Найти(ИмяКолонки); Если Колонка <> Неопределено Тогда мТаблица.Колонки.Удалить(Колонка); КонецЕсли; Возврат ЭтотОбъект; КонецФункции /// ✦ RenameColumn — Переименовать колонку /// ➤ СтароеИмя (Строка) — Текущее имя колонки /// ➤ НовоеИмя (Строка) — Новое имя колонки /// ⬅ A1sDP_VT — ЭтотОбъект для цепочки вызовов Функция RenameColumn(Знач СтароеИмя, Знач НовоеИмя) Экспорт Колонка = мТаблица.Колонки.Найти(СтароеИмя); Если Колонка <> Неопределено Тогда Колонка.Имя = НовоеИмя; КонецЕсли; Возврат ЭтотОбъект; КонецФункции /// ✦ SetValue — Установить значение для всех строк в колонке /// ➤ ИмяКолонки (Строка) — Имя колонки /// ➤ Значение (Произвольный) — Значение для установки /// ⬅ A1sDP_VT — ЭтотОбъект для цепочки вызовов Функция SetValue(Знач ИмяКолонки, Знач Значение) Экспорт Для Каждого Строка Из мТаблица Цикл Строка[ИмяКолонки] = Значение; КонецЦикла; Возврат ЭтотОбъект; КонецФункции /// ✦ UpdateRows — Обновить строки по условию /// ➤ КолонкиИЗначения (Структура) — Условие поиска строк /// ➤ НовыеЗначения (Структура) — Новые значения для обновления /// ⬅ A1sDP_VT — ЭтотОбъект для цепочки вызовов Функция UpdateRows(Знач КолонкиИЗначения, Знач НовыеЗначения) Экспорт НайденныеСтроки = мТаблица.НайтиСтроки(КолонкиИЗначения); Для Каждого Строка Из НайденныеСтроки Цикл ЗаполнитьЗначенияСвойств(Строка, НовыеЗначения); КонецЦикла; Возврат ЭтотОбъект; КонецФункции /// ✦ Reverse — Развернуть порядок строк /// ⬅ A1sDP_VT — ЭтотОбъект для цепочки вызовов Функция Reverse() Экспорт Если мТаблица.Количество() <= 1 Тогда Возврат ЭтотОбъект; КонецЕсли; НоваяТаблица = мТаблица.СкопироватьКолонки(); Для Инд = мТаблица.Количество() - 1 По 0 Цикл ЗаполнитьЗначенияСвойств(НоваяТаблица.Добавить(), мТаблица[Инд]); КонецЦикла; мТаблица = НоваяТаблица; Возврат ЭтотОбъект; КонецФункции /// ✦ Take — Взять первые N строк /// ➤ Количество (Число) — Количество строк /// ⬅ A1sDP_VT — ЭтотОбъект для цепочки вызовов Функция Take(Знач Количество) Экспорт Пока мТаблица.Количество() > Количество Цикл мТаблица.Удалить(мТаблица.Количество() - 1); КонецЦикла; Возврат ЭтотОбъект; КонецФункции /// ✦ Skip — Пропустить первые N строк /// ➤ Количество (Число) — Количество пропускаемых строк /// ⬅ A1sDP_VT — ЭтотОбъект для цепочки вызовов Функция Skip(Знач Количество) Экспорт Удалено = 0; Пока Удалено < Количество И мТаблица.Количество() > 0 Цикл мТаблица.Удалить(0); Удалено = Удалено + 1; КонецЦикла; Возврат ЭтотОбъект; КонецФункции /// ✦ Page — Получить страницу данных (комбинация Skip + Take) /// ➤ НомерСтраницы (Число) — Номер страницы (начиная с 1) /// ➤ РазмерСтраницы (Число) — Количество записей на странице /// ⬅ A1sDP_VT — ЭтотОбъект для цепочки вызовов Функция Page(Знач НомерСтраницы, Знач РазмерСтраницы) Экспорт Пропустить = (НомерСтраницы - 1) * РазмерСтраницы; Skip(Пропустить); Take(РазмерСтраницы); Возврат ЭтотОбъект; КонецФункции /// ✦ Union — Добавить строки из других таблиц /// ➤ ДобавляемыеТаблицы (ТаблицаЗначений, Массив) — Таблица или массив таблиц /// ⬅ A1sDP_VT — ЭтотОбъект для цепочки вызовов Функция Union(Знач ДобавляемыеТаблицы) Экспорт Если ТипЗнч(ДобавляемыеТаблицы) = Тип("ТаблицаЗначений") Тогда Для Каждого Строка Из ДобавляемыеТаблицы Цикл ЗаполнитьЗначенияСвойств(мТаблица.Добавить(), Строка); КонецЦикла; ИначеЕсли ТипЗнч(ДобавляемыеТаблицы) = Тип("Массив") Тогда Для Каждого Таблица Из ДобавляемыеТаблицы Цикл Для Каждого Строка Из Таблица Цикл ЗаполнитьЗначенияСвойств(мТаблица.Добавить(), Строка); КонецЦикла; КонецЦикла; КонецЕсли; Возврат ЭтотОбъект; КонецФункции /// ✦ KeepColumns — Оставить только указанные колонки /// ➤ СписокКолонок (Строка) — Колонки для сохранения через запятую /// ⬅ A1sDP_VT — ЭтотОбъект для цепочки вызовов Функция KeepColumns(Знач СписокКолонок) Экспорт // Делегируем копирование статическому модулю мТаблица = A1sVT.Copy(мТаблица, СписокКолонок); Возврат ЭтотОбъект; КонецФункции /// ✦ UpdateRowIf — Обновить строку по условию /// ➤ КолонкиИЗначения (Структура) — Условие поиска строки /// ➤ НовыеЗначения (Структура) — Новые значения /// ⬅ A1sDP_VT — ЭтотОбъект для цепочки вызовов Функция UpdateRowIf(Знач КолонкиИЗначения, Знач НовыеЗначения) Экспорт НайденныеСтроки = мТаблица.НайтиСтроки(КолонкиИЗначения); Если НайденныеСтроки.Количество() > 0 Тогда ЗаполнитьЗначенияСвойств(НайденныеСтроки[0], НовыеЗначения); КонецЕсли; Возврат ЭтотОбъект; КонецФункции #КонецОбласти #Область МетодыТерминаторы /// ✦ Value — Получить результирующую таблицу значений /// ⬅ ТаблицаЗначений — Результирующая таблица Функция Value() Экспорт Возврат мТаблица; КонецФункции /// ✦ Copy — Получить копию таблицы /// ➤ Колонки (Строка) — Список колонок для копирования (пусто = все) /// ⬅ ТаблицаЗначений — Копия таблицы Функция Copy(Знач Колонки = "") Экспорт Возврат A1sVT.Copy(мТаблица, Колонки); КонецФункции /// ✦ ToArray — Преобразовать таблицу в массив структур /// ➤ Колонки (Строка) — Список колонок (пусто = все) /// ⬅ Массив — Массив структур Функция ToArray(Знач Колонки = "") Экспорт Возврат A1sVT.ToArray(мТаблица, Колонки); КонецФункции /// ✦ Column — Получить значения колонки в виде массива /// ➤ ИмяКолонки (Строка) — Имя колонки /// ⬅ Массив — Массив значений колонки Функция Column(Знач ИмяКолонки) Экспорт Возврат A1sVT.Column(мТаблица, ИмяКолонки); КонецФункции /// ✦ FindRow — Найти первую строку по условию /// ➤ КолонкиИЗначения (Структура) — Условие поиска /// ⬅ СтрокаТаблицыЗначений, Неопределено — Найденная строка или Неопределено Функция FindRow(Знач КолонкиИЗначения) Экспорт НайденныеСтроки = мТаблица.НайтиСтроки(КолонкиИЗначения); Если НайденныеСтроки.Количество() > 0 Тогда Возврат НайденныеСтроки[0]; Иначе Возврат Неопределено; КонецЕсли; КонецФункции /// ✦ FindRows — Найти все строки по условию /// ➤ КолонкиИЗначения (Структура) — Условие поиска /// ⬅ Массив — Массив найденных строк Функция FindRows(Знач КолонкиИЗначения) Экспорт Возврат мТаблица.НайтиСтроки(КолонкиИЗначения); КонецФункции /// ✦ First — Получить первую строку таблицы /// ➤ ПоУмолчанию (Произвольный) — Значение если таблица пуста /// ⬅ СтрокаТаблицыЗначений, Произвольный — Первая строка или значение по умолчанию Функция First(Знач ПоУмолчанию = Неопределено) Экспорт Если мТаблица.Количество() > 0 Тогда Возврат мТаблица[0]; Иначе Возврат ПоУмолчанию; КонецЕсли; КонецФункции /// ✦ Last — Получить последнюю строку таблицы /// ➤ ПоУмолчанию (Произвольный) — Значение если таблица пуста /// ⬅ СтрокаТаблицыЗначений, Произвольный — Последняя строка или значение по умолчанию Функция Last(Знач ПоУмолчанию = Неопределено) Экспорт Если мТаблица.Количество() > 0 Тогда Возврат мТаблица[мТаблица.Количество() - 1]; Иначе Возврат ПоУмолчанию; КонецЕсли; КонецФункции /// ✦ Get — Получить строку по индексу /// ➤ Индекс (Число) — Индекс строки /// ➤ ПоУмолчанию (Произвольный) — Значение если индекс вне диапазона /// ⬅ СтрокаТаблицыЗначений, Произвольный — Строка или значение по умолчанию Функция Get(Знач Индекс, Знач ПоУмолчанию = Неопределено) Экспорт Если Индекс >= 0 И Индекс < мТаблица.Количество() Тогда Возврат мТаблица[Индекс]; Иначе Возврат ПоУмолчанию; КонецЕсли; КонецФункции /// ✦ Count — Получить количество строк /// ⬅ Число — Количество строк в таблице Функция Count() Экспорт Возврат мТаблица.Количество(); КонецФункции /// ✦ IsEmpty — Проверить пустоту таблицы /// ⬅ Булево — Истина если таблица пуста Функция IsEmpty() Экспорт Возврат мТаблица.Количество() = 0; КонецФункции /// ✦ HasColumn — Проверить наличие колонки /// ➤ ИмяКолонки (Строка) — Имя искомой колонки /// ⬅ Булево — Истина если колонка существует Функция HasColumn(Знач ИмяКолонки) Экспорт Возврат мТаблица.Колонки.Найти(ИмяКолонки) <> Неопределено; КонецФункции /// ✦ GetColumnNames — Получить имена всех колонок /// ⬅ Массив — Массив имён колонок Функция GetColumnNames() Экспорт Возврат A1sVT.GetColumnNames(мТаблица); КонецФункции /// ✦ Total — Сумма значений колонки /// ➤ ИмяКолонки (Строка) — Имя числовой колонки /// ⬅ Число — Сумма значений Функция Total(Знач ИмяКолонки) Экспорт Возврат A1sVT.Total(мТаблица, ИмяКолонки); КонецФункции /// ✦ Maximum — Максимальное значение в колонке /// ➤ ИмяКолонки (Строка) — Имя колонки /// ⬅ Произвольный — Максимальное значение или Неопределено Функция Maximum(Знач ИмяКолонки) Экспорт Возврат A1sVT.Maximum(мТаблица, ИмяКолонки); КонецФункции /// ✦ Minimum — Минимальное значение в колонке /// ➤ ИмяКолонки (Строка) — Имя колонки /// ⬅ Произвольный — Минимальное значение или Неопределено Функция Minimum(Знач ИмяКолонки) Экспорт Возврат A1sVT.Minimum(мТаблица, ИмяКолонки); КонецФункции /// ✦ Avg — Среднее значение в колонке /// ➤ ИмяКолонки (Строка) — Имя числовой колонки /// ⬅ Число — Среднее значение или 0 Функция Avg(Знач ИмяКолонки) Экспорт Возврат A1sVT.Avg(мТаблица, ИмяКолонки); КонецФункции /// ✦ Sanitize — Очистить таблицу для JSON /// ⬅ Массив — Массив структур (JSON-ready) Функция Sanitize() Экспорт Возврат A1sVT.Sanitize(мТаблица); КонецФункции /// ✦ ToJSON — Преобразовать таблицу в JSON-строку /// ⬅ Строка — JSON Функция ToJSON() Экспорт Возврат A1sVT.ToJSON(мТаблица); КонецФункции #КонецОбласти #Область Тестирование Функция SelfTest() Экспорт ВсегоТестов = 0; ПройденоТестов = 0; Успешно = Истина; Сообщить("=== Запуск тестирования A1sDP_VT ==="); // ТЕСТ 1: Init + AddRow + Value ВсегоТестов = ВсегоТестов + 1; Попытка Результат = Init("Код,Наименование") .AddRow(Новый Структура("Код,Наименование", "001", "Товар1")) .AddRow(Новый Структура("Код,Наименование", "002", "Товар2")) .Value(); Если Результат.Количество() = 2 И Результат[0].Код = "001" Тогда ПройденоТестов = ПройденоТестов + 1; Сообщить("✓ Тест 1 (Init + AddRow + Value): ПРОЙДЕН"); Иначе Сообщить("✗ Тест 1: ПРОВАЛЕН"); КонецЕсли; Исключение Сообщить("✗ Тест 1: ОШИБКА - " + ОписаниеОшибки()); Успешно = Ложь; КонецПопытки; // ТЕСТ 2: Filter ВсегоТестов = ВсегоТестов + 1; Попытка Результат = Init("Код,Активен:Булево") .AddRow(Новый Структура("Код,Активен", "001", Истина)) .AddRow(Новый Структура("Код,Активен", "002", Ложь)) .AddRow(Новый Структура("Код,Активен", "003", Истина)) .Filter(Новый Структура("Активен", Истина)) .Value(); Если Результат.Количество() = 2 Тогда ПройденоТестов = ПройденоТестов + 1; Сообщить("✓ Тест 2 (Filter): ПРОЙДЕН"); Иначе Сообщить("✗ Тест 2: ПРОВАЛЕН"); КонецЕсли; Исключение Сообщить("✗ Тест 2: ОШИБКА - " + ОписаниеОшибки()); Успешно = Ложь; КонецПопытки; // ТЕСТ 3: Sort ВсегоТестов = ВсегоТестов + 1; Попытка Результат = Init("Код,Цена:Число") .AddRow(Новый Структура("Код,Цена", "002", 200)) .AddRow(Новый Структура("Код,Цена", "001", 100)) .AddRow(Новый Структура("Код,Цена", "003", 300)) .Sort("Цена") .Value(); Если Результат[0].Цена = 100 И Результат[2].Цена = 300 Тогда ПройденоТестов = ПройденоТестов + 1; Сообщить("✓ Тест 3 (Sort): ПРОЙДЕН"); Иначе Сообщить("✗ Тест 3: ПРОВАЛЕН"); КонецЕсли; Исключение Сообщить("✗ Тест 3: ОШИБКА - " + ОписаниеОшибки()); Успешно = Ложь; КонецПопытки; // Итоги Если Успешно Тогда Сообщить("✓ A1sDP_VT.SelfTest: Пройдено " + Строка(ПройденоТестов) + " из " + Строка(ВсегоТестов) + " тестов"); Возврат Истина; Иначе Сообщить("✗ A1sDP_VT.SelfTest: ОШИБКА! Пройдено " + Строка(ПройденоТестов) + " из " + Строка(ВсегоТестов) + " тестов"); Возврат Ложь; КонецЕсли; КонецФункции #КонецОбласти //////////////////////////////////////////////////////////////////////////////// // МОДУЛЬ ЗАВЕРШЕН - A1sDP_VT v2.1.0 ////////////////////////////////////////////////////////////////////////////////