Справочник A1sCode
Зачем: быстрые паттерны на базе A1sQ (запросы) и A1sS (строки/шаблоны/вывод). Клик по коду — копирование.
Обзор модулей
- A1sQ — короткие вызовы для Запроса (шаблоны, параметры, извлечение значений).
- A1sS — строки/форматирование/шаблоны/вывод (AsString, Join, шаблон‑builder, Print*).
A1sQ: самое нужное
TL;DR:
ValueQ() — вместо «QT → ExecuteQ → FirstRow».
// Получить одно значение по параметру
Значение = A1sQ.ValueQ(
"ПЕРВЫЕ 1 Ссылка, Наименование ИЗ Справочник.Пользователи ГДЕ ИдентификаторПользователяИБ = &UID",
Новый Структура("UID", ПользователиИнформационнойБазы.ТекущийПользователь().УникальныйИдентификатор),
"Наименование"); // ключ поля (или 1-й столбец, если не указан)
// Массив значений (1 столбец)
Список = A1sQ.ValuesQ(
"ВЫБРАТЬ Наименование ИЗ Справочник.Номенклатура ГДЕ ПометкаУдаления = &F",
Новый Структура("F", Ложь));
// ТаблицаЗначений целиком
Таб = A1sQ.Unload( A1sQ.ExecuteQ( A1sQ.QT("ВЫБРАТЬ ПЕРВЫЕ 50 Ссылка, Наименование ИЗ Справочник.Номенклатура ПОРЯДОК ПО Наименование") ) );
Параметры: передавайте через
Структуру, имена «&Парам» в тексте запроса должны совпадать.
A1sS: строки и формат
// Универсальное приведение к строке с масками
Опции = Новый Структура("NumberFormat,DateFormat", "ЧГ=0; ЧД=2; N=,; T= ", "ДФ=dd.MM.yyyy");
Текст = A1sS.AsString(12345.6, Опции); // "12 345,60" (пример)
Текст = A1sS.ToAnyReadable(МассивЗначений); // "[...]" удобное представление
// Join / Replace / Wrap / Normalize
Список = Новый Массив; Список.Добавить("R"); Список.Добавить("G"); Список.Добавить("B");
A1sS.Join(Список, ", "); // "R, G, B"
A1sS.ReplaceText("контракт, контрактор", "контракт", "договор", Новый Структура("WholeWord", Истина));
A1sS.Wrap("текст", "[", "]"); // "[текст]"
A1sS.NormalizeWhitespace(" Привет мир "); // "Привет мир"
A1sS: шаблоны
// Быстрый текст с подстановкой {{Ключ}}
Парам = Новый Структура("Имя,Баланс", "Иван", 123.45);
A1sS.AddTextToTemplate("Клиент: {{Имя}}, баланс: {{Баланс}} ₽", Парам);
// Builder-подход
B = A1sS.CreateTemplateBuilder();
A1sS.AddTextToTemplate("Заголовок", Неопределено, "— ", " —");
A1sS.AddTextToTemplate("Список: {{Список}}", Новый Структура("Список", A1sS.Join(Список, ", ")));
Результат = B.ToString(); // или A1sS.GetTemplate()
// Полная обработка шаблона
Tpl = "Товар: {{Имя}} ({{Цена}} ₽)";
A1sS.ProcessTemplate(Tpl, Новый Структура("Имя,Цена", "Яблоко", 10));
Вывод / печать / сериализация
A1sS.Print("Старт процедуры");
A1sS.PrintYN(Проверка()); // Да/Нет
A1sS.PrintJSON(МояСтруктура); // Красиво отформатированный JSON
A1sS.PrintXML(МойОбъект); // XML‑вывод
Проверки и утилиты
Если A1sS.IsValidURL("https://a1scode.ru") Тогда
// ...
КонецЕсли;
Если A1sS.HasText(Стр) Тогда
// не пустая/не пробельная строка
КонецЕсли;
Ошибки и «дымовая» проверка
Рекомендация: оборачивайте рабочие примеры в Попытка/Исключение; добавьте короткий self‑test.
Процедура SmokeTestA1s() Экспорт
Попытка
Assert = Новый Массив;
Assert.Добавить(A1sS.Join(Новый Массив, ", ") = "");
Assert.Добавить(A1sS.IsValidURL("https://example.com"));
Для Каждого Ок Из Assert Цикл
Если Ок = Ложь Тогда ВызватьИсключение "Smoke failed"; КонецЕсли;
КонецЦикла;
A1sS.Print("Smoke OK");
Исключение
A1sS.Print("Smoke FAIL: " + ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
Расширенные примеры
A1sQ: временные таблицы
ТекстЗапроса =
"ВЫБРАТЬ
| Ном.Ссылка КАК Товар,
| Сумма(Обороты.Количество) КАК Количество
|ПОМЕСТИТЬ ВТОбороты
|ИЗ РегистрНакопления.ОстаткиТоваров.Обороты(&ДатаНач, &ДатаКон, , ) КАК Обороты
| ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Ном
| ПО Обороты.Номенклатура = Ном.Ссылка
|СГРУППИРОВАТЬ ПО
| Ном.Ссылка;
|
|ВЫБРАТЬ ПЕРВЫЕ 20
| Товар,
| Количество
|ИЗ ВТОбороты
|ГДЕ Количество > 0
|УПОРЯДОЧИТЬ ПО Количество УБЫВ";
Таб = A1sQ.Unload( A1sQ.ExecuteQ( A1sQ.QT(ТекстЗапроса), Новый Структура("ДатаНач,ДатаКон", НачалоДня(Нач), КонецДня(Кон)) ) );
A1sQ: параметры дат и диапазоны
Текст =
"ВЫБРАТЬ
| Дата, Ссылка, Наименование
|ИЗ Документ.ЗаказПокупателя КАК Дк
|ГДЕ Дк.Дата МЕЖДУ &Нач И &Кон
|И Дк.Проведен
|УПОРЯДОЧИТЬ ПО Дата УБЫВ";
Парам = Новый Структура("Нач,Кон", НачалоДня(ТекущаяДата() - 7), КонецДня(ТекущаяДата()));
Таб = A1sQ.Unload( A1sQ.ExecuteQ( A1sQ.QT(Текст), Парам ) );
Логи: ToAnyReadable + NormalizeWhitespace
Процедура ЛогСобытие(Контекст) Экспорт
// Читабельное представление + нормализация пробелов/переводов
СтрЛог = A1sS.ToAnyReadable(Контекст, Новый Структура("MaxLen", 2000));
СтрЛог = A1sS.NormalizeWhitespace(СтрЛог);
A1sS.Print("[LOG] " + СтрЛог);
КонецПроцедуры
Мини‑демо: smoke после деплоя
Зачем: убедиться, что базовые хелперы работают на вашем стенде.
Процедура SmokeTestA1sCode() Экспорт
Попытка
// 1) Строковые утилиты
Текст = A1sS.Join(Новый Массив("A", "B", "C"), ", ");
Если Текст <> "A, B, C" Тогда ВызватьИсключение "Join"; КонецЕсли;
// 2) Валидация
Если Не A1sS.IsValidURL("https://example.com") Тогда ВызватьИсключение "IsValidURL"; КонецЕсли;
// 3) Запрос (таблица не пустая или без ошибки)
Таб = A1sQ.Unload( A1sQ.ExecuteQ( A1sQ.QT("ВЫБРАТЬ ПЕРВЫЕ 1 Ссылка ИЗ Справочник.Пользователи") ) );
Если Таб.Количество() = 0 Тогда A1sS.Print("Внимание: нет пользователей"); КонецЕсли;
A1sS.Print("Smoke OK");
Исключение
A1sS.Print("Smoke FAIL: " + ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
JSON / XML: round‑trip
Идея: сериализуем структуру в строку и читаем обратно. Удобно для логов/кэша/обмена.
// JSON → строка → объект
Данные = Новый Структура("Имя,Сумма,Состав",
"Счёт 42", 123.45, Новый Массив("A","B","C"));
// Запись в строку
Зап = Новый ЗаписьJSON; Зап.УстановитьСтроку();
ЗаписатьJSON(Зап, Данные);
JSONСтрока = Зап.Закрыть();
// Чтение обратно
Чт = Новый ЧтениеJSON; Чт.УстановитьСтроку(JSONСтрока);
Клон = ПрочитатьJSON(Чт);
// Проверка
A1sS.PrintJSON(Клон);
// XML: общий паттерн (если тип поддерживает сериализацию в XML)
ЗапXML = Новый ЗаписьXML; ЗапXML.УстановитьСтроку();
ЗаписатьXML(ЗапXML, Данные); // для соответствующих типов/схем
XMLСтрока = ЗапXML.Закрыть();
ЧтXML = Новый ЧтениеXML; ЧтXML.УстановитьСтроку(XMLСтрока);
КлонXML = ПрочитатьXML(ЧтXML);
A1sS.PrintXML(КлонXML);
Regex‑утилиты A1sS
Подсказка: используйте флаги (например,
(?i) для безрегистрового) прямо в шаблоне, если поддерживается.
// Соответствие шаблону
Если A1sS.RegexMatch("abc-123", "^[a-z]+-\d+$") Тогда
// ok
КонецЕсли;
// Замена чисел на # (везде)
Текст = A1sS.RegexReplace("a1 b22 c333", "\d+", "#"); // "a# b# c#"
// Разбиение по запятым/точкам с запятой + пробелам
Части = A1sS.RegexSplit("a, b; c", "[,;]\s*"); // ["a","b","c"]
Мини‑ORM на базе ValueQ/ValuesQ
Цель: компактные «репозитории» — функции, возвращающие структуры/массивы/таблицы.
Пользователь по UID
Функция Repo_ПользовательПоUID(UID) Экспорт
Текст = "ВЫБРАТЬ ПЕРВЫЕ 1 Ссылка ИЗ Справочник.Пользователи
ГДЕ ИдентификаторПользователяИБ = &UID";
Ссылка = A1sQ.ValueQ(Текст, Новый Структура("UID", UID), "Ссылка");
Если Ссылка = Неопределено Тогда Возврат Неопределено; КонецЕсли;
// Детали
Текст2 = "ВЫБРАТЬ Наименование ИЗ Справочник.Пользователи ГДЕ Ссылка = &Ссылка";
Имя = A1sQ.ValueQ(Текст2, Новый Структура("Ссылка", Ссылка), "Наименование");
Возврат Новый Структура("Ссылка,Имя", Ссылка, Имя);
КонецФункции
ТОП‑товары для отчёта
Функция Repo_ТопНоменклатуры(Лимит = 20) Экспорт
Текст = "ВЫБРАТЬ ПЕРВЫЕ &N Ссылка, Наименование
ИЗ Справочник.Номенклатура
ПОРЯДОК ПО Наименование";
Парам = Новый Структура("N", Лимит);
Возврат A1sQ.Unload( A1sQ.ExecuteQ( A1sQ.QT(Текст), Парам ) );
КонецФункции
Upsert‑паттерн (найти/создать)
Замечание: создание объектов делайте транзакционно, проверяйте уникальные ключи.
Функция Repo_ПолучитьИлиСоздатьНоменклатуру(Имя) Экспорт
Ссылка = A1sQ.ValueQ(
"ВЫБРАТЬ ПЕРВЫЕ 1 Ссылка ИЗ Справочник.Номенклатура ГДЕ Наименование = &Имя",
Новый Структура("Имя", Имя),
"Ссылка");
Если Ссылка <> Неопределено Тогда Возврат Ссылка; КонецЕсли;
// Создание
Объект = Справочники.Номенклатура.СоздатьЭлемент();
Объект.Наименование = Имя;
Объект.Записать();
Возврат Объект.Ссылка;
КонецФункции
JSON → плоская структура
Зачем: удобно логировать и экспортировать ключевые поля без вложенности.
Функция JSONПлоско(JSONСтрока) Экспорт
Ч = Новый ЧтениеJSON; Ч.УстановитьСтроку(JSONСтрока);
Д = ПрочитатьJSON(Ч);
Р = Новый Структура;
_JSONПлоскоВнутр("", Д, Р);
Возврат Р;
КонецФункции
Процедура _JSONПлоскоВнутр(Префикс, Знач, Рез) Экспорт
Если ТипЗнч(Знач) = Тип("Структура") Тогда
Для Каждого П Из Знач Цикл
Ключ = П.Ключ;
Имя = ?(Префикс = "", Ключ, Префикс + "." + Ключ);
_JSONПлоскоВнутр(Имя, П.Значение, Рез);
КонецЦикла;
ИначеЕсли ТипЗнч(Знач) = Тип("Соответствие") Тогда
Для Каждого К Из Знач.Ключи() Цикл
Имя = ?(Префикс = "", К, Префикс + "." + К);
_JSONПлоскоВнутр(Имя, Знач.Получить(К), Рез);
КонецЦикла;
ИначеЕсли ТипЗнч(Знач) = Тип("Массив") Тогда
Для И = 0 По Знач.Количество()-1 Цикл
Имя = ?(Префикс = "", Строка(И), Префикс + "[" + Строка(И) + "]");
_JSONПлоскоВнутр(Имя, Знач[И], Рез);
КонецЦикла;
Иначе
Рез.Вставить(Префикс, Знач);
КонецЕсли;
КонецПроцедуры
Regex: именованные группы
Важно: именованные группы работают, если ваш движок регулярок их поддерживает.
В A1sS используйте расширенный метод (если есть), иначе — стандартные средства платформы.
В A1sS используйте расширенный метод (если есть), иначе — стандартные средства платформы.
// Вариант через расширение A1sS (если доступно):
Совп = A1sS.RegexMatchEx("email: john@example.com", "(?i)(?[a-z0-9._%+-]+)@(?[a-z0-9.-]+\.[a-z]{2,})");
Если Совп.Нашлось Тогда
Пользователь = Совп.Группы["user"];
Хост = Совп.Группы["host"];
КонецЕсли;
// Или классическая нумерация групп с последующей раскладкой:
Если A1sS.RegexMatch("john@example.com", "^([a-z0-9._%+-]+)@([a-z0-9.-]+\.[a-z]{2,})$") Тогда
Части = A1sS.RegexExtract("john@example.com", "^([a-z0-9._%+-]+)@([a-z0-9.-]+\.[a-z]{2,})$");
Пользователь = Части[0]; // первая группа
Хост = Части[1]; // вторая группа
КонецЕсли;
Экспорт отчёта: CSV / Excel
CSV: кроссплатформенно и быстро. Excel: через COM‑автоматизацию (Windows, толстый клиент).
Процедура ExportCSV(Таблица, Путь = "report.csv", Разделитель = ";") Экспорт
П = Новый ЗаписьТекста(Путь, КодировкаТекста.UTF8);
// Заголовок
Заг = Новый Массив;
Для Каждого К Из Таблица.Колонки Цикл
Заг.Добавить(К.Имя);
КонецЦикла;
П.ЗаписатьСтроку(A1sS.Join(Заг, Разделитель));
// Строки
Для Каждого Р Из Таблица Цикл
М = Новый Массив;
Для Каждого К Из Таблица.Колонки Цикл
М.Добавить(A1sS.AsString(Р[К.Имя]));
КонецЦикла;
П.ЗаписатьСтроку(A1sS.Join(М, Разделитель));
КонецЦикла;
П.Закрыть();
КонецПроцедуры
Excel (COM): только Windows и толстый клиент. Следите за закрытием Excel‑процесса.
Процедура ExportXLSX(Таблица, ПутьXLSX = "report.xlsx") Экспорт
#Если Клиент Тогда
ВызватьИсключение "Экспорт XLSX доступен на сервере/тонком клиенте Windows";
#КонецЕсли
Эксель = Новый COMОбъект("Excel.Application");
Книга = Эксель.Workbooks.Add();
Лист = Книга.ActiveSheet;
// Заголовок
Кол = 1;
Для Каждого К Из Таблица.Колонки Цикл
Лист.Cells(1, Кол).Value = К.Имя;
Кол = Кол + 1;
КонецЦикла;
// Данные
СтрНом = 2;
Для Каждого Р Из Таблица Цикл
Кол = 1;
Для Каждого К Из Таблица.Колонки Цикл
Лист.Cells(СтрНом, Кол).Value = Р[К.Имя];
Кол = Кол + 1;
КонецЦикла;
СтрНом = СтрНом + 1;
КонецЦикла;
Книга.SaveAs(ПутьXLSX);
Книга.Close();
Эксель.Quit();
КонецПроцедуры
Отчёт → ТабличныйДокумент (минимальный шаблон)
Идея: быстро собрать печатный документ без макета. Потом легко заменить на макет.
&НаКлиенте
Процедура ПоказатьОтчет(Команда)
Таб = A1sQ.Unload( A1sQ.ExecuteQ( A1sQ.QT("ВЫБРАТЬ ПЕРВЫЕ 20 Ссылка, Наименование ИЗ Справочник.Номенклатура ПОРЯДОК ПО Наименование") ) );
ТД = ПостроитьТабДок(Таб, "Топ-20 номенклатуры");
ТД.Показать();
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПостроитьТабДок(Таблица, Заголовок) Экспорт
ТД = Новый ТабличныйДокумент;
ТД.Вывести(Заголовок);
ТД.Вывести("");
// Шапка
СтрЗаг = "";
Для Каждого К Из Таблица.Колонки Цикл
СтрЗаг = СтрЗаг + ?(СтрЗаг = "", "", "; ") + К.Имя;
КонецЦикла;
ТД.Вывести(СтрЗаг);
// Строки
Для Каждого Р Из Таблица Цикл
М = Новый Массив;
Для Каждого К Из Таблица.Колонки Цикл
М.Добавить(A1sS.AsString(Р[К.Имя]));
КонецЦикла;
ТД.Вывести(A1sS.Join(М, "; "));
КонецЦикла;
Возврат ТД;
КонецФункции
Замечание: для контроля ширин/шрифтов/границ используйте макет и Области макета.
Пагинация / батч‑выборки (seek‑метод)
Надёжно: вместо смещений используйте «продолжить после ключа» (по возрастанию).
Функция ПеребратьНоменклатуруПакетами(Пакет = 500) Экспорт
Последняя = Неопределено;
Пока Истина Цикл
Текст = "ВЫБРАТЬ ПЕРВЫЕ &N Ссылка, Наименование
ИЗ Справочник.Номенклатура
ГДЕ (&Last ЕСТЬ NULL) ИЛИ (Ссылка > &Last)
ПОРЯДОК ПО Ссылка";
Парам = Новый Структура("N,Last", Пакет, Последняя);
Таб = A1sQ.Unload( A1sQ.ExecuteQ( A1sQ.QT(Текст), Парам ) );
Если Таб.Количество() = 0 Тогда
Прервать;
КонецЕсли;
// Обработка пакета
Для Каждого Р Из Таб Цикл
// ... делаем дело ...
КонецЦикла;
// Сдвигаем маркер
Последняя = Таб[Таб.Количество()-1].Ссылка;
КонецЦикла;
Возврат Истина;
КонецФункции
Важно: «seek» устойчив к вставкам/удалениям между итерациями, в отличие от пагинации по смещению.
Мини‑валидатор схемы JSON (структуры)
Схема: Соответствие вида {Ключ: "Тип" | ВложеннаяСхема | МассивТипов}. Проверка — рекурсивная.
Функция ТипOK(Знч, ИмяТипа) Экспорт
В = СтрЗаменить(СтрЗаглавныеБуквы(НРег(ИмяТипа)), " ", "");
Возврат
(В = "Строка" И ТипЗнч(Знч) = Тип("Строка")) ИЛИ
(В = "Число" И ТипЗнч(Знч) = Тип("Число")) ИЛИ
(В = "Дата" И ТипЗнч(Знч) = Тип("Дата")) ИЛИ
(В = "Булево" И ТипЗнч(Знч) = Тип("Булево")) ИЛИ
(В = "Структура" И ТипЗнч(Знч) = Тип("Структура")) ИЛИ
(В = "Соответствие" И ТипЗнч(Знч) = Тип("Соответствие")) ИЛИ
(В = "Массив" И ТипЗнч(Знч) = Тип("Массив"));
КонецФункции
Процедура JSONПроверитьПоСхеме(Данные, Схема, Ошибки) Экспорт
// Ошибки — Массив строк
Для Каждого К Из Схема.Ключи() Цикл
Ожидаем = Схема.Получить(К);
Есть = Неопределено;
Если ТипЗнч(Данные) = Тип("Структура") Тогда
Есть = Данные.Свойство(К);
ИначеЕсли ТипЗнч(Данные) = Тип("Соответствие") Тогда
Есть = Данные.Содержит(К);
КонецЕсли;
Если Не Есть Тогда
Ошибки.Добавить("Нет ключа: " + К);
Продолжить;
КонецЕсли;
Значение = ?(ТипЗнч(Данные) = Тип("Структура"), Данные[К], Данные.Получить(К));
// Варианты правил
Если ТипЗнч(Ожидаем) = Тип("Строка") Тогда
Если Не ТипOK(Значение, Ожидаем) Тогда
Ошибки.Добавить("Тип поля " + К + " != " + Ожидаем);
КонецЕсли;
ИначеЕсли ТипЗнч(Ожидаем) = Тип("Соответствие") Тогда
JSONПроверитьПоСхеме(Значение, Ожидаем, Ошибки);
ИначеЕсли ТипЗнч(Ожидаем) = Тип("Массив") Тогда
// массив допустимых типов
Подходит = Ложь;
Для Каждого ИмяТипа Из Ожидаем Цикл
Если ТипOK(Значение, ИмяТипа) Тогда Подходит = Истина; Прервать; КонецЕсли;
КонецЦикла;
Если Не Подходит Тогда
Ошибки.Добавить("Поле " + К + " не соответствует одному из типов: " + A1sS.Join(Ожидаем, ", "));
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
// Пример использования
Схема = Новый Соответствие;
Схема.Вставить("Имя", "Строка");
Схема.Вставить("Дата", "Дата");
Схема.Вставить("Сумма", "Число");
Схема.Вставить("Состав", Новый Массив("Массив","Структура"));
Ошибки = Новый Массив;
JSONПроверитьПоСхеме(Новый Структура("Имя,Дата,Сумма,Состав", "Заказ", ТекущаяДата(), 123.45, Новый Массив), Схема, Ошибки);
Если Ошибки.Количество() > 0 Тогда
A1sS.Print("Проблемы: " + A1sS.Join(Ошибки, "; "));
Иначе
A1sS.Print("OK");
КонецЕсли;
ТабличныйДокумент по макету (Области)
Шаблон макета: создайте ОбщийМакет ОтчетНоменклатура с областями:
Шапка, Строка, Итог.
&НаСервереБезКонтекста
Функция ПостроитьТабДокПоМакету(Таблица) Экспорт
Макет = ОбщийМакет("ОтчетНоменклатура");
ОблШапка = Макет.ПолучитьОбласть("Шапка");
ОблСтрока = Макет.ПолучитьОбласть("Строка");
ОблИтог = Макет.ПолучитьОбласть("Итог");
ТД = Новый ТабличныйДокумент;
// Шапка
ТД.Вывести(ОблШапка);
// Строки
Для Каждого Р Из Таблица Цикл
ОблСтрока.Параметры.Очистить();
Для Каждого К Из Таблица.Колонки Цикл
ОблСтрока.Параметры.Вставить(К.Имя, Р[К.Имя]);
КонецЦикла;
ТД.Вывести(ОблСтрока);
КонецЦикла;
// Итог
ОблИтог.Параметры.Вставить("Количество", Таблица.Количество());
ТД.Вывести(ОблИтог);
Возврат ТД;
КонецФункции
Экспорт ТабличногоДокумента в HTML / PDF
Важно: поддержка PDF зависит от версии платформы и установленного конвертера. Всегда делайте проверку и отлавливайте исключения.
Процедура СохранитьТД(ТД, ПутьHTML = "report.html", ПутьPDF = "report.pdf") Экспорт
Попытка
// HTML — как правило, доступен из коробки
ТД.Записать(ПутьHTML, ФорматТабличногоДокумента.HTML);
Исключение
A1sS.Print("HTML export failed: " + ОписаниеОшибки());
КонецПопытки;
Попытка
// PDF — при наличии поддержки в вашей версии/сборке
ТД.Записать(ПутьPDF, ФорматТабличногоДокумента.PDF);
Исключение
A1sS.Print("PDF export not available: " + ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
Пагинация по составному ключу (Дата + Ссылка)
Порядок: сортируем по (Дата, Ссылка); берём записи «строго после» последней пары.
Процедура ОбойтиДокументыПакетами(Пакет = 500) Экспорт
ПоследДата = Дата("00010101");
ПоследСсылка = Неопределено;
Пока Истина Цикл
Текст =
"ВЫБРАТЬ ПЕРВЫЕ &N
| Дата, Ссылка, Номер
|ИЗ Документ.ЗаказПокупателя
|ГДЕ (Дата > &D) ИЛИ (Дата = &D И Ссылка > &R)
|УПОРЯДОЧИТЬ ПО Дата, Ссылка";
Парам = Новый Структура("N,D,R", Пакет, ПоследДата, ПоследСсылка);
Таб = A1sQ.Unload( A1sQ.ExecuteQ( A1sQ.QT(Текст), Парам ) );
Если Таб.Количество() = 0 Тогда Прервать; КонецЕсли;
// обработка
Для Каждого Р Из Таб Цикл
// ...
КонецЦикла;
// сдвинуть маркер
ПоследДата = Таб[Таб.Количество()-1].Дата;
ПоследСсылка = Таб[Таб.Количество()-1].Ссылка;
КонецЦикла;
КонецПроцедуры
JSON‑схема 2.0: required / enum / диапазоны / pattern
Схема: Соответствие {Ключ: Структура("type,required,enum,min,max,pattern", ...)}.
Процедура JSONПроверитьПоСхемеV2(Данные, Схема, Ошибки, Путь = "") Экспорт
Для Каждого П Из Схема Цикл
Ключ = П.Ключ; Прав = П.Значение;
ИмяПоля = ?(Путь = "", Ключ, Путь + "." + Ключ);
// required
Есть = Ложь; Знач = Неопределено;
Если ТипЗнч(Данные) = Тип("Структура") Тогда
Есть = Данные.Свойство(Ключ, Знач);
ИначеЕсли ТипЗнч(Данные) = Тип("Соответствие") Тогда
Есть = Данные.Содержит(Ключ); Если Есть Тогда Знач = Данные.Получить(Ключ); КонецЕсли;
КонецЕсли;
Если Прав.Свойство("required") И Прав.required И Не Есть Тогда
Ошибки.Добавить("Требуется поле: " + ИмяПоля); Продолжить;
КонецЕсли;
Если Не Есть Тогда Продолжить;
// type (строка или массив допустимых типов)
ДопТипы = ?(ТипЗнч(Прав.type) = Тип("Массив"), Прав.type, Новый Массив(Прав.type));
Подходит = Ложь;
Для Каждого ИмяТипа Из ДопТипы Цикл
Если ТипOK(Знач, ИмяТипа) Тогда Подходит = Истина; Прервать; КонецЕсли;
КонецЦикла;
Если Не Подходит Тогда
Ошибки.Добавить("Тип " + ИмяПоля + " не входит в: " + A1sS.Join(ДопТипы, ", "));
Продолжить;
КонецЕсли;
// enum
Если Прав.Свойство("enum") Тогда
ЕстьЛи = Ложь;
Для Каждого Вариант Из Прав.enum Цикл
Если Знач = Вариант Тогда ЕстьЛи = Истина; Прервать; КонецЕсли;
КонецЦикла;
Если Не ЕстьЛи Тогда
Ошибки.Добавить("Поле " + ИмяПоля + " не из допустимых: " + A1sS.Join(Прав.enum, ", "));
КонецЕсли;
КонецЕсли;
// min/max для чисел и дат
Если Прав.Свойство("min") Тогда
Если Знач < Прав.min Тогда Ошибки.Добавить("Поле " + ИмяПоля + " < min"); КонецЕсли;
КонецЕсли;
Если Прав.Свойство("max") Тогда
Если Знач > Прав.max Тогда Ошибки.Добавить("Поле " + ИмяПоля + " > max"); КонецЕсли;
КонецЕсли;
// pattern для строк
Если Прав.Свойство("pattern") Тогда
Если Не A1sS.RegexMatch(A1sS.AsString(Знач), Прав.pattern) Тогда
Ошибки.Добавить("Поле " + ИмяПоля + " не соответствует шаблону");
КонецЕсли;
КонецЕсли;
// nested schema
Если Прав.Свойство("schema") Тогда
JSONПроверитьПоСхемеV2(Знач, Прав.schema, Ошибки, ИмяПоля);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
// Пример схемы
Схема = Новый Соответствие;
Схема.Вставить("Имя", Новый Структура("type,required,pattern", "Строка", Истина, "^[A-Яа-яA-Za-z ]{2,}$"));
Схема.Вставить("Сумма", Новый Структура("type,required,min,max", "Число", Истина, 0, 1000000));
Схема.Вставить("Валюта", Новый Структура("type,enum", "Строка", Новый Массив("RUB","USD","EUR")));
Схема.Вставить("Дата", Новый Структура("type,required", "Дата", Истина));
// Вложенный адрес
АдресСх = Новый Соответствие;
АдресСх.Вставить("Город", Новый Структура("type,required", "Строка", Истина));
АдресСх.Вставить("Индекс", Новый Структура("type,pattern", "Строка", "\\d{6}"));
Схема.Вставить("Адрес", Новый Структура("type,schema", "Структура", АдресСх));
Ошибки = Новый Массив;
JSONПроверитьПоСхемеV2(Данные, Схема, Ошибки);
Если Ошибки.Количество() > 0 Тогда
A1sS.Print("Проблемы: " + A1sS.Join(Ошибки, "; "));
Иначе
A1sS.Print("OK");
КонецЕсли;
Куда дальше
- A1sS: список функций, подробные страницы: AsString, Join, ReplaceText, ProcessTemplate, IsValidURL.
- Рецепты — набор готовых сценариев.
- Справочник 1С — синтаксис платформы.
Совет: начинайте с ValueQ + AsString + Join. Это покрывает 80% задач.
Паттерны по хелперам
A1sQ.ValueQ — одно значение по параметрам
// 1) По одному параметру, вернуть поле "Наименование"
ИмяПольз = A1sQ.ValueQ(
"ВЫБРАТЬ ПЕРВЫЕ 1 Наименование ИЗ Справочник.Пользователи ГДЕ ИдентификаторПользователяИБ = &UID",
Новый Структура("UID", ПользователиИнформационнойБазы.ТекущийПользователь().УникальныйИдентификатор),
"Наименование");
// 2) Несколько параметров, поле по умолчанию — первый столбец
Цена = A1sQ.ValueQ(
"ВЫБРАТЬ ПЕРВЫЕ 1 Цена ИЗ Справочник.Номенклатура ГДЕ Ссылка = &Сс AND ЕдиницаИзмерения = &Ед",
Новый Структура("Сс,Ед", СсылкаНоменклатуры, ЕдиницаРуб));
A1sQ.ValuesQ — массив из одного столбца
// Активные пользователи списком имён
Имена = A1sQ.ValuesQ(
"ВЫБРАТЬ Наименование ИЗ Справочник.Пользователи ГДЕ ПометкаУдаления = &F ПОРЯДОК ПО Наименование",
Новый Структура("F", Ложь));
A1sS.Print("Пользователи: " + A1sS.Join(Имена, ", "));
A1sQ.TableQ — таблица для UI/экспорта
// Топ-50 номенклатуры алфавитом
Таб = A1sQ.Unload( A1sQ.ExecuteQ( A1sQ.QT("ВЫБРАТЬ ПЕРВЫЕ 50 Ссылка, Наименование ИЗ Справочник.Номенклатура ПОРЯДОК ПО Наименование") ) );
// ТаблицаЗначений готова для формы/экспорта
A1sS.AsString — форматирование чисел и дат
Опц = Новый Структура("NumberFormat,DateFormat", "ЧГ=0; ЧД=2; N=,; T= ", "ДФ=dd.MM.yyyy");
СуммаСтр = A1sS.AsString(12345.678, Опц); // "12 345,68" (пример)
ДатаСтр = A1sS.AsString(ТекущаяДата(), Опц);
A1sS.Join — аккуратно соединить
Список = Новый Массив; Список.Добавить("R"); Список.Добавить(""); Список.Добавить("B");
// Фильтруем пустые и соединяем
Непустые = Новый Массив; Для Каждого Э Из Список Цикл Если A1sS.HasText(Э) Тогда Непустые.Добавить(Э); КонецЕсли; КонецЦикла;
Результат = A1sS.Join(Непустые, ", ", Неопределено, "Цвета: ", ".");
// "Цвета: R, B."
A1sS.ReplaceText — замены без регулярок
Текст = "контракт, контрактор";
Опции = Новый Структура("WholeWord", Истина);
Текст = A1sS.ReplaceText(Текст, "контракт", "договор", Опции);
// "договор, контрактор"
A1sS.AddTextToTemplate / CreateTemplateBuilder — быстрый шаблон
B = A1sS.CreateTemplateBuilder();
Для Каждого Т Из Товары Цикл
A1sS.AddTextToTemplate("• {{Имя}} — {{Цена}} ₽", Новый Структура("Имя,Цена", Т.Имя, Т.Цена));
КонецЦикла;
Итог = B.ToString();
A1sS.ProcessTemplate — подстановка по структуре
Шаблон = "Пользователь: {{Имя}} ({{Роль}})";
Стркт = Новый Структура("Имя,Роль", "Иван", "Администратор");
Рез = A1sS.ProcessTemplate(Шаблон, Стркт);
// "Пользователь: Иван (Администратор)"
A1sS.Print* — диагностический вывод
A1sS.Print("Старт");
A1sS.PrintYN(Истина); // "Да"
A1sS.PrintJSON(Новый Структура("A", 1, "B", 2));
A1sS.PrintXML(Новый Соответствие);
A1sS.IsValidURL / HasText / Wrap — валидация и мелочёвка
Если A1sS.IsValidURL("https://a1scode.ru") Тогда
Сообщить("ok");
КонецЕсли;
Если A1sS.HasText(Имя) Тогда
Имя = A1sS.Wrap(Имя, """, """); // "Имя" в кавычках
КонецЕсли;