ВыраженияУпорядочиванияКомпоновкиДанных

Типы · DataCompositionOrderExpressions

Коллекция выражений упорядочивания.

Полное описание, параметры и ограничения

ВыраженияУпорядочиванияКомпоновкиДанных (DataCompositionOrderExpressions)

ВыраженияУпорядочиванияКомпоновкиДанных (DataCompositionOrderExpressions)

Доступен, начиная с версии 8.1.

Элементы коллекции:
ВыражениеУпорядочиванияКомпоновкиДанных
Для объекта доступен обход коллекции посредством оператора Для каждого … Из … Цикл. При обходе выбираются выражения упорядочивания.
Возможно обращение к выражению упорядочивания посредством оператора [...]. В качестве аргумента передается индекс (нумерация с 0).

Методы:
Вставить (Insert)
Добавить (Add)
Индекс (IndexOf)
Количество (Count)
Очистить (Clear)
Получить (Get)
Сдвинуть (Move)
Удалить (Delete)

Описание:

Коллекция выражений упорядочивания.

Доступность:

Сервер, толстый клиент, внешнее соединение, мобильное приложение (сервер), мобильный автономный сервер.

См. также:
ПолеНабораДанныхСхемыКомпоновкиДанных, свойство ВыраженияУпорядочивания
ВычисляемоеПолеСхемыКомпоновкиДанных, свойство ВыраженияУпорядочивания
ГруппировкаМакетаКомпоновкиДанных, свойство ИерархическийПорядок
ГруппировкаМакетаКомпоновкиДанных, свойство Порядок
ЗаписиМакетаКомпоновкиДанных, свойство Порядок
ГруппировкаТаблицыМакетаКомпоновкиДанных, свойство ИерархическийПорядок
ГруппировкаТаблицыМакетаКомпоновкиДанных, свойство Порядок
ЗаписиТаблицыМакетаКомпоновкиДанных, свойство Порядок
ГруппировкаДиаграммыМакетаКомпоновкиДанных, свойство ИерархическийПорядок
ГруппировкаДиаграммыМакетаКомпоновкиДанных, свойство Порядок

Использование в версии:

Доступен, начиная с версии 8.1.

Методическая информация

Практические примеры

Редактор приоритетов: выражения упорядочивания обычного поля и расчётной суммы

На собственной таблице продаж и настоящих полях Код85/Сумма85 редактируем два каталога выражений: вставляем, меняем приоритет, текст и автоматичность, удаляем и восстанавливаем. Каждое состояние сравниваем целиком, а независимая модель сохраняет исходные описания. Это модель настроек, не выполненная сортировка отчёта.

Где и как запускать

Полный серверный общий модуль УчебныеЗадачи новой пустой конфигурации УчебноеУпорядочивание85; в1С не запускался.

Подготовка

  1. Только НОВАЯ отдельная пустая база УчебноеУпорядочивание85 на платформе8.5.1.1343, не копия рабочей. Нет бизнес-объектов, расширений, подписок и фоновых заданий. Здесь база не создаётся и опыт не запускается.

  2. Вручную создайте общий модуль УчебныеЗадачи: Сервер=Да, Вызов сервера=Да, клиентские флаги/Глобальный/Привилегированный=Нет. Вставьте полный основной модуль целиком, не внутрь другой процедуры.

  3. Своя внешняя обработка УчебноеУпорядочивание85 → управляемая Форма: команда Выполнить с действием Выполнить и кнопкой. Полный отдельный модуль формы ниже вставьте только в модуль своей формы. До будущего разрешённого опыта сохраните собственную базу и выполните F7 вне опыта, откройте свежий сеанс без расширений.

  4. Код создаёт таблицу A01/3/500 и B02/5/700, собственный Local-источник, объектный набор Продажи85, три исходных поля и расчёт Сумма85=Количество85 * Цена85. Код — Строка; количество — Число(1,0), цена — Число(3,0), сумма — Число(6,2), всё числовое неотрицательное. Шесть разрядов ВСЕГО включают два дробных, предел9999.99.

  5. В установленной справке ТипУпорядочивания помечено «Только чтение», хотя настоящий код УНФ/КА2 присваивает ему Возр. Противоречие не разрешено запуском и справка не исправляется. Здесь свойство только читается с проверкой типа НаправлениеСортировкиКомпоновкиДанных; значение по умолчанию Возр/Убыв и возможность записи не предполагаются.

