////////////////////////////////////////////////////////////////////////////////
// Модуль: A1sVT
// Назначение: Упрощённая работа с таблицами значений
// Версия: 2.1.0
// Автор: A1sCode
// Сайт: https://a1scode.ru
// Лицензия: MIT
////////////////////////////////////////////////////////////////////////////////
#Область ФабрикиТаблиц
//
// Создает таблицу значений с колонками и опциональными строками данных. ✦
// Строка вида "Колонка1:Тип1,Колонка2:Тип2" или структура с колонками и типами ➤
// Массив структур или массивов со значениями строк (необязательно) ➤
// ValueTable — новая таблица значений ⬅
//
//
Функция Of(КолонкиИТипы, Строки = Неопределено) Экспорт //⚙
Таблица = Новый ТаблицаЗначений; //✏
// Добавляем колонки
Если ТипЗнч(КолонкиИТипы) = Тип("Строка") Тогда //⚡
_ДобавитьКолонкиИзСтроки(Таблица, КолонкиИТипы); //▶️
ИначеЕсли ТипЗнч(КолонкиИТипы) = Тип("Структура") Тогда //⚡
_ДобавитьКолонкиИзСтруктуры(Таблица, КолонкиИТипы); //▶️
КонецЕсли;
// Добавляем строки если переданы
Если ТипЗнч(Строки) = Тип("Массив") Тогда //⚡
Для Каждого ДанныеСтроки Из Строки Цикл //⟳
_ДобавитьСтрокуВТаблицу(Таблица, ДанныеСтроки); //▶️
КонецЦикла;
КонецЕсли;
Возврат Таблица; //↩
КонецФункции
//
// Создает пустую таблицу только с колонками без строк. ✦
//
Функция OfColumns(КолонкиИТипы) Экспорт //⚙
Возврат Of(КолонкиИТипы); //▶️
КонецФункции
//
// Создает таблицу значений на основе массива структур (автоопределение типов). ✦
//
Функция OfStructArray(Знач МассивСтруктур) Экспорт
ТаблицаРезультата = Новый ТаблицаЗначений;
Если МассивСтруктур = Неопределено ИЛИ МассивСтруктур.Количество() = 0 Тогда
Возврат ТаблицаРезультата;
КонецЕсли;
ПерваяСтрока = МассивСтруктур[0];
// Создаем описание типов на основе данных из первой строки
Для Каждого КлючИЗначение Из ПерваяСтрока Цикл
ИмяКолонки = КлючИЗначение.Ключ;
Значение = КлючИЗначение.Значение;
ОписаниеТипа = _ПолучитьОписаниеТипаДляЗначения(Значение, МассивСтруктур);
ТаблицаРезультата.Колонки.Добавить(ИмяКолонки, ОписаниеТипа);
КонецЦикла;
// Заполняем таблицу данными
Для Каждого СтруктураИзМассива Из МассивСтруктур Цикл
НоваяСтрока = ТаблицаРезультата.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, СтруктураИзМассива);
КонецЦикла;
Возврат ТаблицаРезультата;
КонецФункции
//
// Добавляет новую строку в таблицу и заполняет её значениями. ✦
//
Функция AddRow(Таблица, ЗначенияСтроки) Экспорт //⚙
НоваяСтрока = Таблица.Добавить(); //✏
Если ТипЗнч(ЗначенияСтроки) = Тип("Структура") Тогда //⚡
ЗаполнитьЗначенияСвойств(НоваяСтрока, ЗначенияСтроки); //✏
ИначеЕсли ТипЗнч(ЗначенияСтроки) = Тип("Массив") Тогда //⚡
_ЗаполнитьСтрокуИзМассива(НоваяСтрока, ЗначенияСтроки); //▶️
КонецЕсли;
Возврат НоваяСтрока; //↩
КонецФункции
//
// Добавляет несколько строк в таблицу из массива. ✦
//
Функция AddRows(Таблица, МассивСтрок) Экспорт //⚙
Счетчик = 0; //✏
Для Каждого ДанныеСтроки Из МассивСтрок Цикл //⟳
AddRow(Таблица, ДанныеСтроки); //▶️
Счетчик = Счетчик + 1; //✏
КонецЦикла;
Возврат Счетчик; //↩
КонецФункции
#КонецОбласти
#Область НавигацияПоТаблице
/// ✦ First — Первая строка таблицы
Функция First(Таблица) Экспорт //⚙
Если Таблица.Количество() = 0 Тогда //⚡
Возврат Неопределено; //↩
КонецЕсли;
Возврат Таблица[0]; //↩
КонецФункции
/// ✦ Last — Последняя строка таблицы
Функция Last(Таблица) Экспорт //⚙
Количество = Таблица.Количество(); //✏
Если Количество = 0 Тогда //⚡
Возврат Неопределено; //↩
КонецЕсли;
Возврат Таблица[Количество - 1]; //↩
КонецФункции
/// ✦ Take — Первые N строк таблицы (TOP-N)
Функция Take(Таблица, N) Экспорт //⚙
Результат = Таблица.Скопировать(); //✏
Пока Результат.Количество() > N Цикл //⟳
Результат.Удалить(Результат.Количество() - 1);
КонецЦикла;
Возврат Результат; //↩
КонецФункции
/// ✦ Skip — Пропустить первые N строк таблицы
Функция Skip(Таблица, N) Экспорт //⚙
Результат = Таблица.Скопировать(); //✏
Удалено = 0; //✏
Пока Удалено < N И Результат.Количество() > 0 Цикл //⟳
Результат.Удалить(0);
Удалено = Удалено + 1; //✏
КонецЦикла;
Возврат Результат; //↩
КонецФункции
/// ✦ Page — Получить страницу данных
Функция Page(Таблица, НомерСтраницы, РазмерСтраницы) Экспорт //⚙
Пропустить = (НомерСтраницы - 1) * РазмерСтраницы; //✏
Возврат Take(Skip(Таблица, Пропустить), РазмерСтраницы); //↩
КонецФункции
#КонецОбласти
#Область АгрегатныеФункции
/// ✦ Total — Сумма значений колонки
Функция Total(Таблица, ИмяКолонки) Экспорт //⚙
Результат = 0; //✏
Для Каждого Строка Из Таблица Цикл //⟳
Значение = Строка[ИмяКолонки]; //✏
Если ТипЗнч(Значение) = Тип("Число") Тогда //⚡
Результат = Результат + Значение; //✏
КонецЕсли;
КонецЦикла;
Возврат Результат; //↩
КонецФункции
/// ✦ Avg — Среднее значение колонки
Функция Avg(Таблица, ИмяКолонки) Экспорт //⚙
Количество = Таблица.Количество(); //✏
Если Количество = 0 Тогда //⚡
Возврат 0; //↩
КонецЕсли;
Возврат Total(Таблица, ИмяКолонки) / Количество; //↩
КонецФункции
/// ✦ Minimum — Минимальное значение колонки
Функция Minimum(Таблица, ИмяКолонки) Экспорт //⚙
Если Таблица.Количество() = 0 Тогда //⚡
Возврат Неопределено; //↩
КонецЕсли;
Результат = Неопределено; //✏
Для Каждого Строка Из Таблица Цикл //⟳
Значение = Строка[ИмяКолонки]; //✏
Если Результат = Неопределено ИЛИ Значение < Результат Тогда //⚡
Результат = Значение; //✏
КонецЕсли;
КонецЦикла;
Возврат Результат; //↩
КонецФункции
/// ✦ Maximum — Максимальное значение колонки
Функция Maximum(Таблица, ИмяКолонки) Экспорт //⚙
Если Таблица.Количество() = 0 Тогда //⚡
Возврат Неопределено; //↩
КонецЕсли;
Результат = Неопределено; //✏
Для Каждого Строка Из Таблица Цикл //⟳
Значение = Строка[ИмяКолонки]; //✏
Если Результат = Неопределено ИЛИ Значение > Результат Тогда //⚡
Результат = Значение; //✏
КонецЕсли;
КонецЦикла;
Возврат Результат; //↩
КонецФункции
#КонецОбласти
#Область МанипуляцияСтроками
//
// Находит первую строку таблицы по значениям колонок. ✦
//
Функция FindRow(Таблица, КолонкиИЗначения) Экспорт //⚙
НайденныеСтроки = Таблица.НайтиСтроки(КолонкиИЗначения); //✏
Если НайденныеСтроки.Количество() > 0 Тогда //⚡
Возврат НайденныеСтроки[0]; //↩
Иначе
Возврат Неопределено; //↩
КонецЕсли;
КонецФункции
//
// Находит все строки таблицы по значениям колонок. ✦
//
Функция Filter(Таблица, КолонкиИЗначения = Неопределено) Экспорт //⚙
Если КолонкиИЗначения = Неопределено Тогда //⚡
Возврат _ТаблицаВМассив(Таблица); //▶️
Иначе
Возврат Таблица.НайтиСтроки(КолонкиИЗначения); //↩
КонецЕсли;
КонецФункции
//
// Сортирует таблицу по указанным колонкам. ✦
//
Функция Sort(Таблица, Колонки) Экспорт //⚙
Таблица.Сортировать(Колонки); //✏
Возврат Таблица; //↩
КонецФункции
#КонецОбласти
#Область МодификацияТаблицы
//
// Очищает все строки таблицы, сохраняя структуру колонок. ✦
//
Функция Clear(Таблица) Экспорт //⚙
Таблица.Очистить(); //✏
Возврат Таблица; //↩
КонецФункции
//
// Удаляет строки таблицы по условию. ✦
//
Функция DeleteRows(Таблица, КолонкиИЗначения) Экспорт //⚙
НайденныеСтроки = Таблица.НайтиСтроки(КолонкиИЗначения); //✏
Счетчик = НайденныеСтроки.Количество(); //✏
Для Каждого Строка Из НайденныеСтроки Цикл //⟳
Таблица.Удалить(Строка); //✏
КонецЦикла;
Возврат Счетчик; //↩
КонецФункции
#КонецОбласти
#Область СериализацияИСанация
//
// Санация данных таблицы для JSON (вызывает A1sDS.Sanitize). ✦
// Таблица значений ➤
// Array — Массив структур ⬅
//
&НаСервере
Функция Sanitize(Знач Таблица) Экспорт
Если ТипЗнч(Таблица) <> Тип("ТаблицаЗначений") Тогда
Возврат Новый Массив;
КонецЕсли;
Возврат A1sDS.Sanitize(Таблица);
КонецФункции
//
// Преобразует таблицу в JSON-строку (с автоматической санацией). ✦
//
&НаСервере
Функция ToJSON(Знач Таблица) Экспорт
Если ТипЗнч(Таблица) <> Тип("ТаблицаЗначений") Тогда
Возврат "[]";
КонецЕсли;
// 1. Очистка данных от 1С-специфики
ЧистыеДанные = A1sDS.Sanitize(Таблица);
// 2. Сериализация
Возврат A1sDS.ToJSON(ЧистыеДанные);
КонецФункции
#КонецОбласти
#Область Преобразование
//
// Преобразует таблицу в массив структур. ✦
//
Функция ToArray(Таблица, Колонки = "") Экспорт //⚙
Результат = Новый Массив; //✏
СписокКолонок = ?(ПустаяСтрока(Колонки), GetColumnNames(Таблица), СтрРазделить(Колонки, ",", Ложь)); //✏
Для Каждого Строка Из Таблица Цикл //⟳
СтруктураСтроки = Новый Структура; //✏
Для Каждого ИмяКолонки Из СписокКолонок Цикл //⟳
ИмяКолонки = СокрЛП(ИмяКолонки); //✏
СтруктураСтроки.Вставить(ИмяКолонки, Строка[ИмяКолонки]); //✏
КонецЦикла;
Результат.Добавить(СтруктураСтроки); //✏
КонецЦикла;
Возврат Результат; //↩
КонецФункции
//
// Получает значения указанной колонки в виде массива. ✦
//
Функция Column(Таблица, ИмяКолонки) Экспорт //⚙
Результат = Новый Массив; //✏
Для Каждого Строка Из Таблица Цикл //⟳
Результат.Добавить(Строка[ИмяКолонки]); //✏
КонецЦикла;
Возврат Результат; //↩
КонецФункции
//
// Выгружает колонку таблицы в массив (алиас для Column). ✦
//
Функция UnloadColumn(Таблица, ИмяКолонки) Экспорт //⚙
Возврат Column(Таблица, ИмяКолонки); //▶️
КонецФункции
#КонецОбласти
#Область АнализИУтилиты
//
// Получает количество строк в таблице. ✦
//
Функция Count(Таблица) Экспорт //⚙
Возврат Таблица.Количество(); //↩
КонецФункции
//
// Проверяет, пуста ли таблица. ✦
//
Функция IsEmpty(Таблица) Экспорт //⚙
Возврат Таблица.Количество() = 0; //↩
КонецФункции
//
// Создает копию таблицы со всеми данными. ✦
//
Функция Copy(Таблица, Колонки = "") Экспорт //⚙
Если ПустаяСтрока(Колонки) Тогда //⚡
Возврат Таблица.Скопировать(); //↩
Иначе
Возврат Таблица.Скопировать(, Колонки); //↩
КонецЕсли;
КонецФункции
//
// Группирует таблицу по указанным колонкам с агрегацией. ✦
//
Функция GroupBy(Таблица, КолонкиГруппировки, КолонкиСуммирования = "") Экспорт //⚙
Если ПустаяСтрока(КолонкиСуммирования) Тогда //⚡
Возврат Таблица.Скопировать(КолонкиГруппировки); //↩
Иначе
Результат = Таблица.Скопировать(); //✏
Результат.Свернуть(КолонкиГруппировки, КолонкиСуммирования); //✏
Возврат Результат; //↩
КонецЕсли;
КонецФункции
//
// Получает список имён всех колонок таблицы. ✦
//
Функция GetColumnNames(Таблица) Экспорт //⚙
Результат = Новый Массив; //✏
Для Каждого Колонка Из Таблица.Колонки Цикл //⟳
Результат.Добавить(Колонка.Имя); //✏
КонецЦикла;
Возврат Результат; //↩
КонецФункции
//
// Проверяет наличие колонки в таблице. ✦
//
Функция HasColumn(Таблица, ИмяКолонки) Экспорт //⚙
Возврат Таблица.Колонки.Найти(ИмяКолонки) <> Неопределено; //↩
КонецФункции
//
// Создает индекс для быстрого поиска по колонкам. ✦
//
Функция CreateIndex(Таблица, Колонки) Экспорт //⚙
Таблица.Индексы.Добавить(Колонки); //✏
Возврат Таблица; //↩
КонецФункции
//
// Объединяет строки из нескольких таблиц в одну (Union All). ✦
//
Функция Union(ЦелеваяТаблица, ДобавляемыеТаблицы) Экспорт //⚙
Для Каждого Таблица Из ДобавляемыеТаблицы Цикл //⟳
Для Каждого Строка Из Таблица Цикл //⟳
ЗаполнитьЗначенияСвойств(ЦелеваяТаблица.Добавить(), Строка); //✏
КонецЦикла;
КонецЦикла;
Возврат ЦелеваяТаблица; //↩
КонецФункции
//
// Применяет функцию-обработчик к каждой строке таблицы. ✦
//
Функция ForEach(Таблица, Обработчик) Экспорт //⚙
Для Каждого Строка Из Таблица Цикл //⟳
Выполнить(Обработчик + "(Строка)"); //▶️
КонецЦикла;
Возврат Таблица; //↩
КонецФункции
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
// Добавляет колонки в таблицу из строкового описания
Процедура _ДобавитьКолонкиИзСтроки(Таблица, СтрокаОписания) //✍
МассивКолонок = СтрРазделить(СтрокаОписания, ",", Ложь); //✏
Для Каждого ОписаниеКолонки Из МассивКолонок Цикл //⟳
ОписаниеКолонки = СокрЛП(ОписаниеКолонки); //✏
Если СтрНайти(ОписаниеКолонки, ":") > 0 Тогда //⚡
ЧастиОписания = СтрРазделить(ОписаниеКолонки, ":", Ложь); //✏
ИмяКолонки = СокрЛП(ЧастиОписания[0]); //✏
ИмяТипа = СокрЛП(ЧастиОписания[1]); //✏
ТипКолонки = _ПолучитьТипПоИмени(ИмяТипа); //▶️
Таблица.Колонки.Добавить(ИмяКолонки, ТипКолонки); //✏
Иначе
Таблица.Колонки.Добавить(ОписаниеКолонки); //✏
КонецЕсли;
КонецЦикла;
КонецПроцедуры
// Добавляет колонки в таблицу из структуры
Процедура _ДобавитьКолонкиИзСтруктуры(Таблица, Структура) //✍
Для Каждого КлючЗначение Из Структура Цикл //⟳
ИмяКолонки = КлючЗначение.Ключ; //✏
Если ТипЗнч(КлючЗначение.Значение) = Тип("Строка") Тогда //⚡
ТипКолонки = _ПолучитьТипПоИмени(КлючЗначение.Значение); //▶️
Таблица.Колонки.Добавить(ИмяКолонки, ТипКолонки); //✏
ИначеЕсли ТипЗнч(КлючЗначение.Значение) = Тип("ОписаниеТипов") Тогда //⚡
Таблица.Колонки.Добавить(ИмяКолонки, КлючЗначение.Значение); //✏
Иначе
Таблица.Колонки.Добавить(ИмяКолонки); //✏
КонецЕсли;
КонецЦикла;
КонецПроцедуры
// Добавляет строку в таблицу с заполнением значений
Процедура _ДобавитьСтрокуВТаблицу(Таблица, ДанныеСтроки) //✍
НоваяСтрока = Таблица.Добавить(); //✏
Если ТипЗнч(ДанныеСтроки) = Тип("Структура") Тогда //⚡
ЗаполнитьЗначенияСвойств(НоваяСтрока, ДанныеСтроки); //✏
ИначеЕсли ТипЗнч(ДанныеСтроки) = Тип("Массив") Тогда //⚡
_ЗаполнитьСтрокуИзМассива(НоваяСтрока, ДанныеСтроки); //▶️
КонецЕсли;
КонецПроцедуры
// Заполняет строку таблицы значениями из массива по порядку
Процедура _ЗаполнитьСтрокуИзМассива(Строка, МассивЗначений) //✍
Владелец = Строка.Владелец(); //✏
Индекс = 0; //✏
Для Каждого Колонка Из Владелец.Колонки Цикл //⟳
Если Индекс < МассивЗначений.Количество() Тогда //⚡
Строка[Колонка.Имя] = МассивЗначений[Индекс]; //✏
Индекс = Индекс + 1; //✏
КонецЕсли;
КонецЦикла;
КонецПроцедуры
// Возвращает описание типа по его имени
Функция _ПолучитьТипПоИмени(ИмяТипа) Экспорт //✍
ИмяТипа = ВРег(СокрЛП(ИмяТипа)); //✏
Если ИмяТипа = "СТРОКА" ИЛИ ИмяТипа = "STRING" Тогда //⚡
Возврат Новый ОписаниеТипов("Строка"); //↩
ИначеЕсли ИмяТипа = "ЧИСЛО" ИЛИ ИмяТипа = "NUMBER" Тогда //⚡
Возврат Новый ОписаниеТипов("Число"); //↩
ИначеЕсли ИмяТипа = "ДАТА" ИЛИ ИмяТипа = "DATE" Тогда //⚡
Возврат Новый ОписаниеТипов("Дата"); //↩
ИначеЕсли ИмяТипа = "БУЛЕВО" ИЛИ ИмяТипа = "BOOLEAN" Тогда //⚡
Возврат Новый ОписаниеТипов("Булево"); //↩
Иначе
Попытка //⚡
Возврат Новый ОписаниеТипов(ИмяТипа); //↩
Исключение
Возврат Новый ОписаниеТипов; //↩
КонецПопытки;
КонецЕсли;
КонецФункции
// Получает массив имён колонок таблицы
Функция _ПолучитьИменаКолонок(Таблица) //✍
Результат = Новый Массив; //✏
Для Каждого Колонка Из Таблица.Колонки Цикл //⟳
Результат.Добавить(Колонка.Имя); //✏
КонецЦикла;
Возврат Результат; //↩
КонецФункции
// Преобразует таблицу в массив строк
Функция _ТаблицаВМассив(Таблица) //✍
Результат = Новый Массив; //✏
Для Каждого Строка Из Таблица Цикл //⟳
Результат.Добавить(Строка); //✏
КонецЦикла;
Возврат Результат; //↩
КонецФункции
Функция _ПолучитьОписаниеТипаДляЗначения(Значение, МассивПроверки = Неопределено)
ОписаниеТипа = Неопределено;
Если Значение = Неопределено Тогда
Возврат Новый ОписаниеТипов("Строка");
КонецЕсли;
ТипЗначения = ТипЗнч(Значение);
Если ТипЗначения = Тип("Строка") Тогда
Возврат Новый ОписаниеТипов("Строка");
ИначеЕсли ТипЗначения = Тип("Число") Тогда
ЕстьОтрицательные = Ложь;
Если МассивПроверки <> Неопределено Тогда
// ИСПРАВЛЕНИЕ: Перебираем все свойства структуры, так как мы не знаем точное имя колонки.
// Если в таблице есть хотя бы одно отрицательное число в любой колонке,
// мы разрешаем отрицательные значения для всех числовых колонок ради безопасности.
Для Каждого Строка Из МассивПроверки Цикл
Для Каждого КлючИЗначение Из Строка Цикл
ЗначениеПоля = КлючИЗначение.Значение;
Если ТипЗнч(ЗначениеПоля) = Тип("Число") И ЗначениеПоля < 0 Тогда
ЕстьОтрицательные = Истина;
Прервать;
КонецЕсли;
КонецЦикла;
Если ЕстьОтрицательные Тогда
Прервать;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Если ЕстьОтрицательные Тогда
Возврат Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2, ДопустимыйЗнак.Любой));
Иначе
Возврат Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2, ДопустимыйЗнак.Неотрицательный));
КонецЕсли;
ИначеЕсли ТипЗначения = Тип("Дата") Тогда
Возврат Новый ОписаниеТипов("Дата");
ИначеЕсли ТипЗначения = Тип("Булево") Тогда
Возврат Новый ОписаниеТипов("Булево");
ИначеЕсли ТипЗначения = Тип("УникальныйИдентификатор") Тогда
Возврат Новый ОписаниеТипов("УникальныйИдентификатор");
Иначе
// Для прочих типов (ссылки, etc.) используем строку как наиболее универсальный вариант.
Возврат Новый ОписаниеТипов("Строка");
КонецЕсли;
КонецФункции
#КонецОбласти
#Область FluentInterface
//
// Создаёт fluent-обёртку для работы с таблицами значений. ✦
//
&НаСервере
Функция On(Знач Исходная = Неопределено) Экспорт //⚙
Обработка = Обработки.A1sDP_VT.Создать();
Обработка.Init(Исходная);
Возврат Обработка; //↩
КонецФункции
#КонецОбласти
#Область Тестирование
//
// Выполняет автоматическое тестирование всех функций модуля A1sVT. ✦
// Boolean — Истина если все тесты прошли успешно ⬅
//
Функция SelfTest() Экспорт //⚙
TestsTotal = 0; //✏
TestsPassed = 0; //✏
Сообщить("=== Запуск тестирования A1sVT ===");
// Тест 1: Создание таблицы из строки с типами
TestsTotal = TestsTotal + 1; //✏
Попытка
Таб1 = Of("Код:Строка,Наименование:Строка,Цена:Число"); //▶️
Если Count(Таб1) = 0 И HasColumn(Таб1, "Код") И HasColumn(Таб1, "Цена") Тогда //⚡
TestsPassed = TestsPassed + 1; //✏
Сообщить("✓ Тест 1 (Of с типами): ПРОЙДЕН");
Иначе
Сообщить("✗ Тест 1 (Of с типами): ПРОВАЛЕН");
КонецЕсли;
Исключение
Сообщить("✗ Тест 1 (Of с типами): ОШИБКА - " + ОписаниеОшибки());
КонецПопытки;
// Тест 2: Добавление строк
TestsTotal = TestsTotal + 1; //✏
Попытка
Таб2 = OfColumns("Товар,Количество:Число"); //▶️
AddRow(Таб2, Новый Структура("Товар,Количество", "Молоко", 5)); //▶️
МассивЗначений = Новый Массив; //✏
МассивЗначений.Добавить("Хлеб"); //✏
МассивЗначений.Добавить(3); //✏
AddRow(Таб2, МассивЗначений); //▶️
Если Count(Таб2) = 2 Тогда //⚡
TestsPassed = TestsPassed + 1; //✏
Сообщить("✓ Тест 2 (AddRow): ПРОЙДЕН");
Иначе
Сообщить("✗ Тест 2 (AddRow): ПРОВАЛЕН");
КонецЕсли;
Исключение
Сообщить("✗ Тест 2 (AddRow): ОШИБКА - " + ОписаниеОшибки());
КонецПопытки;
// Итоги тестирования
Если TestsPassed = TestsTotal Тогда //⚡
Сообщить("=== A1sVT.SelfTest() SUCCESS: " + Строка(TestsPassed) + "/" + Строка(TestsTotal) + " ===");
Возврат Истина; //↩
Иначе
Сообщить("=== A1sVT.SelfTest() FAILED: " + Строка(TestsPassed) + "/" + Строка(TestsTotal) + " ===");
Возврат Ложь; //↩
КонецЕсли;
КонецФункции
#КонецОбласти
////////////////////////////////////////////////////////////////////////////////
// МОДУЛЬ ЗАВЕРШЕН - A1sVT v2.1.0
////////////////////////////////////////////////////////////////////////////////