Процедура ВыполнитьПример() Экспорт
    ПроверитьСвойПустойСтенд();
    Если ПривилегированныйРежим() Тогда
        ВызватьИсключение "Привилегированный режим не нужен";
    КонецЕсли;
    Пусто = Новый Массив;
    ИсходныйКод = СтрРазделить("Количество85,Цена85", ",");
    ИсходнаяСумма = СтрРазделить("Количество85 * Цена85,Код85", ",");
    Стенд = СоздатьСвойСтендПорядка();
    ПорядокКода = СвойКаталогПорядка(Стенд, "Код");
    ПорядокСуммы = СвойКаталогПорядка(Стенд, "Сумма");
    ПроверитьСвойСтендПорядка(Стенд, Пусто, Ложь, Пусто, Ложь);
    Количество = ПорядокКода.Добавить();
    ЗаполнитьСвоеВыражениеПорядка(Количество, "Количество85", Ложь);
    ПроверитьСвойСтендПорядка(Стенд, СтрРазделить("Количество85", ","), Ложь, Пусто, Ложь);
    Цена = ПорядокКода.Вставить(0);
    ЗаполнитьСвоеВыражениеПорядка(Цена, "Цена85", Ложь);
    ПроверитьСвойСтендПорядка(Стенд, СтрРазделить("Цена85,Количество85", ","), Ложь, Пусто, Ложь);
    ПорядокКода.Сдвинуть(Цена, 1);
    ПроверитьСвойСтендПорядка(Стенд, ИсходныйКод, Ложь, Пусто, Ложь);
    ВосстановитьСвойКаталогПорядка(Стенд, "Сумма");
    ПроверитьСвойСтендПорядка(Стенд, ИсходныйКод, Ложь, ИсходнаяСумма, Ложь);
    Копия = СоздатьСвойСтендПорядка();
    ВосстановитьСвойКаталогПорядка(Копия, "Код");
    ВосстановитьСвойКаталогПорядка(Копия, "Сумма");
    ПроверитьСвойСтендПорядка(Копия, ИсходныйКод, Ложь, ИсходнаяСумма, Ложь);
    ЗаполнитьСвоеВыражениеПорядка(Количество, "Код85", Истина);
    ПроверитьСвойСтендПорядка(Стенд, СтрРазделить("Код85,Цена85", ","), Истина, ИсходнаяСумма, Ложь);
    ПроверитьСвойСтендПорядка(Копия, ИсходныйКод, Ложь, ИсходнаяСумма, Ложь);
    ЗаполнитьСвоеВыражениеПорядка(Количество, "Количество85", Ложь);
    ПроверитьСвойСтендПорядка(Стенд, ИсходныйКод, Ложь, ИсходнаяСумма, Ложь);
    ФормулаСуммы = ПорядокСуммы[0];
    КодРасчета = ПорядокСуммы.Получить(1);
    ПорядокСуммы.Сдвинуть(КодРасчета, -1);
    ПроверитьСвойСтендПорядка(Стенд, ИсходныйКод, Ложь, СтрРазделить("Код85,Количество85 * Цена85", ","), Ложь);
    ПроверитьСвойСтендПорядка(Копия, ИсходныйКод, Ложь, ИсходнаяСумма, Ложь);
    ЗаполнитьСвоеВыражениеПорядка(КодРасчета, "Код85", Истина);
    ЗаполнитьСвоеВыражениеПорядка(ФормулаСуммы, "Цена85", Ложь);
    ПроверитьСвойСтендПорядка(Стенд, ИсходныйКод, Ложь, СтрРазделить("Код85,Цена85", ","), Истина);
    ПроверитьСвойСтендПорядка(Копия, ИсходныйКод, Ложь, ИсходнаяСумма, Ложь);
    ЗаполнитьСвоеВыражениеПорядка(КодРасчета, "Код85", Ложь);
    ЗаполнитьСвоеВыражениеПорядка(ФормулаСуммы, "Количество85 * Цена85", Ложь);
    ПорядокСуммы.Сдвинуть(КодРасчета, 1);
    ПроверитьСвойСтендПорядка(Стенд, ИсходныйКод, Ложь, ИсходнаяСумма, Ложь);
    ПорядокКода.Удалить(Цена);
    ПроверитьСвойСтендПорядка(Стенд, СтрРазделить("Количество85", ","), Ложь, ИсходнаяСумма, Ложь);
    ПроверитьСвойСтендПорядка(Копия, ИсходныйКод, Ложь, ИсходнаяСумма, Ложь);
    НоваяЦена = ПорядокКода.Вставить(1);
    ЗаполнитьСвоеВыражениеПорядка(НоваяЦена, "Цена85", Ложь);
    ПроверитьСвойСтендПорядка(Стенд, ИсходныйКод, Ложь, ИсходнаяСумма, Ложь);
    ПорядокСуммы.Удалить(КодРасчета);
    ПроверитьСвойСтендПорядка(Стенд, ИсходныйКод, Ложь, СтрРазделить("Количество85 * Цена85", ","), Ложь);
    НовыйКодРасчета = ПорядокСуммы.Вставить(1);
    ЗаполнитьСвоеВыражениеПорядка(НовыйКодРасчета, "Код85", Ложь);
    ПроверитьСвойСтендПорядка(Стенд, ИсходныйКод, Ложь, ИсходнаяСумма, Ложь);
    ПорядокКода.Очистить();
    ПорядокСуммы.Очистить();
    ПроверитьСвойСтендПорядка(Стенд, Пусто, Ложь, Пусто, Ложь);
    ПроверитьСвойСтендПорядка(Копия, ИсходныйКод, Ложь, ИсходнаяСумма, Ложь);
    ВосстановитьСвойКаталогПорядка(Стенд, "Код");
    ВосстановитьСвойКаталогПорядка(Стенд, "Сумма");
    ПроверитьСвойСтендПорядка(Стенд, ИсходныйКод, Ложь, ИсходнаяСумма, Ложь);
    ПроверитьСвойСтендПорядка(Копия, ИсходныйКод, Ложь, ИсходнаяСумма, Ложь);
КонецПроцедуры

Процедура ПроверитьСвойПустойСтенд()
    Если Метаданные.Справочники.Количество() <> 0 Или Метаданные.Документы.Количество() <> 0 Или Метаданные.Перечисления.Количество() <> 0 Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0 Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0 Или Метаданные.ПланыВидовХарактеристик.Количество() <> 0 Или Метаданные.ПланыВидовРасчета.Количество() <> 0 Или Метаданные.ПланыСчетов.Количество() <> 0 Или Метаданные.ПланыОбмена.Количество() <> 0 Или Метаданные.Последовательности.Количество() <> 0 Или Метаданные.БизнесПроцессы.Количество() <> 0 Или Метаданные.Задачи.Количество() <> 0 Или Метаданные.ОбщиеРеквизиты.Количество() <> 0 Или Метаданные.ПодпискиНаСобытия.Количество() <> 0 Или Метаданные.РегламентныеЗадания.Количество() <> 0 Или Метаданные.ВнешниеИсточникиДанных.Количество() <> 0 Тогда
        ВызватьИсключение "Нужен только свой новый пустой учебный стенд";
    КонецЕсли;
    Если Метаданные.ЕстьИзмененияРасширениямиКонфигурации() Тогда
        ВызватьИсключение "Свой сеанс не должен изменяться расширениями";
    КонецЕсли;
    Источники = Новый Массив;
    Источники.Добавить(ИсточникРасширенийКонфигурации.БазаДанных);
    Источники.Добавить(ИсточникРасширенийКонфигурации.СеансАктивные);
    Источники.Добавить(ИсточникРасширенийКонфигурации.СеансОтключенные);
    Для Каждого Источник Из Источники Цикл
        Расширения = РасширенияКонфигурации.Получить(, Источник);
        Если ТипЗнч(Расширения) <> Тип("Массив") Тогда
            ВызватьИсключение "Native список расширений должен иметь тип Массив";
        КонецЕсли;
        Если Расширения.Количество() <> 0 Тогда
            ВызватьИсключение "В своём новом стенде нет расширений базы или сеанса";
        КонецЕсли;
    КонецЦикла;
    Если ТранзакцияАктивна() Тогда
        ВызватьИсключение "Чужая или вложенная активная транзакция не допускается";
    КонецЕсли;
КонецПроцедуры

Функция СвояРазрядностьПродаж(Имя)
    Если Имя = "Код85" Тогда
        Возврат 0;
    ИначеЕсли Имя = "Количество85" Тогда
        Возврат 1;
    ИначеЕсли Имя = "Цена85" Тогда
        Возврат 3;
    ИначеЕсли Имя = "Сумма85" Тогда
        Возврат 6;
    КонецЕсли;
    ВызватьИсключение "В своей модели продаж только четыре заранее определённых поля";
КонецФункции

Функция СвойТипПродаж(Имя)
    Разрядность = СвояРазрядностьПродаж(Имя);
    Если Разрядность = 0 Тогда
        Возврат Новый ОписаниеТипов("Строка");
    КонецЕсли;
    ДробнаяЧасть = 0;
    Если Разрядность = 6 Тогда
        ДробнаяЧасть = 2;
    КонецЕсли;
    Возврат Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(Разрядность, ДробнаяЧасть, ДопустимыйЗнак.Неотрицательный));
КонецФункции

Процедура ПроверитьСвойТипПродаж(Описание, Имя)
    Если ТипЗнч(Описание) <> Тип("ОписаниеТипов") Тогда
        ВызватьИсключение "Нужно собственное описание типа продаж";
    КонецЕсли;
    Разрядность = СвояРазрядностьПродаж(Имя);
    ТипПоля = Тип("Число");
    Если Разрядность = 0 Тогда
        ТипПоля = Тип("Строка");
    КонецЕсли;
    ПолныеТипы = Описание.Типы();
    Если ПолныеТипы.Количество() <> 1 Или ПолныеТипы[0] <> ТипПоля Тогда
        ВызватьИсключение "Не совпал полный собственный тип поля продаж";
    КонецЕсли;
    Если Разрядность = 0 Тогда
        Возврат;
    КонецЕсли;
    ДробнаяЧасть = 0;
    Если Разрядность = 6 Тогда
        ДробнаяЧасть = 2;
    КонецЕсли;
    Квалификаторы = Описание.КвалификаторыЧисла;
    Если ТипЗнч(Квалификаторы) <> Тип("КвалификаторыЧисла") Или Квалификаторы.Разрядность <> Разрядность
        Или Квалификаторы.РазрядностьДробнойЧасти <> ДробнаяЧасть
        Или Квалификаторы.ДопустимыйЗнак <> ДопустимыйЗнак.Неотрицательный Тогда
        ВызватьИсключение "Не совпали разряды, дробная часть и знак собственного поля продаж";
    КонецЕсли;
КонецПроцедуры

Функция СоздатьСвоюОсновуПродаж()
    Данные = Новый ТаблицаЗначений;
    Имена = СтрРазделить("Код85,Количество85,Цена85", ",");
    Для Каждого Имя Из Имена Цикл
        Данные.Колонки.Добавить(Имя, СвойТипПродаж(Имя));
    КонецЦикла;
    СтрокаПродажи = Данные.Добавить();
    СтрокаПродажи.Код85 = "A01";
    СтрокаПродажи.Количество85 = 3;
    СтрокаПродажи.Цена85 = 500;
    СтрокаПродажи = Данные.Добавить();
    СтрокаПродажи.Код85 = "B02";
    СтрокаПродажи.Количество85 = 5;
    СтрокаПродажи.Цена85 = 700;
    Схема = Новый СхемаКомпоновкиДанных;
    Источник = Схема.ИсточникиДанных.Добавить();
    Источник.Имя = "СвоиПродажи85";
    Источник.ТипИсточникаДанных = "Local";
    Набор = Схема.НаборыДанных.Добавить(Тип("НаборДанныхОбъектСхемыКомпоновкиДанных"));
    Если ТипЗнч(Набор) <> Тип("НаборДанныхОбъектСхемыКомпоновкиДанных") Тогда
        ВызватьИсключение "Нужен собственный объектный набор продаж";
    КонецЕсли;
    Набор.Имя = "Продажи85";
    Набор.ИмяОбъекта = "Продажи85";
    Набор.ИсточникДанных = "СвоиПродажи85";
    Для Каждого Имя Из Имена Цикл
        Поле = Набор.Поля.Добавить(Тип("ПолеНабораДанныхСхемыКомпоновкиДанных"));
        Если ТипЗнч(Поле) <> Тип("ПолеНабораДанныхСхемыКомпоновкиДанных") Тогда
            ВызватьИсключение "Нужно собственное простое поле исходных продаж";
        КонецЕсли;
        Поле.Поле = Имя;
        Поле.ПутьКДанным = Имя;
        Поле.ТипЗначения = СвойТипПродаж(Имя);
    КонецЦикла;
    ВнешниеДанные = Новый Структура;
    ВнешниеДанные.Вставить("Продажи85", Данные);
    Стенд = Новый Структура;
    Стенд.Вставить("Схема", Схема);
    Стенд.Вставить("ВнешниеДанные", ВнешниеДанные);
    Возврат Стенд;
КонецФункции

Процедура ПроверитьСвоюОсновуПродаж(Стенд)
    Если ТипЗнч(Стенд) <> Тип("Структура") Или Стенд.Количество() <> 2 Тогда
        ВызватьИсключение "Нужна собственная структура схемы и внешних продаж";
    КонецЕсли;
    Схема = Неопределено;
    ВнешниеДанные = Неопределено;
    Если Не Стенд.Свойство("Схема", Схема) Или Не Стенд.Свойство("ВнешниеДанные", ВнешниеДанные) Тогда
        ВызватьИсключение "Не совпали оба собственных ключа стенда продаж";
    КонецЕсли;
    Если ТипЗнч(Схема) <> Тип("СхемаКомпоновкиДанных") Или Схема.ИсточникиДанных.Количество() <> 1
        Или Схема.НаборыДанных.Количество() <> 1 Тогда
        ВызватьИсключение "Нужен единственный собственный источник и объектный набор";
    КонецЕсли;
    Если ТипЗнч(ВнешниеДанные) <> Тип("Структура") Или ВнешниеДанные.Количество() <> 1 Тогда
        ВызватьИсключение "Нужен единственный собственный внешний объект продаж";
    КонецЕсли;
    Данные = Неопределено;
    Если Не ВнешниеДанные.Свойство("Продажи85", Данные) Тогда
        ВызватьИсключение "Внешний ключ обязан содержать настоящую собственную таблицу";
    КонецЕсли;
    Если ТипЗнч(Данные) <> Тип("ТаблицаЗначений") Или Данные.Количество() <> 2 Или Данные.Колонки.Количество() <> 3 Тогда
        ВызватьИсключение "Нужны две собственные продажи и три колонки";
    КонецЕсли;
    Источник = Схема.ИсточникиДанных.Получить(0);
    Если ТипЗнч(Источник) <> Тип("ИсточникДанныхСхемыКомпоновкиДанных")
        Или Источник.Имя <> "СвоиПродажи85" Или Источник.ТипИсточникаДанных <> "Local" Тогда
        ВызватьИсключение "Не совпал собственный логический источник";
    КонецЕсли;
    Набор = Схема.НаборыДанных.Получить(0);
    Если ТипЗнч(Набор) <> Тип("НаборДанныхОбъектСхемыКомпоновкиДанных") Или Набор.Имя <> "Продажи85"
        Или Набор.ИмяОбъекта <> "Продажи85" Или Набор.ИсточникДанных <> "СвоиПродажи85"
        Или Схема.НаборыДанных.Найти("Продажи85") <> Набор Или Набор.Поля.Количество() <> 3 Тогда
        ВызватьИсключение "Не совпал полный собственный набор и его три исходных поля";
    КонецЕсли;
    Имена = СтрРазделить("Код85,Количество85,Цена85", ",");
    Для Индекс = 0 По 2 Цикл
        Колонка = Данные.Колонки.Получить(Индекс);
        Поле = Набор.Поля.Получить(Индекс);
        Если ТипЗнч(Колонка) <> Тип("КолонкаТаблицыЗначений") Или Колонка.Имя <> Имена[Индекс]
            Или ТипЗнч(Поле) <> Тип("ПолеНабораДанныхСхемыКомпоновкиДанных")
            Или Поле.Поле <> Имена[Индекс] Или Поле.ПутьКДанным <> Имена[Индекс] Тогда
            ВызватьИсключение "Не совпали все имена, порядок и пути исходных колонок и полей";
        КонецЕсли;
        ПроверитьСвойТипПродаж(Колонка.ТипЗначения, Имена[Индекс]);
        ПроверитьСвойТипПродаж(Поле.ТипЗначения, Имена[Индекс]);
    КонецЦикла;
    Коды = СтрРазделить("A01,B02", ",");
    Количества = Новый Массив;
    Количества.Добавить(3);
    Количества.Добавить(5);
    Цены = Новый Массив;
    Цены.Добавить(500);
    Цены.Добавить(700);
    Суммы = Новый Массив;
    Суммы.Добавить(1500);
    Суммы.Добавить(3500);
    Для Индекс = 0 По 1 Цикл
        СтрокаПродажи = Данные.Получить(Индекс);
        Если ТипЗнч(СтрокаПродажи) <> Тип("СтрокаТаблицыЗначений")
            Или ТипЗнч(СтрокаПродажи.Код85) <> Тип("Строка") Или СтрокаПродажи.Код85 <> Коды[Индекс]
            Или ТипЗнч(СтрокаПродажи.Количество85) <> Тип("Число") Или СтрокаПродажи.Количество85 <> Количества[Индекс]
            Или ТипЗнч(СтрокаПродажи.Цена85) <> Тип("Число") Или СтрокаПродажи.Цена85 <> Цены[Индекс]
            Или СтрокаПродажи.Количество85 * СтрокаПродажи.Цена85 <> Суммы[Индекс] Тогда
            ВызватьИсключение "Не совпали все собственные ячейки и отдельный арифметический эталон BSL";
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Функция СвоеПолеДляПорядка(Стенд, Владелец)
    ПроверитьСвоюОсновуПродаж(Стенд);
    Расчеты = Стенд.Схема.ВычисляемыеПоля;
    Если ТипЗнч(Расчеты) <> Тип("ВычисляемыеПоляСхемыКомпоновкиДанных") Или Расчеты.Количество() <> 1 Тогда
        ВызватьИсключение "Нужен единственный собственный расчёт суммы";
    КонецЕсли;
    Сумма = Расчеты[0];
    Если ТипЗнч(Сумма) <> Тип("ВычисляемоеПолеСхемыКомпоновкиДанных")
        Или Сумма.ПутьКДанным <> "Сумма85" Или Сумма.Заголовок <> "Сумма продажи"
        Или Сумма.Выражение <> "Количество85 * Цена85" Тогда
        ВызватьИсключение "Не совпало полное собственное описание суммы";
    КонецЕсли;
    ПроверитьСвойТипПродаж(Сумма.ТипЗначения, "Сумма85");
    Если Владелец = "Сумма" Тогда
        Возврат Сумма;
    ИначеЕсли Владелец = "Код" Тогда
        Набор = Стенд.Схема.НаборыДанных.Получить(0);
        ПолеКода = Набор.Поля.Получить(0);
        Если ТипЗнч(ПолеКода) <> Тип("ПолеНабораДанныхСхемыКомпоновкиДанных")
            Или ПолеКода.Поле <> "Код85" Или ПолеКода.ПутьКДанным <> "Код85" Тогда
            ВызватьИсключение "Нужно настоящее собственное поле кода набора";
        КонецЕсли;
        Возврат ПолеКода;
    КонецЕсли;
    ВызватьИсключение "В собственном редакторе только владельцы Код или Сумма";
КонецФункции

Функция СвойКаталогПорядка(Стенд, Владелец)
    Поле = СвоеПолеДляПорядка(Стенд, Владелец);
    Каталог = Поле.ВыраженияУпорядочивания;
    Если ТипЗнч(Каталог) <> Тип("ВыраженияУпорядочиванияКомпоновкиДанных") Тогда
        ВызватьИсключение "Нужен собственный каталог выражений упорядочивания поля";
    КонецЕсли;
    Возврат Каталог;
КонецФункции

Функция СоздатьСвойСтендПорядка()
    Стенд = СоздатьСвоюОсновуПродаж();
    Сумма = Стенд.Схема.ВычисляемыеПоля.Добавить();
    Если ТипЗнч(Сумма) <> Тип("ВычисляемоеПолеСхемыКомпоновкиДанных") Тогда
        ВызватьИсключение "Добавить обязан вернуть собственное вычисляемое описание";
    КонецЕсли;
    Сумма.ПутьКДанным = "Сумма85";
    Сумма.Выражение = "Количество85 * Цена85";
    Сумма.Заголовок = "Сумма продажи";
    Сумма.ТипЗначения = СвойТипПродаж("Сумма85");
    СвойКаталогПорядка(Стенд, "Код").Очистить();
    СвойКаталогПорядка(Стенд, "Сумма").Очистить();
    Возврат Стенд;
КонецФункции

Процедура ЗаполнитьСвоеВыражениеПорядка(Элемент, Выражение, Автоматически)
    Если ТипЗнч(Элемент) <> Тип("ВыражениеУпорядочиванияКомпоновкиДанных")
        Или ТипЗнч(Выражение) <> Тип("Строка") Или ТипЗнч(Автоматически) <> Тип("Булево") Тогда
        ВызватьИсключение "Нужны настоящий элемент порядка, строка и Булево";
    КонецЕсли;
    Если Выражение <> "Код85" И Выражение <> "Количество85" И Выражение <> "Цена85"
        И Выражение <> "Количество85 * Цена85" Тогда
        ВызватьИсключение "В своей модели только выражения подготовленных исходных полей продаж";
    КонецЕсли;
    Элемент.Выражение = Выражение;
    Элемент.Автоупорядочивание = Автоматически;
КонецПроцедуры

Процедура ВосстановитьСвойКаталогПорядка(Стенд, Владелец)
    Каталог = СвойКаталогПорядка(Стенд, Владелец);
    Если Каталог.Количество() <> 0 Тогда
        ВызватьИсключение "Восстановление создаёт новые элементы только в очищенном своём каталоге";
    КонецЕсли;
    Если Владелец = "Код" Тогда
        Имена = СтрРазделить("Количество85,Цена85", ",");
    Иначе
        Имена = СтрРазделить("Количество85 * Цена85,Код85", ",");
    КонецЕсли;
    Для Каждого Имя Из Имена Цикл
        Элемент = Каталог.Добавить();
        ЗаполнитьСвоеВыражениеПорядка(Элемент, Имя, Ложь);
    КонецЦикла;
КонецПроцедуры

Процедура ПроверитьСвойКаталогПорядка(Стенд, Владелец, Выражения, АвтоПервого)
    Если ТипЗнч(Выражения) <> Тип("Массив") Или ТипЗнч(АвтоПервого) <> Тип("Булево") Тогда
        ВызватьИсключение "Нужны полный массив ожидаемых приоритетов и Булево-признак первого";
    КонецЕсли;
    Каталог = СвойКаталогПорядка(Стенд, Владелец);
    Если Каталог.Количество() <> Выражения.Количество() Тогда
        ВызватьИсключение "Не совпало полное количество выражений собственного поля";
    КонецЕсли;
    Для Индекс = 0 По Выражения.Количество() - 1 Цикл
        Элемент = Каталог.Получить(Индекс);
        Если ТипЗнч(Элемент) <> Тип("ВыражениеУпорядочиванияКомпоновкиДанных")
            Или Каталог[Индекс] <> Элемент Или Каталог.Индекс(Элемент) <> Индекс Тогда
            ВызватьИсключение "Не совпали тип, Получить, числовой индекс и положение элемента порядка";
        КонецЕсли;
        ОжидаемоеАвто = (Индекс = 0) И АвтоПервого;
        Если ТипЗнч(Элемент.Выражение) <> Тип("Строка") Или Элемент.Выражение <> Выражения[Индекс]
            Или ТипЗнч(Элемент.Автоупорядочивание) <> Тип("Булево") Или Элемент.Автоупорядочивание <> ОжидаемоеАвто
            Или ТипЗнч(Элемент.ТипУпорядочивания) <> Тип("НаправлениеСортировкиКомпоновкиДанных") Тогда
            ВызватьИсключение "Не совпали все выражения, приоритеты, автоматичность или тип направления";
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Процедура ПроверитьСвойСтендПорядка(Стенд, КодВыражения, КодАвто, СуммаВыражения, СуммаАвто)
    ПроверитьСвойКаталогПорядка(Стенд, "Код", КодВыражения, КодАвто);
    ПроверитьСвойКаталогПорядка(Стенд, "Сумма", СуммаВыражения, СуммаАвто);
КонецПроцедуры
УчебноеУпорядочивание85.Форма

Своя внешняя обработка УчебноеУпорядочивание85 → управляемая Форма → Модуль

Полный отдельный модуль собственной формы с серверным вызовом; здесь не запускался.

&НаКлиенте
Процедура Выполнить(Команда)
    ВыполнитьНаСервере();
    Сообщить("Собственные данные и приоритеты двух каталогов выражений восстановлены; отчёт не выполнялся");
КонецПроцедуры

&НаСервереБезКонтекста
Процедура ВыполнитьНаСервере()
    УчебныеЗадачи.ВыполнитьПример();
КонецПроцедуры

Разбор по шагам

  1. СвоеПолеДляПорядка получает именно обычное Код85 через настоящий набор и вычисляемое Сумма85 через каталог схемы. Проверяются все собственные строки, колонки, исходные поля, внешний ключ, формула и квалификаторы суммы. Начальные каталоги явно очищаются, их исходное содержимое не предполагается.

  2. Readonly ВыраженияУпорядочивания — это доступ к существующей коллекции, не запрет менять её элементы. ПорядокКода и ПорядокСуммы принадлежат двум разным настоящим полям; новую коллекцию или элемент через неизвестный конструктор не создают.

  3. Для Код85 учебный исходный приоритет — сначала Количество85, затем Цена85. Это пользовательское описание при сортировке по Код85, не обычный порядок по строковому коду. Для Сумма85 — сначала исходное выражение Количество85 * Цена85, затем Код85 как дополнительный ключ. Все имена и данные реально подготовлены самим кодом.

  4. Добавить() ставит новый элемент в конец, Вставить(индекс) — на указанное место, оба без Type-аргумента. Сдвинуть получает сам элемент и относительное смещение+1/-1. Индекс и Получить сверяются с числовым [], именной индекс каталога не выдумывается. Удалить получает объект, не номер.

  5. Шестнадцать состояний оригинала охватывают пустые каталоги, добавление/вставку, смену приоритета в обоих направлениях, правку выражения и автоматичности, восстановление, удаление и новую вставку у обоих владельцев, очистку и полное восстановление. В каждой сверке проверяются оба каталога и все исходные данные, не только количество элементов.

  6. Автоупорядочивание явно задаётся Булево. Временная Истина у первого выражения демонстрирует хранение настройки, потом возвращается Ложь. Для собственных строковых/числовых полей не обещается видимый эффект; это не направление Возр/Убыв и не автоматическое переставление элементов коллекции.

  7. Семь сверок независимой копии проверяют оба исходных каталога при смене текста/приоритета/автоматичности, удалении и очистке оригинала. Копия полностью строится заново: другая таблица, схема, набор, исходные поля, вычисление и элементы порядка; общих ссылок на изменяемые описания нет.

  8. После удаления Цена и КодРасчета больше не используются. НоваяЦена/НовыйКодРасчета создаются заново. После очистки не используются прежние элементы; восстановление допускается только в пустом каталоге. Сами поля, их типы и таблица не удаляются.

  9. В настоящем УниверсальномОтчете УНФ через ВыраженияУпорядочивания.Добавить создаются приоритеты периода/регистратора; в КА2 ЭкземплярБюджета создаёт выражение и Автоупорядочивание. Эти бизнес-поля и рабочие процедуры не заимствуются. Их присваивания ТипУпорядочивания не считаются подтверждением writable-контракта платформы8.5.1.1343.

Как проверить результат

  1. Ожидаемый будущий итог: обе продажи неизменны; обычное Код85 имеет выражения Количество85,Цена85 в этом порядке; Сумма85 имеет Количество85 * Цена85,Код85. У всех четырёх элементов Автоупорядочивание=Ложь. Независимая копия сохраняет те же каталоги, число/строковые типы и исходный расчёт.

  2. Будущий отрицательный контроль только в отдельно разрешённом стенде: изменить второй текст Цена85 на Количество85, не меняя ожидание, — проверка должна отказать при прежнем размере. Другие контроли: заменить Ложь на Истина без смены ожидания либо ценуB02 с700 на701; они должны отказать. Здесь эти контроли не запускались.

  3. runtimeVerifiedScenarios=0. Проверены установленные контракты и статическая целостность, не исполнение платформы. Порядок элементов каталога не доказывает порядок строк результата; арифметический эталон1500/3500 не является выполнением выражений СКД. Направление сортировки и поведение отчётного движка здесь не проверялись.

Ожидаемый результат

Полный собственный редактор двух каталогов с реальными владельцами, контролем приоритетов и независимым восстановлением; границы направления и фактической сортировки раскрыты.

На что обратить внимание

  1. Не заменяйте readonly Поле.ВыраженияУпорядочивания новым объектом и не присваивайте ТипУпорядочивания по неподтверждённому примеру. Проверка его типа не подтверждает конкретное направление, доступность setter или сохранение направления после пересоздания элемента.

  2. Перемещение элемента — смена приоритета выражений, не направление сортировки.+1 — относительное смещение, а не «переместить на индекс1». Обращение [] числовое с0; имя поля не является индексом этой коллекции.

  3. Выражение порядка отдельное от Выражение вычисляемого поля. Временная замена ключа на Цена85 не меняет Сумма85=Количество85 * Цена85, тип суммы и данные. Ни один ключ не ссылается на неизвестное поле или другое вычисляемое описание.

  4. Для исходного пустого ожидания создаётся Новый Массив без аргумента, не СтрРазделить пустой строки и не размерный Новый Массив(...). Возвращённые элементы используются только пока они принадлежат собственному действующему каталогу.

  5. Не создаются настройки выбора/порядка отчёта, ресурсы, компоновщик макета или процессор. Этот опыт не выдаётся за готовый исполнимый отчёт или доказательство сортировки. Никакой записи, запросов к рабочим данным, сети, печати, запуска1С или изменения конфигураций пользователя.

Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.

Исследовать серии и точки настоящего макета диаграммы СКД

Строим свою гистограмму из трёх продаж, затем разбираем созданные компоновщиком группировки серий и точек, выражения, ограничения, сортировки и области ресурсов.

Где и как запускать

Полный серверный общий модуль УчебныйМакетДиаграммы85; запускается только из собственной серверной учебной команды.

Подготовка

  1. Используйте отдельную пустую учебную базу 8.5.1.1343. Данные рабочих конфигураций, готовые отчёты и подключение к интернету не нужны.

  2. Создайте общий модуль УчебныйМакетДиаграммы85: Сервер — Да, Клиент — Нет, Вызов сервера — Нет, Привилегированный — Нет. Вставьте весь модуль одного урока целиком, включая вспомогательные функции.

  3. В своей учебной обработке создайте управляемую форму и команду ВыполнитьУрок. Через конструктор обработчика добавьте клиентскую процедуру команды, вызывающую собственную процедуру ВыполнитьНаСервере() с директивой &НаСервереБезКонтекста. В её тело вставьте УчебныйМакетДиаграммы85.ВыполнитьПример();.

  4. В запросе только свои три строки: Север/Книга — количество 3, сумма 750; Север/Ручка — 1 и 50; Юг/Книга — 2 и 500. Сумма источника 1300, количество единиц 6. Запрос ничего не читает из справочников или регистров.

  5. Поставьте точку останова перед последним Сообщить в ВыполнитьПример. В серверном отладчике смотрите переменные Макет, Группы и Результат; у табличного документа можно открыть просмотр значения. Не пытайтесь вернуть Макет в тонкий клиент.

  6. Каждый запуск заново строит свою схему и макет в памяти. Код не открывает клиентское окно, не печатает, не сохраняет файлы, не меняет настройки другого пользователя и не пишет в базу.

  7. Магазины — серии, товары — точки, ресурс — сумма. Группировка настроек, группировка скомпилированного макета и готовая серия рисунка — разные объекты. У группировки макета нет конструктора Новый; она получается обходом собственных Макет.Тело → Диаграмма → Серии/Точки.

  8. Пример не запускался в 1С. Контрольные результаты ниже ожидаемые; статические проверки сигнатур не подтверждают фактическое оформление или размещение итогов в табличном документе.

  9. Наш запрос не содержит Юг/Ручка. Отсутствующая комбинация — не отдельная исходная строка с нулём. Суммы магазина Север 800, Юга 500, товара Книга 1250 и Ручка 50.

Процедура ВыполнитьПример() Экспорт
    Схема = Новый СхемаКомпоновкиДанных;
    Источник = Схема.ИсточникиДанных.Добавить();
    Источник.Имя = "УчебныеПродажи";
    Источник.ТипИсточникаДанных = "Local";
    Набор = Схема.НаборыДанных.Добавить(Тип("НаборДанныхЗапросСхемыКомпоновкиДанных"));
    Набор.Имя = "СвоиТриСтроки";
    Набор.ИсточникДанных = Источник.Имя;
    Набор.АвтоЗаполнениеДоступныхПолей = Истина;
    Набор.Запрос = "ВЫБРАТЬ
    |    ""Север"" КАК Магазин,
    |    ""Книга"" КАК Наименование,
    |    3 КАК Количество,
    |    750 КАК Сумма
    |ОБЪЕДИНИТЬ ВСЕ
    |ВЫБРАТЬ ""Север"", ""Ручка"", 1, 50
    |ОБЪЕДИНИТЬ ВСЕ
    |ВЫБРАТЬ ""Юг"", ""Книга"", 2, 500";
    Для Каждого ИмяРесурса Из СтрРазделить("Сумма,Количество", ",") Цикл
        Ресурс = Схема.ПоляИтога.Добавить();
        Ресурс.ПутьКДанным = ИмяРесурса;
        Ресурс.Выражение = "Сумма(" + ИмяРесурса + ")";
    КонецЦикла;
    Настройки = Схема.НастройкиПоУмолчанию;
    Диаграмма = Настройки.Структура.Добавить(Тип("ДиаграммаКомпоновкиДанных"));
    Диаграмма.Имя = "УчебныеПродажиПоМагазинам";
    Диаграмма.Использование = Истина;
    Выбранное = Диаграмма.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
    Выбранное.Поле = Новый ПолеКомпоновкиДанных("Сумма");
    Выбранное.Использование = Истина;
    Серия = Диаграмма.Серии.Добавить();
    Серия.Имя = "Магазины";
    Серия.Использование = Истина;
    ПолеСерии = Серия.ПоляГруппировки.Элементы.Добавить(Тип("ПолеГруппировкиКомпоновкиДанных"));
    ПолеСерии.Поле = Новый ПолеКомпоновкиДанных("Магазин");
    ПолеСерии.ТипГруппировки = ТипГруппировкиКомпоновкиДанных.Элементы;
    ПолеСерии.Использование = Истина;
    Точка = Диаграмма.Точки.Добавить();
    Точка.Имя = "Товары";
    Точка.Использование = Истина;
    ПолеТочки = Точка.ПоляГруппировки.Элементы.Добавить(Тип("ПолеГруппировкиКомпоновкиДанных"));
    ПолеТочки.Поле = Новый ПолеКомпоновкиДанных("Наименование");
    ПолеТочки.ТипГруппировки = ТипГруппировкиКомпоновкиДанных.Элементы;
    ПолеТочки.Использование = Истина;
    Диаграмма.ПараметрыВывода.УстановитьЗначениеПараметра("ТипДиаграммы", ТипДиаграммы.Гистограмма);
    Диаграмма.ПараметрыВывода.УстановитьЗначениеПараметра("Заголовок", "Свои продажи: магазины и товары");
    КонтрольныйЗапрос = Новый Запрос;
    КонтрольныйЗапрос.Текст = Набор.Запрос;
    ИсходныеСтроки = КонтрольныйЗапрос.Выполнить().Выгрузить();
    Если ИсходныеСтроки.Количество() <> 3 Или ИсходныеСтроки.Итог("Сумма") <> 1300 Тогда
        ВызватьИсключение "Изменились собственные учебные данные";
    КонецЕсли;
    Компоновщик = Новый КомпоновщикМакетаКомпоновкиДанных;
    Макет = Компоновщик.Выполнить(Схема, Настройки);
    Группы = Новый Массив;
    НайтиГруппыДиаграмм(Макет.Тело, Группы);
    Если Группы.Количество() = 0 Тогда
        ВызватьИсключение "В собственном макете не найдены группировки диаграммы";
    КонецЕсли;
    Для Каждого ГруппаМакета Из Группы Цикл
        Сообщить("Имя группировки: " + ГруппаМакета.Имя);
        Сообщить("Идентификатор: " + ГруппаМакета.Идентификатор);
        Сообщить("Ограничение количества: " + Строка(ГруппаМакета.КоличествоЗаписей));
        Сообщить("Процент записей: " + Строка(ГруппаМакета.ПроцентЗаписей));
        Сообщить("Отбор записей: " + ГруппаМакета.ОтборЗаписей);
        Сообщить("Отбор группировок: " + ГруппаМакета.ОтборГруппировок);
        Сообщить("Отбор группировок с иерархией: " + ГруппаМакета.ОтборГруппировокСИерархией);
        Сообщить("Отбор только иерархии: " + ГруппаМакета.ОтборГруппировокТолькоИерархия);
        Сообщить("Частей тела: " + Строка(ГруппаМакета.Тело.Количество()));
        Сообщить("Частей иерархического тела: " + Строка(ГруппаМакета.ТелоИерархии.Количество()));
        Для Каждого Поле Из ГруппаМакета.Группировка Цикл
            Сообщить("Поле группировки: " + Поле.ИмяПоля + "; выражение: " + Поле.Выражение);
        КонецЦикла;
        Для Каждого Порядок Из ГруппаМакета.Порядок Цикл
            Сообщить("Порядок: " + Порядок.Выражение + "; направление: " + Строка(Порядок.ТипУпорядочивания));
        КонецЦикла;
        Сообщить("Элементов иерархического порядка: " + Строка(ГруппаМакета.ИерархическийПорядок.Количество()));
        Для Каждого ЧастьТела Из ГруппаМакета.Тело Цикл
            Если ТипЗнч(ЧастьТела) = Тип("МакетГруппировкиДиаграммыМакетаКомпоновкиДанных") Тогда
                Сообщить("Область группировки диаграммы: " + ЧастьТела.Макет);
                Сообщить("Макетов ресурсов этой области: " + Строка(ЧастьТела.МакетРесурсов.Количество()));
                Для Каждого МакетРесурса Из ЧастьТела.МакетРесурсов Цикл
                    Сообщить("Область ресурса: " + МакетРесурса.Макет);
                    Сообщить("Область группировки ресурса: " + МакетРесурса.МакетГруппировки);
                КонецЦикла;
            КонецЕсли;
        КонецЦикла;
    КонецЦикла;
    Результат = СформироватьСвойДокумент(Макет);
    Сообщить(Результат.ВысотаТаблицы > 0);
КонецПроцедуры

Процедура НайтиГруппыДиаграмм(Тело, Найденные)
    Для Каждого Часть Из Тело Цикл
        Если ТипЗнч(Часть) = Тип("ДиаграммаМакетаКомпоновкиДанных") Тогда
            Сообщить("Диаграмма: " + Часть.Имя);
            Сообщить("Идентификатор диаграммы: " + Часть.Идентификатор);
            Сообщить("Макет диаграммы: " + Часть.Макет);
            Сообщить("Макет ресурсов диаграммы: " + Часть.МакетРесурсов);
            СобратьГруппыОси(Часть.Серии, Найденные);
            СобратьГруппыОси(Часть.Точки, Найденные);
        ИначеЕсли ТипЗнч(Часть) = Тип("ГруппировкаМакетаКомпоновкиДанных") Тогда
            НайтиГруппыДиаграмм(Часть.Тело, Найденные);
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Процедура СобратьГруппыОси(ТелоОси, Найденные)
    Для Каждого Часть Из ТелоОси Цикл
        Если ТипЗнч(Часть) = Тип("ГруппировкаДиаграммыМакетаКомпоновкиДанных") Тогда
            Найденные.Добавить(Часть);
            СобратьГруппыОси(Часть.Тело, Найденные);
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Функция СформироватьСвойДокумент(СвойМакет)
    Процессор = Новый ПроцессорКомпоновкиДанных;
    Процессор.Инициализировать(СвойМакет);
    Документ = Новый ТабличныйДокумент;
    Вывод = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
    Вывод.ОтображатьПроцентВывода = Ложь;
    Вывод.УстановитьДокумент(Документ);
    РезультатВывода = Вывод.Вывести(Процессор, Ложь);
    Если ТипЗнч(РезультатВывода) <> Тип("ТабличныйДокумент") Тогда
        ВызватьИсключение "Не получен собственный табличный документ";
    КонецЕсли;
    Возврат РезультатВывода;
КонецФункции

Разбор по шагам

  1. Источник Local содержит только собственные константы. Сумма и Количество объявлены ресурсами, но в диаграмму выбираем Сумма.

  2. Настройки задают Магазин для серий и Наименование для точек; ТипГруппировки Элементы не запрашивает иерархию справочника.

  3. Схема и настройки передаются компоновщику. Полученный МакетКомпоновкиДанных ещё не является рисунком или ТабличнымДокументом.

  4. В реальном теле ищем точный тип ДиаграммаМакетаКомпоновкиДанных. Его Серии и Точки — отдельные readonly-коллекции группировок макета; не присваиваем им новые массивы.

  5. Тип каждого узла проверяется перед чтением. Рекурсия обходит простые неиерархические группировки своей диаграммы; пустое тело не превращается в выдуманный объект.

  6. Группировка описывает поля и выражения оси. Имя и Идентификатор читаем для диагностики, не переименовываем связанную часть макета.

  7. Четыре области отбора, обычный и иерархический порядок относятся к разным этапам. Пустые выражения и отсутствие иерархического тела допустимы в этой простой задаче.

  8. В теле группы отдельно проверяем МакетГруппировкиДиаграммыМакетаКомпоновкиДанных: Макет — строковое имя области, МакетРесурсов — коллекция объектов. У каждого объекта читаем свои Макет и МакетГруппировки.

  9. Свежий процессор и процессор вывода создают собственный табличный документ с диаграммой. В отладчике можно сопоставить описание группировок с фактическими сериями и точками.

Как проверить результат

  1. Группы не пусты. Среди полей найдите Магазин и Наименование, заключительное сравнение высоты документа должно дать Истина.

  2. В просмотре результата ожидаются две серии Север и Юг, точки Книга и Ручка. Значения имеющихся пересечений: 750, 50 и 500; исходная общая сумма 1300.

  3. Проверьте в отладчике типы коллекций и частей тела. Техническое число областей, их имена и заполнение неиспользуемых иерархических частей не фиксируются.

  4. Отсутствующая Юг/Ручка может оформляться как пустое значение; по её виду нельзя заключать, что исходный запрос содержал четвёртую продажу.

Ожидаемый результат

Получена собственная диаграмма и полноценный диагностический разбор её реального макета, без неизвестных входных объектов и записи в рабочую базу.

На что обратить внимание

  1. ГруппировкаДиаграммыМакетаКомпоновкиДанных не равна ГруппировкаДиаграммыКомпоновкиДанных из настроек и не равна СерияДиаграммы готового рисунка.

  2. Не присваивайте readonly-ссылки Группировка, Порядок, ИерархическийПорядок, Тело и ТелоИерархии. Строковые имена областей нельзя подменять объектами.

  3. У группировки диаграммы нет МакетШапки и МакетПодвала, в отличие от других группировок. Области вывода ищутся в её теле.

  4. Не вставляйте SQL или текст запроса в скомпилированные отборы без проверки языка выражений СКД. Для обычного изменения фильтра корректируйте настройки и пересобирайте макет.

  5. Обход рассчитан на созданную здесь простую диаграмму без иерархических группировок и вложенных схем; это не универсальный инспектор чужих отчётов.

  6. Статические проверки не подтверждают оформление диаграммы на экране. Здесь агент не запускает 1С, не вызывает сеть, печать или сохранение файла.

Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.

Не хотите разбираться сами?

Адаптируем это решение под вашу базу. Оценка бесплатно.

Оставить задачу

1С, 1С:Предприятие — товарные знаки ООО «1С». Сайт не является официальным представительством фирмы «1С» и не аффилирован с ней.