1С
- Встроенный язык
- Типы данных и операторы
- Общая информация
- Циклы и метки
- Модули, директивы препроцессора и компиляции
- Подпрограммы
- Исключения, внешний код
- Управление отображением и событиями платформы
- Механизм блокировок
- Механизм транзакций
- Администрирование
- Создание или добавление информационной базы
- Структура решения и обновление
- Пользователи и роли
- Учебная версия
- Монопольный режим
- Объекты конфигурации
- Общая информация
- Класс Константы и Перечисления
- Класс Справочники
- Класс Документы и Журналы документов
- Класс Регистры
- Класс Отчеты
- Макеты
- Периодические задания
- План видов характеристик
- Запросы
- Одноуровневые запросы
- Вложенные запросы, соединение, объединение, пакетные запросы
- Конструктор запросов
- Способы обхода результата запроса
- Бизнес процессы и задачи.
- Разработка интерфейса
- Общая информация
- Формы интерфейса
- Эстетическое оформление
- Интерактивное взаимодействие и оповещения
- Динамические списки
- Сценарное тестирование
- Отчеты
Встроенный язык
Типы данных и операторы
Переменные
Динамическая типизация.
а = -1;
а = "Один";
Сообщить(а);
//"Один"
ТипЗнч(элмас) - вывести тип переменной.
Можно явно определить имя переменной, ключевое слово Экспорт позволяет обращаться к переменной через контекст модуля. Без экспорта только для эстетики кода.
Перем <Имя переменной 1> [Экспорт]
Типы данных и преобразования типов
Примитивные типы данных
Тип | Описание |
Null |
Исключительно для определения отсутствующего значения при работе с базой данных. |
Неопределено (Undefined) |
Пустое значение, не принадлежащее ни к одному другому типу.
Прямое преобразование в булево: нельзя При сравнении любой тип не равен Неопределено
|
Число |
Определены основные арифметические операции. Максимальная разрядность 38 знаков. Разделитель точка. 32 знака. Прямое преобразование в булево: любое ненулевое Истина, 0 Ложь Преобразование в строку: Строка() |
Строка |
Формат Unicode произвольной длины. В двойных кавычках. Многостроковый режим через | Прямое преобразование в булево: нельзя
Преобразование в число:
Преобразование в дату:
|
Дата |
Строка цифр, заключенная в одинарные кавычки вида: 'ГГГГММДДччммсс' Прямое преобразование в булево: нельзя Контроль заполненности: Перем.ЗначениеЗаполнено() Пустая дата - Дата(1,1,1) |
Булево |
Значения данного типа имеют два значения Истина и Ложь |
Тип |
Используются для идентификации типов значений. Это необходимо для определения и сравнения типов. |
Универсальные коллекции значений
Тип | Описание |
Массив |
Аналог списка. Конструктор:
Методы: Количество
Найти - Если найден - индекс, иначе неопределено. Очистить - Удаляет все значения из массива. Удалить - удаляет указанный индекс |
Структура
|
Аналог словаря. Ключи только строковые. Конструктор:
Доступ к элементу:
Перебор значений:
Вставить(ключ, значение)
|
Соответствие | Как структура, только ключ может быть любого типа. |
Список значений | Как массив + строковое описание (Представление), Пометка и Картинка |
Таблица значений |
Двумерная таблица.
|
Фиксированный (массив, соответствие, структура) | Аналогичный объект только для чтения. |
Хранилище значений | Недоступен напрямую в управляемой форме. Нужно городить временное хранилище. |
Объекты
Респект и уважуха автору AlexO за разъяснение сущности взаимодействия в 1С ссылка на форум
В 1С нет настоящих "объектов" ООП. Эти товарищи обозвали словом "объект" ссылку на словарь значений. В 1С введено внутреннее понятие КоллекцияЗначений - и это не аналог контейнера объектов из ООП (который и сам определяет поведение входящих объектов, и дает доступ напрямую к ним - к их свойствам, методам, данным, событиям и т.д.), а набор ссылок на другие объекты, и из коллекции, если не получен "вложенный" элемент-объект (например, через метод НабораЗаписей НаборЗаписей.Прочитать()" ), нельзя напрямую получить свойства и методы элементов коллекции, а только - получить "объекты" коллекции, и уже обходом или обращением к элементу коллекции - работать со свойствами и методами "вложенных" объектов. Объект РегистрСведений не содержит объект РегистрСведенийНаборЗаписей, а НаборЗаписей не содержит объекты РегистрСведенийЗапись. Для работы с каждым вложенным уровнем нужно заново получать объекты этого нового уровня вложенности. Собственно, вся канитель "не могу получить данные объекта там-то", "не могу получить доступ к процедуре тут-то", "не видна переменная экспортная такая-то" и прочие невообразимые и множественные ограничения платформы - именно из-за наборов не связанных напрямую друг с другом "объектов", которых нужно каждый раз "получать", извлекать данные, и которым нужно каждый раз указывать - что мы от них хотим.
Тип конфигурации ...Объект (например СправочникОбъект) -
Поскольку переписывать лень, далее используется слово Объект в понимании 1С.
Внешних модулей нет. Использование процедур в разных проектах - только копирование/вставка. Придется смириться.
Обращение к свойствам через точку или <Объект>["имя свойства"]
Менеджер = Справочники["Менеджеры"];
Менеджер = Справочники.Менеджеры;
Обращение к методам - через точку. Дополнение:
Категорический запрет на использование в запросах "двойного разъименования" (Объект.Свойство<содержащее СсылкуНаДругойОбъект>.СвойствоДругогоОбъекта) - только явное соединение таблиц через СОЕДИНЕНИЕ...
Условные операторы
?(<Логическое выражение>, <Выражение 1>, <Выражение 2>)
а = Истина;
б = ?(а = Ложь, 0, 1);//б = 1
Если <Логическое выражение> Тогда
// Операторы
[ИначеЕсли <Логическое выражение> Тогда]
// Операторы
[Иначе]
// Операторы
КонецЕсли;
Разное
Выполнить(<Строка>);
Выполнить("Сообщить(а)");
Исполняет строковое представление команды.
Общая информация
В данном разделе предоставлена информация, максимально связанная только со встроенным языком 1С. Информация об остальных объектах языка представлена по необходимости.
Предварительная подготовка конфигурации.
- Создать пустую конфигурацию Создание или добавление информационной базы
- Открыть конфигуратор, открыть конфигурацию
- Создать справочник Менеджеры, без дополнительных данных.
Проверка встроенного языка 1С будет проводиться по следующему алгоритму: Создание обработки
Циклы и метки
В циклах могут использовать операторы Прервать; и Продолжить;
Цикл for:
Для <Имя переменной> = <Выражение 1> По <Выражение 2> Цикл
// Операторы
КонецЦикла;
Обход коллекции:
Для каждого <Имя переменной 1> Из <Имя переменной 2> Цикл
// Операторы
КонецЦикла;
Цикл While
Пока <Логическое выражение> Цикл
// Операторы
КонецЦикла;
В языке есть метки.
Перейти ~ВыходИзДвойногоЦикла;
~ВыходИзДвойногоЦикла:
//продолжение
Модули, директивы препроцессора и компиляции
В 1С ебанутые правила, связанные с модульностью. Понять и простить.
Модули служат для хранения кода. Несколько регламентированных точек размещения модулей, однако точка размещения кода для решения конкретной задачи регламентирована на уровне "можно и здесь, а можно и где-то там", поэтому финальная точка размещения зависит от фазы луны в момент создания кода разработчиком. То есть правила вроде есть, но их можно не исполнять. Однако важный нюанс: в каждой точке размещения доступны разные глобальные переменные, поэтому при написании кода набор доступных переменных нужно обязательно уточнять. Часто в интернетах приводят код без указания размещения модуля, потом при вопросе "А у меня не работает" сначала пара страниц троллинга типа они пиздец какие охуевшие спецы, потом кто-то снисходит до лошары. Хотя данное разделение не несет практической цели для разработчика конфигурации кроме искусственного усложнения и скорее артефакт изначально упрощенной архитектуры. Как деление подпрограмм на процедуры и функции.
Интересная статья по модулям, однако есть ряд недосказанных моментов.
Для подпрограмм всех модулей актуальны директивы препроцессора и компиляции. Модули можно сгруппировать по следующим правилам (группировка субъективная на основании изучения различных источников):
Группа | Размещение модулей | Базовое назначение | Подробное описание |
Общие | Конфигурация - Общие - Общие модули | Хранение общего кода, доступного из остальных модулей. Настроить обработку событий нельзя. | В этой статье. |
Модули конфигурации |
Конфигурация - Свойства.
Модуль приложения |
Обработка общих событий платформы. Размещение подпрограмм обработки событий платформы. Например запуска приложения или внешнего вызова. |
Управление отображением и событиями платформы |
Модули классов |
Конкретный класс.
Модуль формы |
События, связанные с конкретным классом. Например нажатие кнопки "Показать группы" в окне списка справочника Номенклатура. | Объекты конфигурации |
Структура модуля:
Раздел определения переменных - от начала текста модуля до первого оператора Процедура, Функция, или любого исполняемого оператора. Только операторы объявления переменных Перем.
Раздел процедур - от первого Процедура / Функция до любого исполняемого оператора вне тела описания процедур или функций.
Раздел основной программы - от первого исполняемого оператора вне тела последней процедуры или функции до конца модуля. Могут находиться только исполняемые операторы. Исполняется в момент инициализации модуля. Обычно в разделе
основной программы имеет смысл размещать операторы инициализации переменных какими-либо конкретными значениями, которые необходимо провести до первого вызова любой из процедур или функций модуля.
Свойства модуля:
- Способ обращения к подпрограммам
- «Глобальный». Возможность вызова подпрограмм без указания имени модуля. Имена должны быть уникальными в разрезе всего глобального контекста. Компилируются при старте системы. Чем больше таких модулей, тем медленнее программа будет стартовать. Если не указан, то компиляция будет выполняться в момент первого обращения к нему.
- Область видимости
- «Клиент». Возможность исполнения подпрограмм модуля на клиенте;
- «Сервер». Возможность исполнения подпрограмм модуля на сервере;
- «Внешнее соединение». Возможность исполнения подпрограмм модуля через подключение внешнего источника;
- Возможности со стороны подпрограмм модуля
- «Вызов сервера». Возможность подпрограмм модуля вызывать сервер, выполняясь на клиенте;
- «Привилегированный». При работе кода процедур модуля не проверяет права доступа. Вызвать общий модуль с такой настройкой можно только на сервере. Настройки «Клиент» и «Внешнее соединение» будут сброшены.
Это необходимо, если требуется массовая обработка данных. Контроль прав доступа увеличивает время обращения к базе данных .
- Кэширование
- Для не глобальных Общих модулей. Варианты: «Повторное использование». Варианты: «Не использовать», «На время сеанса», «На время вызова». При многократном вызове одной процедуры система может использовать рассчитанные ранее данные в рамках процедуры (вызов) или жизни всего сеанса (запуска 1С).
Цель – ускорить повторные вызовы. Имеет смысл только для тех функций, результат которых зависит исключительно от входных параметров. Если выбрано значение соответствующего параметра На время вызова, то кэш будет действовать до тех пор, пока работает та процедура, откуда был сделан вызов метода Общего модуля. Если выбрано значение На время сеанса, то условно считается, что кэш будет действовать, пока пользователь работает. Существуют временнЫе ограничения, очистка кэша происходит автоматически через 20 минут после попадания значения в кэш. Использовать осознанно.
- Для не глобальных Общих модулей. Варианты: «Повторное использование». Варианты: «Не использовать», «На время сеанса», «На время вызова». При многократном вызове одной процедуры система может использовать рассчитанные ранее данные в рамках процедуры (вызов) или жизни всего сеанса (запуска 1С).
Директивы препроцессора и компиляции
Есть два режима, определяются при создании конфигурации: на локальном ПК (файловый) и на сервере 1С (клиент-серверный вариант). Файловый вариант объединяет в себе и код клиента, и код сервера, поэтому смысла от деления кода при помощи директив препроцессора нет.
При запуске конфигурации на выполнение производится загрузка и компиляция конфигурации. Алгоритм компиляции:
- Экземпляры всех общих модулей создаются как на серверной, так и на клиентской стороне. Препроцессор используя директивы препроцессора и области видимостей модулей создает несколько слегка отличающихся копий (в соответствии с количеством платформ) кода. Директивы компиляции игнорируются. По умолчанию (без директив) все подпрограммы попадают во все копии. При наличии, код физически вырезается, и другая платформа не видит чужой код. Нужно для уменьшения объема кода и ускорения работы каждого из блоков.
- Код компилируется для каждой платформы. Используя директивы компиляции, формируются алгоритмы взаимодействия. Например, при вызове из подпрограммы &НаКлиенте подпрограммы &НаСервере форма упаковывается в контейнер (!), переправляется по каналу tcp\ip на сервер, распаковывается сервером, выполняется код целевой процедуры, форма запаковывается обратно в контейнер, передается на клиент, распаковывается клиентом, отображается на экране. В случае с "..БезКонтекста" платформа выполняет код "налегке", т.е. на сервер передаются только параметры функции, а обратно прилетает только результат выполнения. Директивой по умолчанию является &НаСервере.
Директивы препроцессора
При компиляции блоки распределяются в соответствии с директивами. Для указания разрешения использования процедур и функций общих модулей и модулей объектов используют инструкции препроцессора.
Синтаксис:
#Если <Логическое выражение> Тогда
#ИначеЕсли <Логическое выражение> Тогда
#Иначе
#КонецЕсли
<Логическое выражение> = [НЕ] <Символ препроцессора> [<Булева операция> [НЕ] <Символ препроцессора> [<Булева операция> [НЕ] <Символ препроцессора>]…]
<Символ препроцессора> = {НаКлиенте | НаСервере | ТолстыйКлиентОбычноеПриложение | ТолстыйКлиентУправляемоеПриложение | Клиент | Сервер | ВнешнееСоединение }
<Булева операция> = {И | ИЛИ}
Можно использовать И (AND), ИЛИ (OR), НЕ (NOT) Регистр букв не имеет значения.
Области
#Область, #КонецОбласти Нужны только для визуального сворачивания блоков кода. Могут быть вложенными.
#Область [<Имя области>]
#КонецОбласти
Условия
#Если (#If), #Тогда (#Then), #ИначеЕсли (#ElsIf), #Иначе (#Else), #КонецЕсли (#EndIf) Можно организовывать выполнение различных процедур и функций на сервере приложения или на клиентском месте. Для того, чтобы процедура присутствовала и была вызвана на стороне сервера, фрагмент кода должен выглядеть следующим образом:
#Если Сервер Тогда
Процедура Проц1() Экспорт
КонецПроцедуры
#КонецЕсли
Если блок #Если Сервер Тогда … #КонецЕсли включает только часть процедуры, то процедура будет присутствовать как на стороне клиента, так и на стороне сервера. Только на клиентской стороне она будет без той части, которая заключена в блок, поэтому результат выполнения процедуры может зависеть от того, где обрабатывается вызов этой процедуры.
Для выполнения на клиентском месте в обычном и управляемом режиме:
#Если НаКлиенте Тогда
#КонецЕсли
Точки исполнения
Инструкция препроцессора НаКлиенте определена для всех клиентских приложений. Для тонкой подстройки модуля под конкретное клиентское приложение дополнительно введены инструкции ТолстыйКлиентОбычноеПриложение, ТолстыйКлиентУправляемоеПриложение, ТонкийКлиент и ВебКлиент, которые определены в соответствующих приложениях.
В обычном клиенте в обычном и управляемом режиме доступны НаКлиенте, Клиент, ТолстыйКлиентОбычноеПриложение, ТолстыйКлиентУправляемоеПриложение , НаСервере, Сервер.
В файловом варианте инструкции препроцессора #Если Сервер…, #Если Клиент…, #Если ТолстыйКлиентОбычноеПриложение или #Если ТолстыйКлиентУправляемоеПриложение… определены всегда, поэтому экземпляр кода будет присутствовать всегда.
В тонком клиенте доступны – ТонкийКлиент, НаКлиенте, Клиент.
На серверной части тонкого клиента – Сервер, НаСервере.
Во внешнем соединении – ВнешнееСоединение, НаСервере, Сервер.
Директивы компиляции
Каждая процедура и функция модуля формы, модуля команды и общего модуля управляемого приложения предваряется директивой компиляции, определяющей среду исполнения данной процедуры. Директива предваряется символом "&".
Запросы между клиентом и сервером за счет директив компиляции корректно формируются только внутри модуля обработчика. Во внешнем модуле нельзя вызвать подпрограммы разных контекстов. Нужно сначала перейти в соответствующий контекст в модуле, затем вызвать подпрограмму из общего модуля.
&НаКлиенте — определяет клиентскую процедуру (функцию); исполняется в среде клиентского приложения. В такой процедуре доступен клиентский контекст формы и вызовы любых процедур модуля.
&НаСервере — определяет серверную процедуру (функцию); исполняется в среде серверного приложения. В такой процедуре доступны данные формы, доступен серверный контекст формы и вызовы серверных и серверных внеконтекстных процедур модуля. При вызове такой процедуры данные формы будут передаваться с клиента на сервер и обратно (по окончанию вызова).
&НаСервереБезКонтекста — определяет серверную процедуру (функцию), исполняемую на сервере вне контекста формы. Переменные не могут быть внеконтекстными. В таких методах недоступен контекст формы (включая данные формы). Допустимыми являются вызовы только других внеконтекстных методов. При вызове этих методов не выполняется передача данных формы на сервер и обратно. Применение внеконтекстных методов позволяет существенно уменьшить объем передаваемых данных при вызове серверной процедуры из среды клиентского приложения;
&НаКлиентеНаСервереБезКонтекста — определяет процедуру (функцию), исполняемую в модуле формы на клиенте и на сервере, не имеющую доступа к контексту формы, данным формы, переменным, но имеющую доступ к процедурам и функциям общих модулей – серверных, не глобальных и серверных и клиентских одновременно. Сама процедура (функция) доступна для клиентский, серверных контекстных и неконтекстных процедур и функций модуля формы. Из серверных внеконтекстных методов формы допускается вызов серверных методов общих модулей;
&НаКлиентеНаСервере — определяет процедуру (функцию), исполняемую в модуле команды, выполняемую на клиенте и на сервере, имеющую доступ к процедурам и функциям общих модулей – серверных, не глобальных и серверных и клиентских одновременно, не имеющую доступ к переменным. Сама процедура (функция) доступна для клиентских серверных процедур и функций модуля команды.
Серверная процедура (функция), исполняемая вне контекста формы, (внеконтекстная) исполняется в среде серверного приложения. В такой процедуре (функции) недоступен контекст формы (включая данные формы). Допустимыми являются вызовы только других внеконтекстных процедур (функций). При вызове этих процедур (функций) не выполняется передача данных формы на сервер и обратно. Применение внеконтекстных процедур (функций) позволяет существенно уменьшить объем передаваемых данных при вызове серверной процедуры (функции) из среды клиентского приложения.
В модуле команды предопределенная процедура-обработчик ОбработатьКоманду должна предваряться директивой &НаКлиенте, так как выполнение команды происходит в клиентском приложении.
Модуль формы
В модуле формы доступны директивы компиляции – &НаКлиенте, &НаСервере, &НаСервереБезКонтекста, &НаКлиентеНаСервереБезКонтекста.
Модуль команды
В модуле команды доступны директивы компиляции – &НаКлиенте, &НаСервере, &НаКлиентеНаСервере.
Общий модуль
В общем модуле доступны директивы компиляции – &НаКлиенте, &НаСервере.
Общие модули.
Описание подпрограмм, вызываемых из различных мест. Для доступности подпрограмм извне необходимо ключевое слово Экспорт. То есть модули-то общие, но есть нюанс.
Даже при средней сложности конфигурации, подпрограммы нужно группировать в разные Общие модули. Для удобства имена Общих модулей должны отражать содержание описываемых в них процедур. При создании Общего модуля, правилом хорошего тона считается не указывать директивы компиляции. Т.е. доступность процедур и функций должна определяться свойствами самого модуля. При таком подходе в отдельных Общих модулях будут располагаться клиентские процедуры, и в отдельных Общих модулях – процедуры серверные. В названиях общих модулей рекомендуется это указывать. Например: РегламентныеПроцедурыСервер, РегламентныеПроцедурыКлиент.
Нельзя описывать глобальные переменные модуля и раздел основной программы. Т е все внешние переменные должны передаваться в подпрограммы извне.
Доступность модулей зависит от типа приложения и режима работы (Клиент, Сервер).
В отличие от остальных типов модулей (в них по умолчанию директива компиляции &НаСервере), если директиву компиляции для подпрограммы не указывать, то она будет скомпилирована во всех контекстах, определенных для модуля. Будет сделано несколько копий подпрограмм. Выбор конкретного скомпилированного экземпляра зависит от места вызова процедуры (по правилу ближайшего вызова). При этом следует учитывать, что код такой процедуры должен быть написан с учетом его доступности во всех определенных для модуля контекстах.
Модули с несколькими флагами компиляции на практике используются крайне редко. Это некоторые общие действия, доступные как на Клиенте, так и на Сервере. Обычно, это какие-то простейшие вычисления.
Подпрограммы
Функции возвращают одно значение, процедуры выполняют операции и могут изменять переданные параметры. Переменные, объявленные в теле подпрограммы, локальные.
Общие определения:
Знач - Следующий за ним параметр передается по значению. По умолчанию параметр процедуры передается по ссылке.
<Парам1>, ..., <ПарамN> - Список формальных параметров, разделяемых запятыми, может быть пуст.
=<ДефЗнач>- Установка значения параметра по умолчанию.
Экспорт - Данная процедура доступна из других программных модулей.
Описание процедуры:
Процедура <Имя_процедуры>([[Знач] <Парам1> [=<ДефЗнач>], ... ,[Знач] <ПарамN> [=<ДефЗнач>]])[Экспорт]
// Операторы;
[Возврат;]
КонецПроцедуры
Параметры:
Возврат - Завершает выполнение процедуры и осуществляет возврат. Не обязательно.
КонецПроцедуры - Обязательное ключевое слово, обозначающее конец исходного текста процедуры, завершение выполнения процедуры.
Описание функции:
Функция <Имя_функции>([[Знач] <Парам1> [=<ДефЗнач>], ... ,[Знач] <ПарамN> [=<ДефЗнач>]])[Экспорт]
// Операторы ;
Возврат <Возвращаемое значение>;
КонецФункции
Возврат <Возвращаемое значение> Завершает выполнение функции и возвращает значение.
Возврат; Завершает выполнение процедуры.
В качестве возвращаемого значения может выступать выражение или переменная, значение которого содержит результат обращения к функции.
Функции отличаются от процедур только тем, что возвращают <Возвращаемое значение>. Конец программной секции функции определяется по ключевому слову КонецФункции.
Вызов функции можно записывать как вызов процедуры, т.е. допускается не принимать от функции возвращаемое значение.
Исключения, внешний код
Попытка
ПроверяемыйПараметр = Неопределено;
Если ПроверяемыйПараметр Тогда
//код, который не будет выполнен
КонецЕсли;
Исключение
Сообщить(ОписаниеОшибки());
КонецПопытки;
Генерация исключения
ВызватьИсключение [<Выражение>]; //описание - результат вычисления Выряжение.
Выполнить("") выполнить фрагмент кода, который передается ему в качестве строкового значения. Использовать аккуратно.
Управление отображением и событиями платформы
Модули конфигурации
Модуль сеанса Выполняется при старте системы «1С:Предприятие» в момент загрузки конфигурации. Предназначен для инициализации параметров сеанса и отработки действий, связанных с сеансом работы. Исполняется в привилегированном режиме. Установка параметров сеанса выполняется в обработчике события УстановкаПараметровСеанса(). Исполнение модуля сеанса происходит до начала исполнения модуля управляемого приложения и модуля внешнего соединения. Может содержать только определения процедур и функций, может использовать процедуры из общих модулей конфигурации и не
содержит экспортируемых процедур и функций.
Модуль управляемого приложения Автоматически выполняется при загрузке конфигурации, при старте системы в режимах тонкого клиента, веб-клиента, толстого клиента в режиме управляемого приложения.
Предназначен для отработки действий, связанных с сеансом работы конечного пользователя (прежде всего обработки начала и окончания сеанса работы). Недоступен для процедур, работающих на сервере. Процедуры и функции модуля управляемого приложения, а также переменные, для которых в заголовке указано ключевое слово Экспорт, являются доступными в неглобальных клиентских общих модулях, клиентских процедурах и функциях модуля команды, клиентских процедурах и функциях модуля управляемой формы.
В контексте модуля управляемого приложения доступны часть глобального контекста, которая может исполняться в управляемом приложении; экспортируемые процедуры и функции любых клиентских общих модулей; экспортируемые процедуры и функции серверных неглобальных общих модулей, у которых установлено свойство Вызов сервера.
Модуль внешнего соединения Процедуры-обработчики событий при старте и окончании работы системы в режиме внешнего соединения (СОМ-соединения). Возможно объявление переменных, а также объявление и описание процедур и функций, которые будут доступны для внешнего приложения. Объекты, доступные извне через COM-соединение:
- экспортируемые переменные и процедуры/функции модуля внешнего соединения;
- экспортируемые переменные и процедуры/функции общих модулей:
- включение и исключение модулей целиком выполняются с помощью установки свойств общих модулей;
- включение и исключение фрагментов общих модулей выполняются с помощью инструкций препроцессора;
- глобальный контекст «1С:Предприятия».
Модуль присутствует только в сессии внешнего соединения, нет пользовательского интерфейса.
События платформы
Основные направления общей настройки платформы: внешний вид и события. Переход в элементы настройки производится через окно свойств конфигурации.
События формы
Для настройки обработки событий формы необходимо сначала создать форму вместо формы по умолчанию. ПКМ на любом добавленном элементе формы -> События выведет список доступных обработчиков событий. Или в свойствах этого элемента.
При клике будет создан обработчик события. Для обращения к активному в модуле формы используется Элементы, все хранится в Объект. Пример автоматического пересчета итоговой суммы при изменении цены или количества в табличной части:
&НаКлиенте
Процедура ПересчитатьИтоговуюСумму()
ТабЧасть = Объект.ПереченьТоваров;
ФиналСумма = 0;
Для каждого Товар из ТабЧасть Цикл
ФиналСумма = ФиналСумма + Товар.Сумма;
КонецЦикла;
Объект.СуммаПоДокументу = ФиналСумма;
КонецПроцедуры
&НаКлиенте
Процедура ПереченьТоваровКоличествоПриИзменении(Элемент)
СтрТабЧасти = Элементы.ПереченьТоваров.ТекущиеДанные;
СтрТабЧасти.Сумма = СтрТабЧасти.Цена * СтрТабЧасти.Количество;
ПересчитатьИтоговуюСумму();
КонецПроцедуры
&НаКлиенте
Процедура ПереченьТоваровЦенаПриИзменении(Элемент)
СтрТабЧасти = Элементы.ПереченьТоваров.ТекущиеДанные;
СтрТабЧасти.Сумма = СтрТабЧасти.Цена * СтрТабЧасти.Количество;
ПересчитатьИтоговуюСумму();
КонецПроцедуры
Если будет несколько документов с необходимостью пересчитывать суммы, возможно стоит сделать процедуру НаКлиенте в общих модулях, передавая туда табличную часть, текущие данные, поле для общей суммы,
Программное создание обработчика события.
ДобавитьОбработчик <Событие>, <ОбработчикСобытия>;
Добавляет обработчик события. При добавлении обработчика события производится проверка соответствия числа параметров события числу параметров метода, назначаемого в качестве обработчика.
УдалитьОбработчик <Событие>, <ОбработчикСобытия>;
Удаляет обработчик события. При удалении обработчика события производится проверка соответствия числа параметров события числу параметров метода, назначенного в качестве обработчика.
Механизм блокировок
Хорошая статья по блокировкам на ИТС, но слегка устаревшая, в 8.3.14 алгоритм пессимистичной блокировки изменен.
Очень интересная статья, исследование блокировок.
Ускорение работы при высокой нагрузке, для погружения.
В простых словах и с примерами описание управляемой блокировки
Механизмы и типы блокировок.
Критичная тема для понимания работы платформы.
Механизм объектной блокировки - механизм обеспечения целостности объекта (элемент справочника, документ, ...) средствами платформы 1С. В большинстве случаев это связано с интерактивной работой пользователей в формах: редактирование существующих объектов, удаление, создание новых и др.
Механизм транзакционной блокировки - механизм обеспечения целостности и непротиворечивости данных средствами ядра СУБД на уровне транзакций.
Отличия заключается в элементе контроля и выбора точки блокировки. К тому же, у разных СУБД разные уровни блокировок (на уровне записей или на уровне таблиц). Например, элемент справочника состоит из реквизита Наименование и табличной части Характеристики с названием и значением. С точки зрения базы данных, в ней создается основная таблица с ключом, наименованием, и дополнительная таблица Характеристики с индексом, названием, значением и ссылкой на владельца.
Блокировка на уровне объекта подразумевает наличие в БД третьей таблицы, в которой указывается, что Пользователь1 редактирует объект1. При попытке Пользователем2 изменить объект1, в операции будет отказано и до уровня старта изменений в данных дело не дойдет. Но здесь на первый план выходит алгоритм добавления и удаления данных из третьей таблицы.
Блокировка на уровне транзакции подразумевает отсутствие третьей таблицы, и при изменении данных в соответствии с логикой СУБД (либо запись об объекте1 в таблице1 и соответствующих записей в таблице2, либо целиком обоих таблиц), после успешного завершения блокировки снимаются.
- Объектная Оптимистическая. Построена на анализе номера версии объекта, хранящейся в базе данных и номера версии, помещенной в память компьютера в момент считывания данных из информационной базы. Если при записи объекта номера версий на форме и на сервере отличаются, то будет выдано предупреждение о том, что версия объекта изменилась или он был удален. Происходит автоматически при сохранении данных через механизмы формы (не через запрос) или при чтении данных (разные типы блокировок).
- Объектная Пессимистическая неявная (в форме). В тот момент, когда пользователь начинает модификацию объекта (имеется в виду в первый раз нажал на кнопку Сохранить, а не момент открытия или момент изменения данных в поле) в форме, расширение формы устанавливает пессимистическую блокировку. Если после этого другой пользователь попытается выполнить редактирование, ему будет выдано сообщение о невозможности блокировки объекта. Снимается после закрытия формы объекта либо через минуту после сохранения данных. Для отключения пессимистической блокировки в управляемых формах в свойстве основного реквизита надо снять флаг «Сохраняемые данные». Данный флаг определяет будет ли при интерактивном редактировании блокироваться данные основного реквизита, или нет.
- Объектная пессимистическая блокировка явная (в коде)
- Для управляемых форм. Используется если необходимо просто заблокировать данные на сервере пока выполняются преобразования данных на форме. Для работы с блокировками из управляемой формы без вызова сервера используются методы «ЗаблокироватьДанныеФормыДляРедактирования()» и «РазблокироватьДанныеФормыДляРедактирования()». Как и в случае неявной, контролируются флагом «Сохраняемые данные». Пессимистическая блокировка хранится в сервисе блокировок DataEditLockService кластера 1С. Увидеть блокировку конкретного объекта можно в консоли кластера в разделе Кластреры -> Информационные базы -> Блокировки
- Без формы Методы «Заблокировать()», «Разблокировать()» и «Заблокирован()», используются для объектов базы данных, существуют только на сервере. Метод «Заблокирован()» не может быть использован для проверки, заблокирован ли вообще объект базы данных, например, другими пользователями. Для этого следует использовать метод «Заблокировать()» в попытке.
&НаСервереБезКонтекста
...
Попытка
тестобъект.Заблокировать();
// что-то делаем с объектом
тестобъект.Разблокировать();
Исключение
Сообщить("Не удалось заблокировать тест");
КонецПопытки;
- Автоматические. Ответственность за блокировки полностью лежит на СУБД. Это облегчает работу, но создание информационной системы для большого количества пользователей на автоматических блокировках нежелательно (особенно для СУБД PostgreSQL, Oracle BD, т.к. при модификации данных они полностью блокируют таблицу).
- Управляемые. В управляемом режиме есть возможность использовать менеджер транзакционных блокировок данных. В этом режиме система использует гораздо более низкий уровень изоляции транзакций для MS SQL Server и IBM DB2, и блокировку на уровне записей для PostgreSQL. Это позволяет повысить степень параллельности работы пользователей.
Длительность блокировок
Детали установки блокировок
Настройка объектов конфигурации
Режим управления блокировками данных настраивается в свойствах объекта конфигурации, раздел Режим управления блокировками данных. Может быть Управляемый или Автоматический.
Шаблоны кода
Получить версию объекта на клиенте и на сервере.
&НаСервереБезКонтекста
Процедура ПолучитьВерсиюОбъектаНаСервере(ТекОбъект)
Сообщить(ТекОбъект.ВерсияДанных);
КонецПроцедуры
&НаКлиенте
Процедура ПолучитьВерсиюОбъекта(Команда)
ПолучитьВерсиюОбъектаНаСервере(Объект.Ссылка);
Сообщить(Объект.ВерсияДанных);
КонецПроцедуры
Проверка необходимости обновления.
&НаСервереБезКонтекста
Функция ВернутьВерсиюДанныхНаСервере(ТекОбъект)
Возврат ТекОбъект.ВерсияДанных;
КонецФункции
&НаКлиенте
Процедура ОболочкаОбработчика()
ВерсияНаСервере = ВернутьВерсиюДанныхНаСервере(Объект.Ссылка);
Если ВерсияНаСервере <> Объект.ВерсияДанных Тогда
ЭтаФорма.Прочитать();
ПроверкаЭлементовНаВидимость();
КонецЕсли;
КонецПроцедуры
Проверить, заблокирован ли объект
// Попытка установки блокировки
Объект = Номенклатура.ПолучитьОбъект();
Попытка
Объект.Заблокировать();
Исключение
// Данные объекта уже заблокированы.
КонецПопытки;
Проверка предположений.
Проверка факта запрета блокировки другим объектом.
&НаСервереБезКонтекста
Процедура ПроверкаПериодаБлокировкиНаСервере()
тест = Справочники.ДляТранзакций.НайтиПоНаименованию("первый");
тест2 = Справочники.ДляТранзакций.НайтиПоНаименованию("первый");
тестобъект = тест.ПолучитьОбъект();
тестобъект2 = тест2.ПолучитьОбъект();
Попытка
тестобъект.Заблокировать();
Сообщить("Объект тест заблокирован");
Исключение
Сообщить("Не удалось заблокировать тест");
КонецПопытки;
Попытка
тестобъект2.Заблокировать();
Сообщить("Объект тест2 заблокирован");
Исключение
Сообщить("Не удалось заблокировать тест2");
КонецПопытки;
КонецПроцедуры
Объект тест2 заблокировать не удалось.
Блокировка держится до конца транзакции
Механизм транзакций
Транзакция – это последовательность действий, переводящая базу данных из одного целостного состояния в другое целостное состояние.
Свойства транзакции:
- Атомарность (неделимость). После завершения транзакции все данные должны быть согласованы. Даже при простом добавлении записи может произойти рассогласование, и необходимо это обрабатывать.
- Изоляция. Это свойство обеспечивает параллельную работу пользователей и предотвращает порчу общих данных. Например, чтобы не вышло ситуации, когда 2 пользователя меняют один и тот же документ и тем самым перестирают данные друг друга. Блокировки выступают как средство обеспечения изоляции транзакции.
Особенности транзакции:
-
не поддерживаются вложенные транзакции. Так эта особенность официально звучит, однако интересно: далее в тексте встречается термин Вложенная транзакция. Понять и простить. Под этим подразумевается, что вместо дерева транзакций мы имеем дело с одноуровневым списком, и все должно быть выполнено. В случае возникновения и подавлении ошибки где-то внутри "вложенной" транзакции, все равно вся транзакция будет считаться битой.
Здесь помогает метод ТранзакцияАктивна, помогающий текущему коду понять, находится ли он внутри транзакции или его транзакция наверху.
-
при возникновении исключения в общем случае транзакция не может быть зафиксирована – при этом не важно, было ли это исключение обработано или нет
-
транзакция может быть инициирована явно в прикладном коде при использовании метода НачатьТранзакцию. Так же платформа неявным образом начинает транзакцию при любой записи в базу данных //Добавлено после экспериментов// Некоторые события (например ПриЗаписиНаСервере) входят в состав транзакции, автоматически созданной платформой. Поэтому в некоторых источниках вся процедура обработки данного события входит в транзакцию (причем код, начинающий и заканчивающий транзакцию где-то посередине), что приводит к неправильным выводам (в моем случае - "то есть если в коде присутствует начало и конец транзакции, то вся процедура попадает в транзакцию", "а зачем тогда посередине начинать транзакцию?").
Из особенностей следуют правила:
- Поскольку исключение не отменяет транзакцию сразу, но запрещает успешное завершение транзакции, то все вызовы НачатьТранзакцию с одной стороны и ЗафиксироватьТранзакцию или ОтменитьТранзакцию с другой стороны должны быть парными.
- Начало транзакции и ее фиксация (отмена) должны происходить в контексте одного метода
-
Обработка исключений должна придерживаться следующих правил:
-
метод НачатьТранзакцию должен быть за пределами блока Попытка-Исключение непосредственно перед оператором Попытка
-
все действия, выполняемые после вызова метода НачатьТранзакцию, должны находиться в одном блоке Попытка, в том числе чтение, блокировка и обработка данных
-
метод ЗафиксироватьТранзакцию должен идти последним в блоке Попытка перед оператором Исключение, чтобы гарантировать, что после ЗафиксироватьТранзакцию не возникнет исключение
-
необходимо предусмотреть обработку исключений – в блоке Исключение нужно сначала вызвать метод ОтменитьТранзакцию, а затем выполнять другие действия, если они требуются
-
рекомендуется в блоке Исключение делать запись в журнал регистрации
-
при использовании вложенных транзакций в конце блока Исключение рекомендуется добавить оператор ВызватьИсключение. В противном случае исключение не будет передано выше по стеку вызовов, там не сработает обработка исключения, внешняя транзакция не будет явным образом отменена и платформа вызовет исключение «В данной транзакции происходила ошибка»
НачатьТранзакцию(); Попытка БлокировкаДанных = Новый БлокировкаДанных; ЭлементБлокировкиДанных = БлокировкаДанных.Добавить("Документ.ПриходнаяНакладная"); ЭлементБлокировкиДанных.УстановитьЗначение("Ссылка", СсылкаДляОбработки); ЭлементБлокировкиДанных.Режим = РежимБлокировкиДанных.Исключительный; БлокировкаДанных.Заблокировать(); ... // чтение или запись данных ДокументОбъект.Записать(); ЗафиксироватьТранзакцию(); Исключение ОтменитьТранзакцию(); ЗаписьЖурналаРегистрации(НСтр("ru = 'Выполнение операции'"), УровеньЖурналаРегистрации.Ошибка,,, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке())); ВызватьИсключение; // есть внешняя транзакция КонецПопытки;
-
-
Использование вложенных транзакций приводит к усложнению кода. Принимая решение об использовании этой возможности, нужно очень взвешенно оценить решаемую задачу: возможно, это усложнение просто не оправдано.
-
Не стоит усложнять код, явно используя метод НачатьТранзакцию, когда кроме записи объекта другие действия c базой данных не делаются – платформа при записи сама откроет транзакцию.
-
Не нужно явно открывать транзакцию тогда, когда не требуется выполнять ответственное чтение данных. Например, обычно ответственное чтение не требуется при записи нового объекта (нового набора записей регистра).
-
При использовании методов ПолучитьОбъект (или Прочитать для наборов записей) необходимо анализировать должно ли чтение быть отвественным и в зависимости от этого принимать решение о явном использовании метода НачатьТранзакцию.
-
Если метод рассчитан на вызов только в рамках уже открытой транзакции (например, метод предназначен для вызова только из событий ПередЗаписью, ОбработкаПроведения и т.п.) в общем случае явным образом открывать в нем транзакцию не имеет никакого практического смысла.
-
При необходимости повысить качество сообщений об ошибках – на каждом уровне разработчик может предусмотреть свою обработку исключений, для чего, возможно, потребуется открыть вложенную транзакцию.
Пример. Вызывается метод ДобавитьЭлектроннуюПодпись. Внутри, если что-то пошло не так, нужно обработать исключение и добавить текст вида: «Не удалось добавить электронную подпись к объекту %ПредставлениеОбъекта% по причине:%ОписаниеОшибки%». В противном случае исключение будет обработано выше по стеку вызовов, например, при записи файла и будет выдано сообщение вида: «Не удалось записать файл %ИмяФайла% по причине: %ОписаниеОшибки%», где в «%ОписаниеОшибки%», будет просто указание на строчку кода и пользователю будет непонятно, зачем вообще программа записывала файл, если он просто его подписывал.
-
При обработке исключения, если транзакция все еще активна, например, исключение возникло во вложенной транзакции, нельзя обращаться к базе данных, так как это приведет к исключению «В этой транзакции уже происходили ошибки». При этом нужно учитывать, что обращение к базе данных может быть неявным, например, для получения представления ссылки.
-
-
В общем случае в рамках одной транзакции нужно выполнять только те действия, которые неделимы, исходя из бизнес-логики.
Пример. При проведении документа записывается документ и его движения в регистрах. Если не прошла запись хотя бы в один регистр вся операция проведения должна быть отменена.
-
Следует избегать транзакций, которые выполняются длительное время.
Например, неправильно: для загрузки адресного классификатора записывать все данные, относящиеся к одной версии классификатора в одной транзакции, для того, чтобы в случае ошибки откатить целиком загружаемую версию классификатора. Т.к. данных по одной версии классификатора много (объем около 1 Гб), то для выполнения такой транзакции, во-первых, может не хватить оперативной памяти (особенно при использовании файловой информационной базы на 32-разрядной ОС), а, во-вторых, такая операция будет выполняться достаточно долго и ее нельзя будет оптимизировать за счет выполнения в несколько потоков.
Правильно: разбить загрузку новой версии классификатора на небольшие порции так, чтобы запись порции в одной транзакции не превышала 20 секунд в условиях высоконагруженной информационной системы и реализовать функциональность по откату к предыдущей версии в случае ошибки. Максимальная продолжительность указана исходя из того, что время ожидания установки транзакционной блокировки данных в информационной базе по умолчанию равно 20 сек.
-
Чем дольше выполняется транзакция, тем большее время будут заняты ресурсы сервера 1С:Предприятия и СУБД. Как правило длинные транзакции занимают следующие ресурсы:
-
в ходе выполнения транзакции все изменения в базе данных записываются в журнал транзакций, что необходимо для возможности откатить транзакцию;
-
блокировки, установленные в транзакции, остаются до конца транзакции
-
на сервере 1С:Предприятия блокировки занимают оперативную память
-
другие ресурсы, необходимые самой бизнес-логике, которая выполняется в транзакции.
-
-
Если две транзакции пересекаются по блокируемым ресурсам, то транзакция, которая начала выполняться позже, будет ожидать возможность установления блокировки ограниченное время (по умолчанию – 20 секунд), после чего будет завершена с исключением «Превышено время ожидания установки блокировки». Поэтому длинные транзакции могут сильно снижать удобство параллельной работы пользователей.
Возникновение таких исключений – это повод провести анализ действий, которые выполняются в конфликтующих транзакциях
-
В рамках транзакции нужно стремиться выполнять минимум действий – только те, которые нельзя в соответствии с бизнес-логикой выполнять вне транзакции.
-
Обязательное использование транзакции в случае, если для ускорения операции записи в регистр используется отключение итогов, такую операцию вместе с отключением и включением итогов необходимо выполнять в транзакции, иначе в других сеансах может возникнуть ошибка при получении среза последних.
Проверка понимания.
Определение и граница использования транзакции. Транзакции - нечто неделимое, возвращающее все в предыдущее состояние. Это осталось в голове после заумных текстов без тестов лапками. Первым, что пришло в голову - восстановить значение реквизита :) Обработка с полем ввода ТестовоеЧисло, 0 по умолчанию.
&НаСервере
Процедура БезОбработкиОшибокНаСервере()
НачатьТранзакцию();
ТестовоеЧисло = 5;
ВызватьИсключение "Число не то!";
ЗафиксироватьТранзакцию();
КонецПроцедуры
&НаКлиенте
Процедура БезОбработкиОшибок(Команда)
БезОбработкиОшибокНаСервере();
КонецПроцедуры
Не удалось! Ошибка сгенерировалась, но ТестовоеЧисло стало 5. Ведь транзакции актуальны при изменении данных в базе, т е SQL запрос обрамляется чем-то типа "BEGIN ... COMMIT". Мой косяк, поехали дальше.
Ошибка при создании элемента справочника. Справочник Города.
&НаСервереБезКонтекста
Процедура НовыйЭлементСправочникаНаСервере()
НачатьТранзакцию();
НовыйГород = Справочники.Города.СоздатьЭлемент();
НовыйГород.Наименование = "Тестовый город";
НовыйГород.Записать();
НовыйГород2 = Справочники.Города.СоздатьЭлемент();
НовыйГород2.Наименование = "Тестовый город 2";
НовыйГород2.Записать();
ВызватьИсключение "Город не правильный!";
ЗафиксироватьТранзакцию();
КонецПроцедуры
Да, тестовые города не создались. Получилось!
Вложенные транзакции (или то чего нет).
&НаСервереБезКонтекста
Процедура ВложеннаяТранзакция()
НачатьТранзакцию();
Попытка
НовыйГород = Справочники.Города.СоздатьЭлемент();
НовыйГород.Наименование = "Тестовый город вложенный";
НовыйГород.Записать();
ВызватьИсключение "Город не правильный!";
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
КонецПопытки;
КонецПроцедуры
&НаСервереБезКонтекста
Процедура ВложенныеТарнзакцииНаСервере()
НачатьТранзакцию();
НовыйГород = Справочники.Города.СоздатьЭлемент();
НовыйГород.Наименование = "Тестовый город внешний";
НовыйГород.Записать();
ВложеннаяТранзакция();
ЗафиксироватьТранзакцию();
КонецПроцедуры
Во вложенной транзакции мы подавляем исключение - и вся транзакция тихо не выполняется. Ни один город не создан. Я не получил вообще никакого отклика от платформы, что и логично. Теперь попробуем добавить во внешний код обработку ошибок.
&НаСервереБезКонтекста
Процедура ВложеннаяТранзакция()
НачатьТранзакцию();
Попытка
НовыйГород = Справочники.Города.СоздатьЭлемент();
НовыйГород.Наименование = "Тестовый город вложенный";
НовыйГород.Записать();
ВызватьИсключение "Город не правильный!";
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
КонецПопытки;
КонецПроцедуры
&НаСервереБезКонтекста
Процедура ВложенныеТарнзакцииНаСервере()
НачатьТранзакцию();
Попытка
НовыйГород = Справочники.Города.СоздатьЭлемент();
НовыйГород.Наименование = "Тестовый город внешний";
НовыйГород.Записать();
ВложеннаяТранзакция();
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
Сообщить("Исключение было поймано");
КонецПопытки;
КонецПроцедуры
Вполне логично, что сообщение не было сформировано.
Проверка функции ТранзакцияАктивна.
&НаСервереБезКонтекста
Процедура НовыйЭлементСправочникаНаСервере()
Сообщить(ТранзакцияАктивна());
НачатьТранзакцию();
НовыйГород = Справочники.Города.СоздатьЭлемент();
НовыйГород.Наименование = "Тестовый город 3";
НовыйГород.Записать();
Сообщить(ТранзакцияАктивна());
ЗафиксироватьТранзакцию();
Сообщить(ТранзакцияАктивна());
КонецПроцедуры
Ожидаемый вывод: Нет, Да, Нет. Теперь проверим факт из статьи о блокировках о возникновении блокировки и как следствие транзакции при чтении (это так я понял текст)
&НаСервереБезКонтекста
Процедура ТранзакцияПриЧтенииНаСервере()
МойГород = Справочники.Города.НайтиПоНаименованию("Иркутск");
Сообщить(ТранзакцияАктивна());
НовыйГород = Справочники.Города.СоздатьЭлемент();
НовыйГород.Наименование = "Тестовый город 3";
НовыйГород.Записать();
Сообщить(ТранзакцияАктивна());
КонецПроцедуры
&НаКлиенте
Процедура ТранзакцияПриЧтении(Команда)
ТранзакцияПриЧтенииНаСервере();
КонецПроцедуры
И получил Нет, Нет. Видимо что-то не так понял. Аналогичный результат при поэлементном чтении всего справочника. После внимательного рассмотрения, о транзакции в пределах процедуры было сказано для обработки события ПриЗаписиНаСервере (в случае сохранения данных через форму). Чтож, проверим это. Если транзакция есть, то данный код не запишет данные.
&НаСервере
Процедура ПриЗаписиНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
Отказ = ТранзакцияАктивна();
КонецПроцедуры
И да, создать объект не удалось, значит транзакция была активна!
Количество выполненных действий при исключении во вложенной транзакции. Смоделируем ситуацию: при входе во вложенную транзакцию происходит подавленная ошибка. Причем только одна ошибка в середине процесса. Сколько раз выполнится внешняя транзакция? Ведь в одном из предыдущих примеров исключение из вложенной транзакции поймано не было.
&НаСервереБезКонтекста
Процедура ВложеннаяТранзакция()
НачатьТранзакцию();
Попытка
НовыйЭлемент = Справочники.ДляТранзакций.СоздатьЭлемент();
НовыйЭлемент.Наименование = "Тестовый элемент внутренний";
НовыйЭлемент.Записать();
ВызватьИсключение "Ошибка!";
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
Сообщить("Ошибка во вложенной транзакции");
КонецПопытки;
КонецПроцедуры
&НаСервереБезКонтекста
Процедура ТестТранзакцииНаСервере()
НачатьТранзакцию();
Попытка
Для сч = 1 По 5 Цикл
НовыйЭлемент = Справочники.ДляТранзакций.СоздатьЭлемент();
НовыйЭлемент.Наименование = "Тестовый элемент внешний " + Строка(сч);
НовыйЭлемент.Записать();
Сообщить("Попытка записи " + Строка(сч) + " внешнего элемента.");
//Если сч = 3 Тогда
// ВложеннаяТранзакция(); //ошибка в середине
//КонецЕсли;
КонецЦикла;
ВложеннаяТранзакция();//ошибка в конце
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
Сообщить("Исключение было поймано");
КонецПопытки;
КонецПроцедуры
Сначала все логично. В указанном варианте (он повторяет предыдущий эксперимент) выведено 5 сообщений и "Ошибка во вложенной транзакции". Сообщение "Исключение было поймано" не отображается.
А дальше ждал сюрприз. Если раскомментировать условие (ошибка на третьем шаге) то получается какая-то бабуйня: выведено 3 сообщения, сообщение "Ошибка во вложенной транзакции" и сообщение "Исключение было поймано"! То есть исключение транслируется наверх, если происходит между выполняемыми действиями. Однако если после выполняемых действий, но до фиксации транзакции - ошибка не транслируется наверх, а транзакция тихо откатывается.
Администрирование
Создание или добавление информационной базы
Под информационной базой в 1С понимается объединение ядра системы управления базами данных (СУБД) и алгоритмов платформы 1С.
После запуска 1С:Предприятие, создание и добавление баз осуществляется нажатием на кнопку "Добавить"
- Создание новой базы:
- Выбрать "Создание новой информационной базы", нажать Далее
- Выбрать "Создание информационной базы без конфигурации", нажать Далее
- Указать название базы, это название будет отображаться в списке информационных баз. Вариант "На данном компьютере..." создает файловую базу, вариант "На сервере..." - сетевую базу.
- Для файловой указать директорию размещения базы
- Добавление существующей базы
- Выбрать "Добавление в список существующей информационной базы"
Структура решения и обновление
Общая информация
Режимы работы 1С
Существуют два режима работы 1С - файловый и клиент-серверный. Эти режимы относятся только к способу хранения данных. Т.е. возможно например настроить работу web версии для файлового режима. При работе в файловом режиме требуется общая папка, в которой находятся файлы. При работе с 1С в клиент-серверном режиме требуется сервер 1С:Предприятия и сервер базы данных (MSSQL или Postgresql).
Следовательно, архивация в файловом режиме - хоть простым копированием. Архивация/восстановление в клиент-серверном может быть выполнена при помощи инструментов сервера баз данных без использования средств 1С.
Поэтому, зная структуру таблиц, можно получить доступ к данным напрямую средствами сервера базы данных и, как следствие - используя любой язык программирования. Но это очень сложный путь.
Возможно, есть путь по созданию/обновлению структуры данных в БД напрямую, имея только конфигурацию.
Термин Конфигурация
Под термином "конфигурация" понимаются различные элементы, что вызывает путаницу.
Конфигурация - настройки прикладного решения (включая модули, ...). Не включает в себя пользовательские данные (например, конкретные записи в справочнике).
Информационная база - данные + конфигурация.
Информационная база.
Расширение файла: dt
Сохранение: Администрирование -> Выгрузить информационную базу
Полное восстановление: Администрирование -> Загрузить информационную базу. Нет сравнений конфигураций.
Поскольку данные и конфигурация в одном флаконе, этот способ нужен только для полного сохранения для последующего восстановления "Как есть".
Конфигурация
Конфигурацию можно сохранить 3 способами:
В виде файлов |
В виде файла |
В виде обновления конфигурации |
|
Описание |
Элементы конфигурации сохраняются в отдельных файлах, описание - в xml файлах. Заменяет существующую конфигурацию. |
Полная конфигурация в виде одного файла в собственном формате. Можно как заменить существующую конфигурацию, так и сравнить и найти отличия. |
Инкрементная конфигурация в виде одного файла в собственном формате. Для использования требуется установленная предыдущая версия конфигурации. |
Расширение |
Директория с xml файлами или zip архив директории |
.cf |
.cfu |
Сохранение |
Конфигурация -> Выгрузить конфигурацию в файлы |
Конфигурация -> Сохранить конфигурацию в файл |
Конфигурация -> Поддержка -> Обновить конфигурацию |
Восстановление |
Конфигурация -> Загрузить конфигурацию из файлов |
Конфигурация -> Загрузить конфигурацию из файла |
Конфигурация -> Поставка конфигурации -> Создать файлы поставки и ... |
В контексте влияния на данные, обновление конфигурации само по себе ограничивается созданием/удалением шаблонов объектов конфигурации (например реквизит справочника), создание новых данных не производится. Для обновления в общем случае требуется обновление конфигурации и внешняя обработка (например, заполнение значений по умолчанию в случае добавления обязательного реквизита). Также следует, что возврат к предыдущей конфигурации в общем случае невозможен. Далее термин "обновление" используется только в части обновления конфигурации.
Поддержка конфигурации
Этот термин определяет возможность обновления через файл обновления конфигурации.
У конфигурации есть 3 параметра: Имя конфигурации, Поставщик и Версия. Их можно увидеть и (если разрешено) изменить в свойствах конфигурации. У обновления задаются эти же параметры + версии, с которых можно обновиться. При несовпадении одного из этих параметров файл обновления конфигурации платформа запретит использовать файл обновления.
Изменение статуса поддержки
Конфигурация без поддержки или Конфигурация с поддержкой с возможностью редактирования -> Конфигурация с поддержкой без возможности редактирования. Получится, если изначально данная конфигурация/база была создана из конфигурации с поддержкой и есть файл конфигурации с поддержкой поставщика. Вариант "Импорт из файла с неправильным поставщиком - Изменение поставщика - Применение обновления" не прошел. Удалось сначала загрузить конфигурацию в виде файла и затем обновиться.
Конфигурация с поддержкой без возможности редактирования -> Конфигурация с поддержкой с возможностью редактирования. Конфигурация - Поддержка - Настройка поддержки. В окне нажать "Включить возможность изменения".
Конфигурация с поддержкой с возможностью редактирования -> Конфигурация без поддержки. Конфигурация - Поддержка - Настройка поддержки. В окне нажать "Снять с поддержки".
Создание файла обновления конфигурации
Настройка поставщика и версии
ПКМ на корне конфигурации - Свойства
В разделе Разработка настроить параметры Поставщик и Версия
Создать обновление командой Конфигурация - Поставка конфигурации - Создать файлы поставки и обновления конфигурации. Нужно настроить каталог хранения конфигураций. Для этого нажать на кнопку Каталог файлов поставки, в нем будут создаваться директории в соответствии с номерами версий.
Есть 3 группы: файл поставки, файл обновления и конфигурации для обновления. В файл поставки сохранится полная копия конфигурации. В конфигурации для обновления добавляются файлы предыдущих конфигураций. В файл обновления сохранятся обновления для каждого из файлов предыдущих конфигураций.
Абсолютное значение версии не анализируется, главное - чтобы строковое представление номера версии было в списке возможных конфигураций для обновления.
Если конфигурация на поддержке была изменена, то дальнейшее обновление будет проводиться с помощью сравнения конфигураций.
Пользователи и роли
Пользователи
Для пользователя задается Имя, Полное имя и адрес электронной почты. На вкладке Дополнительно указываются роли.
Для заполнения реального профиля этих полей явно будет мало, поэтому используют следующую схему:
- Создается справочник (например Пользователи), в нем указывают необходимые реквизиты. Можно добавить дополнительные объекты, в которых есть связь со справочником Пользователи. Например, для бизнес процессов дополнительно создается справочник РолиИсполнителей (этот справочник в общем случае никак не связан с Ролями в контексте назначенных ролей пользователю) и регистр сведений РегистрАдресации. Подробнее см. в Общая информация о задачах
- Один из реквизитов (обычно Наименование) в справочнике Пользователи на уровне сравнения строк должен соответствовать Имени пользователя. Затем создается минимум один параметр сеанса, в который при авторизации сохраняется ссылка на справочник Пользователи. После этого через данную ссылку возможно получить всю дополнительную информацию по текущему пользователю. Для удобства и снижения количества запросов к БД стоит для часто используемых данных создать параметры сеанса и сохранять в них данные при авторизации.
Программное добавление пользователя
ПользовательИБ = ПользователиИнформационнойБазы.СоздатьПользователя();
ПользовательИБ.Имя = "ИвановИИ";
ПользовательИБ.ПолноеИмя = "Иванов Иван Иванович";
ПользовательИБ.АутентификацияОС = Ложь;
ПользовательИБ.АутентификацияOpenID = Ложь;
ПользовательИБ.АутентификацияСтандартная = Истина;
ПользовательИБ.ЗапрещеноИзменятьПароль = Ложь;
ПользовательИБ.ПоказыватьВСпискеВыбора = Истина;
ПользовательИБ.Пароль ="";
//ПользовательИБ.ОсновнойИнтерфейс = Метаданные.Интерфейсы[""];
//ПользовательИБ.Язык = Метаданные.Языки[""];
//ПользовательИБ.Роли.Добавить(Метаданные.Роли[""]);
//ПользовательИБ.Роли.Добавить(Метаданные.Роли.АдминистраторСистемы);
//ПользовательИБ.РежимЗапуска = РежимыЗапуска[""];
ПользовательИБ.Записать();
НовыйПользователь = Справочники.Пользователи.СоздатьЭлемент();
НовыйПользователь.Наименование = "ИвановИИ";
НовыйПользователь.ОбменДанными.Загрузка = Истина;
НовыйПользователь.ИдентификаторПользователяИБ = ПользовательИБ.УникальныйИдентификатор;
НовыйПользователь.Недействителен = Ложь;
НовыйПользователь.Подготовлен = Истина;
НовыйПользователь.Записать();
Т е можно сделать отдельную обработку для создания пользователя и настройки ролей (ролей в контексте системы и в контексте расширенных параметров за счет справочников/...), из полей которой брать нужные параметры. Можно также добавить создание записей в дополнительных справочниках/... Можно усовершенствовать до создания шаблонов прав доступа, и создавать пользователей без необходимости создания множества записей в разных таблицах, без повторного ввода данных и вероятности где-то ошибиться при ручном вводе.
Скорее всего, есть готовые обработки (если нет, то через Метаданные и пару недель кодирования это реализуется), которые создадут базовые матрицы доступа по всем пользователям для упрощения контроля предоставления прав.
Контроль итоговых прав и выяснения, почему конкретный Петя не видит нужное - на самом деле не тривиальная задача, поскольку классический термин "права доступа" в 1С объединяется с классическим термином "правила отображения". Правила отображения могут быть простыми условиями в рамках запроса в одной из форм, могут размещаться в разных частях конфигурации. А механизм RLS - просто способ неявного автоматического добавления текста условий к исполняемому запросу + небольшие ограничения (неясно практически для чего они нужны). Понять и простить.
Роли
После добавления роли, нужно обновить БД клавишей F7 чтобы роль отобразилась в списке ролей пользователей.
Ролевая модель доступа. Роли независимые, один уровень. Иерархии ролей нет. У одного пользователя может быть несколько ролей. При нескольких ролях у пользователя приоритет разрешения. Если хотя бы в одной роли есть разрешение, то доступ будет разрешен, если во всех ролях есть запрещение, то доступ будет запрещен.
Роли можно копировать для упрощения настроек.
&НаСервере
Процедура ПросмотретьРолиПользователяСервер()
СписокРолей = Новый Массив;
Роли = ПользователиИнформационнойБазы.ТекущийПользователь().Роли;
Для каждого роль из роли цикл
Сообщить(роль.Имя);
КонецЦикла
КонецПроцедуры
Права доступа могут настраиваются с точностью до записи базы данных (например у одного пользователя может быть доступ к одним записям справочника Контрагенты, у другого - к другим),
Все права делятся на основные и интерактивные. Основные права (чтение, добавление, изменение, удаление) это разрешения на действия, выполняемые над элементами данных системы или над всей системой в целом, и проверяются независимо от способа обращения к данным. Интерактивные права это разрешения на действия, выполняющиеся пользователем интерактивно. Проверяются при выполнении интерактивных операций стандартными способами. В клиент-серверном варианте проверка основных прав выполняется на сервере, интерактивных на клиенте.
Проверку интерактивных прав доступа можно обойти, если создать в конфигураторе собственную форму объекта и заменить стандартные команды собственными. Проверку основных прав обойти нельзя. Допускается установка основного права и сброс интерактивного, но не наоборот.
Основные и интерактивные права взаимосвязаны. Целостность взаимных связей отслеживается системой автоматически, при установке подчиненного права устанавливаются родительские, при снятии родительского удаляются все подчиненные.
Иерархия прав
Права корневого элемента конфигурации. Устанавливается набор прав в контексте способов доступа, административных функций. Деление на группы субъективно, для моего удобства.
Право | Действия |
Способы взаимодействия | |
Тонкий клиент | право запуска тонкого клиента |
Веб клиент | право запуска веб-клиента |
Мобильный клиент | право запуска мобильного клиента |
Толстый клиент | право запуска толстого клиента |
Внешнее Соединение | право взаимодействия между базами 1С по COM технологии в качестве сервера (про деление на тип сервер / клиент предположение, не проверял) |
Automation | возможность взаимодействия между базами 1С по COM технологии или использование внешнего OLE соединения в качестве клиента. Например вызов сервера автоматизации OLE MS Office. (про деление на тип сервер / клиент предположение, не проверял) |
Управление функциями и данными | |
Администрирование данных |
право административных действий над данными. В право входит:
Не позволяет открыть конфигурацию в конфигураторе, т е для манипулирования данными через созданные процедуры в режиме Предприятие. |
Администрирование |
предоставляет полный доступ к любым данным и функциям. Подчинено праву Администрирование данных.
|
Администрирование Расширений Конфигурации | управляет доступом к интерфейсу управления расширениями (как интерактивному, так и программному) в режиме «1С:Предприятие». В безопасном режиме администрирование расширений невозможно. |
Обновление Конфигурации Базы Данных | позволяет выполнять обновление конфигурации базы данных в неинтерактивном (не через конфигуратор) режиме, т е через обработку. Не позволяет в конфигураторе открыть конфигурацию. |
Режим технического специалиста | Похоже из практического позволяет получить ссылку на текущий объект или перейти по существующей ссылке. |
Регистрация в системе взаимодействия | Мутное право. Вроде требует полного доступа к базе, но при установке этого права, административные права не устанавливаются. Хз. |
Монопольный режим и статус пользователей | |
Монопольный Режим | право на использование монопольного режима |
Завершение монопольного режима при начале сеанса | Сеанс другого пользователя с монопольным режимом может быть завершен при начале нового сеанса пользователя с правом ЗавершениеМонопольногоРежимаПриНачалеСеанса. |
Активные пользователи | Просто просмотр списка активных пользователей. |
Журнал регистрации | Просмотр журнала авторизации пользователей. |
Доступные типы интерфейсов в режиме Предприятие |
|
5 штук, говорят сами за себя | |
Возможность запуска внешних обработок/отчетов |
|
Интерактивное открытие ... (2 штуки, также ясно). | |
Вывод | Возможность копирования в буфер, печати, сохранения в файл |
Другое | |
Сохранение данных пользователя |
Если право выключено, то:
|
Дочерние классы конфигурации. Основные и интерактивные. Основные (неинтерактивные) рассматривались ранее. Интерактивные делятся на операции с обычными элементами, с предопределенными, и историей данных. Есть специфичные права для конкретных классов, например для бизнес процессов - Старт, интерактивный старт и интерактивная активация. Сложность в том, что при жесткой политике доступа, некоторые функции (из-за связанного использования) могут требовать права к другим объектам. Поэтому желательно автоматическое тестирование при настройке прав (следующий раздел).
Неявное использование прав доступа и ускорение работы
Если необходимо часть действий выполнять без учета установленных ограничений, а полные права на эти объекты давать из соображений безопасности не стоит, следует вынести эти действия в привилегированные модули или явно включать и выключать привилегированный режим в соответствующих местах программного кода.
Объекты конфигурации могут выполнять обращения к некоторым полям базы данных неявно. При этом наложение
ограничений доступа выполняется способом «все», что может приводить к неожиданным сообщениям о нарушении прав доступа. Поэтому ограничивать доступ к таким полям нельзя.
Включение автонумерации или контроля уникальности номеров объектов приводит к неявному чтению поля Код (для документов, бизнес процессов и задач – Номер) при создании нового объекта и при его записи. Если в справочниках в качестве серии кодов выбрано «в пределах подчинения», то происходит неявное чтение полей Код, Родитель. Если используется иерархия групп и элементов, то кроме этого неявно считывается поле ЭтоГруппа. При выборе в качестве серии кодов «в пределах подчинения владельцу» неявно будет выполняться чтение полей Код и Владелец.
Если при записи документа, бизнес-процесса или задачи установлен режим автоматического определения времени, то при записи будет неявно выполняться чтение полей Дата и Ссылка. Поэтому чтение полей Дата и Ссылка должно быть разрешено.
Также рекомендуется проиндексировать реквизиты, которые используются в ограничениях доступа. Ускорение работы с использованием индексов достигается за счет того, что индекс имеет структуру, оптимизированную под поиск, например, сбалансированного дерева. Но индексы занимают дополнительный объем памяти, поэтому перед созданием индекса следует убедиться, что планируемый выигрыш в производительности запросов превысит дополнительную затрату ресурсов компьютера на поддержание индекса.
Использование нескольких таблиц и соединений в ограничениях доступа приводят к усложнению запроса. Поэтому рекомендуется реквизиты, на которые опирается определение доступности записей, включать в состав самого объекта конфигурации, а не обращаться к ним через точку. Это приведет к хранению избыточной информации, но
позволит увеличить скорость выполнения запроса.
Ограничения доступа на уровне записей базы данных
Использовать в случае крайней необходимости!
Механизм RLS (Record Level Security). Нагружает систему дополнительными запросами.
Настраивается только для основных прав. Для регистров накопления, бухгалтерского учета и расчета условия позволяют разграничить доступ по значениям измерений (для регистров бухгалтерского учета по балансовым измерениям), а для объектных данных и регистров сведений условия позволяют разграничивать доступ к данным по любым полям.
Для операций изменения, добавления и удаления можно задать только одно условие, а для операции чтения можно задать несколько ограничений доступа на уровне записей.
Способы настройки ограничений:
<Прочие поля> | Конкретное имя поля | |
Способ установки ограничения | На всю запись | На отдельное поле записи |
Использование при запросе | Будет накладываться для всех полей объекта, кроме полей, для которых ограничения заданы явным образом | Условие будет накладываться только в том случае, если в запросе присутствует поле, для которого задано ограничение |
Данные могут быть выбраны из базы запросом или при помощи объектной техники. При использовании объектного чтения объект всегда будет считан из базы целиком. При использовании запроса есть возможность явно указать только необходимые поля, поэтому если в запрос не попадут поля с ограничениями, то данные записей будут предоставлены. Есть дополнительная деталь. Существует два способа функционирования ограничений доступа:
- Все. Операция должна быть выполнена над всеми подразумеваемыми данной операцией объектами базы данных. Если при выполнении такой операции должны быть прочитаны или изменены объекты базы данных, для которых не выполняются соответствующие ограничения доступа, то операция завершается аварийно из-за нарушения прав доступа
- Разрешенные. При выполнении операции над данными должны быть прочитаны только те объекты базы данных, которые удовлетворяют соответствующим ограничениям доступа. Объекты базы данных, не удовлетворяющие ограничениям доступа, при выполнении такой операции считаются отсутствующими и на результат операции не влияют.
При отображении динамических списков используется способ «Разрешенные», а при получении объектов средствами встроенного языка и при записи объектов в базу данных применяется способ «Все». В запросах способом функционирования ограничений можно управлять. Если в тексте запроса используется ключевое слово РАЗРЕШЕННЫЕ, то работа ограничений выполняется в соответствии с одноименным способом, в противном случае используется способ «Все».
Пример отличия в исполнении запроса в режиме ВСЕ и в режиме РАЗРЕШЕННЫЕ. В таблице есть поле Контрагенты, на него установлено ограничение на наименование. Есть и как записи с данным неименованием, так и
Текст первого запроса:
ВЫБРАТЬ
Контрагенты.Наименование КАК Наименование
ИЗ
Справочник.Контрагенты КАК Контрагенты
Текст второго запроса
ВЫБРАТЬ РАЗРЕШЕННЫЕ
Контрагенты.Наименование КАК Наименование
ИЗ
Справочник.Контрагенты КАК Контрагенты
В первом случае будет ошибка "... недостаточно прав ...". Второй запрос вернет список, проходящий по установленному ограничению.
Язык ограничения доступа к данным.
Подмножество языка запросов. В нем необходимо описать условие (секцию ГДЕ запроса). Такая секция будет добавляться к любым запросам при обращении к этому объекту. Если условие для объекта
принимает значение Истина, значит, операция выполняется. Особенности языка:
- В запросе всегда присутствует одна таблица в качестве источника данных – это таблица объекта, на который накладывается ограничение
- В запросе доступны только секции ИЗ и ГДЕ языка запросов
- В условиях можно указывать параметры сеанса и функциональные опции в качестве параметров запроса
- Не допускается применение оператора В ИЕРАРХИИ и предложения ИТОГИ
- Нельзя использовать виртуальные таблицы регистров (например, СрезПоследних или ОстаткиИОбороты)
- В запросе можно использовать шаблоны, упрощающие написание ограничений.
Простейший пример ограничения. Наименование - реквизит справочника Фирмы:
Можно обращаться через точку к полям реквизитов основной таблицы
Контрагенты ГДЕ Контрагенты.Регион.Наименование = "Иркутск"
Можно использовать соединения нескольких таблиц. Например, необходимо иметь доступ только к тем контрагентам, которые указаны как основной поставщик в каком-либо товаре:
Контрагенты ИЗ Справочник.Контрагенты КАК Контрагенты
ВНУТРЕННЕЕ СОЕДИНЕНИЕ
Справочник.Товары КАК Товары
ПО
Контрагенты.Ссылка = Товары.Поставщик
Здесь явно нет секции ГДЕ, однако такое ограничение работает. Применяется следующий алгоритм:
- Запись считается доступной если в результате работы условия для одной записи таблицы основного объекта ограничения получена непустая таблица (т.е. таблица, содержащая не менее одной записи).
- Если в результате работы условия получается пустая таблица, то запись считается недоступной.
В качестве параметров в тексте запроса допустимо использовать параметры сеансов и не зависящие от параметров функциональные опции.
ГДЕ Автор = &ТекущийПользователь
Ограничения, полученные из одной роли, объединяются операцией И. Ограничения, полученные из разных ролей, объединяются операцией ИЛИ.
Инструкции препроцессора.
Дополнительная "нарезка" запроса.
#Если <Выражение> #Тогда
#ИначеЕсли <Выражение> #Тогда
#Иначе
#КонецЕсли
Выражения должны иметь тип Булево. В них можно использовать параметры сеанса. В зависимости от истинности, в текст запроса будет включено то или иное выражение. Если текст ограничения доступа содержит инструкции препроцессора, то его нельзя редактировать при помощи конструктора.
Шаблоны ограничений доступа.
Шаблоны ограничений актуальны в пределах одной роли. Текст шаблона содержит фрагмент ограничения доступа. В нем можно использовать параметры. Параметры в шаблоне выделяются символом «#». После этого символа далее можно использовать:
- Ключевое слово Параметр, после которого в скобках указывается номер параметра в шаблоне
- Ключевое слово ТекущаяТаблица – обозначает вставку в текст полного имени таблицы, для которой строится ограничение
- Ключевое слово ИмяТекущейТаблицы – обозначает вставку в текст полного имени таблицы (как строковое значение, в кавычках), к которой применяется инструкция, на текущем варианте встроенного языка
- Ключевое слово ИмяТекущегоПраваДоступа – содержит имя права, для которого выполняется текущее ограничение: ЧТЕНИЕ, ДОБАВЛЕНИЕ, ИЗМЕНЕНИЕ, УДАЛЕНИЕ
- Имя параметра шаблона – означает вставку в текст ограничения соответствующего параметра шаблона
- Символ "#" – обозначает вставку в текст одного символа "#".
В тексте ограничения используется формат #ИмяШаблона(...Параметры...). Параметры передаются в виде строки, затем добавляются в текст в виде строки (второй пример). Т е шаблоны играют роль простого шаблонизатора текста. Но это упрощение может очень сильно запутать код.
Пример шаблона ограничения по автору:
Текст шаблона:
ГДЕ #Параметр(1) = &ТекущийПользователь
Текст в ограничении
#ОграничениеПоАвтору(“Автор”)
Итог:
ГДЕ Автор = &ТекущийПользователь
Если в другом документе вместо реквизита Автор используется реквизит с именем Ответственный, то ограничение доступа:
#ОграничениеПоАвтору(“Ответственный”)
Пример шаблона ограничения с передачей "сложного" выражения
Текст шаблона:
ГДЕ #Параметр(1) = &ТекущийПользователь #Параметр(2)
Текст в ограничении
#ОграничениеПоАвтору(“Автор”, "ИЛИ ЭтоГруппа")
Итог:
ГДЕ Автор = &ТекущийПользователь ИЛИ ЭтоГруппа
Учебная версия
Доступна на официальном сайте. Нужно выбрать дистрибутив, указать имя, почту и придет ссылка на архив.
Запуск setup.exe Старый ярлык не удаляется. Но оба ссылаются на один и тот же файл.
Обновление с 8.3.8 до 8.3.26 прошло без проблем.
Монопольный режим
В большинстве случаев работы он не используется. Необходим, когда требуется очистить помеченные на удаление объекты или при свертке базы на определенную дату. Условия установки монопольного режима:
- В базе не должно быть никого
- У пользователя должны быть права по установке этого режима.
- В системе не должно выполнятся транзакций.
Установка / снятие монопольного режима:
УстановитьМонопольныйРежим(Булево);
Проверка установки режима:
МонопольныйРежим();//возвращает Истина если монопольный режим установлен
В клиент-серверном варианте однопользовательский режим не устанавливается.
Объекты конфигурации
Общая информация
Получение информации о конфигурации
Через отчет по метаданным конфигурации (в режиме Конфигуратор меню Конфигурация – Отчет по конфигурации). Имена, показанные в отчете, соответствуют именам свойств и коллекций объектов.
Ссылочное удаление (пометка удаления)
В конфигурации могут существовать связанные свойства у разных объектов. Предлагаемый алгоритм удаления:
- Объект помечается как удаляемый путем установки пометки на удаление (кнопка Del или контекстное меню). Все связанные объекты автоматически помечаются на удаление.
- Основное меню - Все функции
- Стандартные - Удаление помеченных объектов
- Можно посмотреть удаляемые объекты выбрав Выборочное удаление.
- Можно выбрать удаляемые объекты и удалить.
Удаление элемента родительского справочника.
Есть элемент (Подчиненный) в подчиненном справочнике, у которого выставлен в качестве родителя удаляемый нами элемент (Основной).
- В случае удаление через "Удалить" (Shift-Del) оба элемента тихо удалятся.
- В случае установки пометки можно увидеть все удаляемые элементы.
- При снятии пометки удаления с Основного, с Подчиненного тоже удаляется метка.
- Однако проверка ссылочной целостности происходит только в момент установки пометки. То есть если пометить на удаление Основной, затем создать второй Подчиненный, будет выдано предупреждение "Вы хотите установить в качестве владельца элемент с пометкой удаления", но пометка удаления на втором подчиненном элементе не установится. При попытке удаления через предлагаемую процедуру появится ошибка и объект не будет удален.
Но при удалении через "Удалить" (Shift-Del) все элементы (и помеченный, и непомеченный) удалятся. - Если при просмотре удаляемых объектов убрать пометку с подчиненного, оставив основной, то удаление не произойдет и будет ошибка из предыдущего пункта.
Удаление элемента справочника в случае наличия ссылки на него в табличной части.
- При установке пометки на удаление, в табличной части другого справочника элемент не помечается на удаление. В списке элементов будет отражен один элемент, однако при попытке удаления будет выдано предупреждение о наличии ссылок и элемент не будет удален и можно будет посмотреть список элементов, в которых есть ссылки.
- При удалении через "Удалить" (Shift-Del) элемент будет удален, но в табличной части другого справочника в строке со ссылкой будет надпись "Объект не найден".
- Для исправления предыдущей ситуации можно использовать Администрирование - Тестирование и исправление информационной базы
В служебных сообщениях будет выведен список элементов с битыми ссылками.
Это считается медленной процедурой и требует монопольного доступа, можно использовать внешнюю обработку
Типы данных встроенных классов
Раздел относится к классам Справочник, Документ, ПланВидовХарактеристик, ПланСчетов и ПланВидовРасчета. Идея общая для всех классов, рассмотрен пример класса Справочник.
При создании объекта появляются следующие типы (так их называют в документации) - СправочникМенеджер, СправочникСсылка, СправочникОбъект, СправочникВыборка. Эти слова используются часто. Но есть тьма вопросов, основной из которых - нахрена было сделано данное разделение терминологий. Ответ: понять и простить.
Названия типов не связаны с их использованием в коде.
СправочникМенеджер
Название типа |
Отображение в коде |
Назначение |
СправочникиМенеджер | Справочники | Содержит все СправочникМенеджер и метод ТипВсеСсылки(), позволяющий получить ссылки на типы всех справочников для последующего сравнения с типом переменной. |
СправочникМенеджер |
Справочники.ИмяСправочника | Это конкретный элемент СправочникиМенеджера. Понять и простить.
Общие действия, относящиеся к конкретному справочнику, а не к его конкретным объектам. Например, методы позволяют создать новый объект или найти объект по коду. |
СправочникСсылка
Хранит ссылку, идентифицирующую запись в таблице справочника. Внутренний идентификатор, хранящийся в реквизите Ссылка таблицы справочника. Через СправочникСсылка можно получить данные всего объекта через методы. При программной работе объект СправочникСсылка получают при поиске элемента справочника. Используется только для чтения данных. При получении ссылки на одну и ту же запись справочника разными способами, ссылки будут одинаковые (в отличие от объекта).
Получение СправочникОбъект из ссылки:
ЗаписьНоменклатураСсылка = Справочники.Номенклатура.НайтиПоНаименованию("Ручка");
ЗаписьНоменклатураОбъект = ЗаписьНоменклатураСсылка.ПолучитьОбъект();
// Здесь идут какие-то изменения
ЗаписьНоменклатураОбъект.Записать();
При первом обращении к свойству происходит запрос к БД и данные кэшируются. При обращении или раз в 20 секунд происходит проверка неизменности данных. При внешнем изменении данных, свойство, к которому происходит обращение, обновляется. Объекты в кэше очищаются через 20 минут.
СправочникОбъект.
Используется для создания, изменения и удаления объекта, для отображения и редактирования всех данных элемента справочника в форме элемента. Так как содержит весь объект, тяжелее ссылки. Очень похоже на передачу данных по ссылке и по значению. При каждом запросе на получение объекта создается новый временный объект.
Объект может быть создан с помощью менеджера справочника. В этом случае создается новый объект, которого еще нет в базе данных. Если его записать, то появится новый объект в базе данных. Объект может быть получен из ссылки. В этом случае из базы данных считывается существующий объект, на который указывает ссылка. Объект также может быть получен из выборки (СправочникВыборка). В этом случае данные объекта заполняются данными, полученными в процессе считывания выборки.
СправочникОбъект оптимизирует запись изменений в базу данных, сохраняя только изменения. Обеспечивается оптимистическая блокировка - запись заблокируется в случае изменении в базе данных после считывания. Это обеспечивает логическую целостность изменения объектов.
Существует пессимистическая блокировка, запрещающая изменения до снятия блокировки. Включается методом Заблокировать(). В основном он предназначен для блокировки объектов, редактируемых в форме. Расширение формы элемента справочника автоматически включает блокировку, чтобы пользователь был уверен что, начав редактировать объект, он сможет его записать.
Предоставляется доступ через свойства к данным объекта. Значения СправочникОбъект заполняются при считывании существующего объекта значениями из базы данных.
Проверка факта изменения в СправочникСсылка и отсутствия изменений в одном из объектов:
&НаСервереБезКонтекста
Процедура ПроверитьАктуальностьНаСервере()
ЕдиницаСсылка = Справочники.ЕдиницыИзмерения.НайтиПоНаименованию("Метр");
ЕдиницаОбъект1 = ЕдиницаСсылка.ПолучитьОбъект();
ЕдиницаОбъект2 = ЕдиницаСсылка.ПолучитьОбъект();
ЕдиницаОбъект2.Наименование = "Метр2";
ЕдиницаОбъект2.Записать();
Сообщить("В ссылке:" + ЕдиницаСсылка.Наименование);
Сообщить("В объекте 1:" + ЕдиницаОбъект1.Наименование);
Сообщить("В объекте 2:" +ЕдиницаОбъект2.Наименование);
//ЕдиницаОбъект1.Наименование = "Метр3";
//ЕдиницаОбъект1.Записать();
КонецПроцедуры
&НаКлиенте
Процедура ПроверитьАктуальность(Команда)
ПроверитьАктуальностьНаСервере();
КонецПроцедуры
Наименование в ЕдиницаОбъект1 действительно не изменилось. Если раскомментировать команды записи первого объекта, то будет ошибка:
Похоже, что обновление СправочникОбъект возможно только через повторное получение, поэтому в продуктовом решении минимум необходимо добавить обработку ошибок и, возможно, запись в цикле до успешного сохранения + понимание что же изменилось, почему, и нужно ли в принципе обновлять объект.
Получение ссылки из объекта:
СсылкаНаОбъект = МойОбъект.Ссылка;
Поскольку реквизит ссылка - это параметр в базе данных, то до записи нового объекта в ней ничего нет. Проверка:
&НаКлиенте
Процедура ДобавитьЕдиницуИзмерения(Команда)
СоздатьЕдиницуИзмерения(Объект.НоваяЕдиницаИзмерения);
КонецПроцедуры
&НаСервереБезКонтекста
Процедура СоздатьЕдиницуИзмерения(НазваниеЕдиницы)
НовыйОбъект = Справочники.ЕдиницыИзмерения.СоздатьЭлемент();
НовыйОбъект.Наименование = НазваниеЕдиницы;
Сообщить("До записи:" + НовыйОбъект.Ссылка);
НовыйОбъект.Записать();
Сообщить("После записи:" + НовыйОбъект.Ссылка);
КонецПроцедуры
СправочникВыборка
Предназначен для обхода всех элементов справочника. Считанные элементы могут быть получены в качестве значений типа СправочникОбъект, при этом они не будут повторно считываться из базы данных. Выборка считывает данные объектов целиком (все поля и все табличные части).
&НаСервереБезКонтекста
Процедура ВывестиВсеЕдиницыНаСервере()
Выборка = Справочники.ЕдиницыИзмерения.Выбрать();
Пока Выборка.Следующий() Цикл
Сообщить(Выборка.Наименование);
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Процедура ВывестиВсеЕдиницы(Команда)
ВывестиВсеЕдиницыНаСервере();
КонецПроцедуры
СправочникСписок
Предназначен для динамического просмотра данных справочника в элементе управления ТабличноеПоле (свойство Данные). Возможность считывать данные порциями. В том случае, если ни один из индексов таблицы не соответствует заданному пользователем упорядочиванию, механизм динамического просмотра не будет задействован. Может быть настроен состав считываемых полей (колонок), отбор и сортировка. Список осуществляет считывание данных порциями в процессе навигации пользователем в табличном поле. Обращение к реквизитам на чтение аналогично СправочникСсылка.
Регламентные задания
Разобраться, интересная статья
Программное создание конфигурации.
Хер. Внешний обработчик может только уведомить об отсутствии чего-либо в конфигурации, создать кодом не получится.
Тестирование
Через жопу. Статья о тестировании Используется уже другой (!) язык. Им видимо двух не хватало...
Git
Еще нужно разобраться, но вроде есть.
Класс Константы и Перечисления
Константы
Т к константы хранятся в базе данных, доступ к ним нужно получать через процедуру на сервере. В случае обращения к несуществующей константе будет сгенерировано исключение.
&НаКлиенте
Процедура ВыводКонстант(Команда)
Отобразить();
КонецПроцедуры
&НаСервере
Процедура Отобразить()
Сообщить(Константы.НазваниеОрганизации.Получить());
Константы.НазваниеОрганизации.Установить("ООО");
КонецПроцедуры
Получение одним запросом нескольких констант, их перебор и сохранение.
&НаСервере
Процедура Отобразить()
Набор = Константы.СоздатьНабор("НазваниеОрганизации, ЕщеКонстанта");
Набор.Прочитать();
Набор.ЕщеКонстанта = "Сохраненная из кода";
Набор.Записать();
КонецПроцедуры
Можно сделать единую форму ввода констант в контекстном меню "Создать форму констант". Если после создания формы создана новая константа - зайти в реквизиты созданной формы и перетащить мышью новую константу на форму.
Можно настроить обработки "ОбработкаПроверкиЗаполнения", "ПередЗаписью", "ПриЗаписи". На каждой константе нужно щелкнуть правой кнопкой -> Открыть модуль менеджера значений. Через модуль менеджера. Пример ограничения значения константы (должна быть больше 4), процедура определена в модуле менеджера значений константы Константа4.
Процедура ПередЗаписью(Отказ)
Если Значение < 5 Тогда
Сообщить("Значение константы не может быть меньше 4.");
Отказ = Истина;
КонецЕсли;
КонецПроцедуры
Перечисления
Для неизменяемых в процессе использования конфигурации значений. Вот им больше подходит термин "Константа". Задается в конфигураторе в разделе Данные. Обращения через объектный вариант напрямую по имени.
Перечисления.ВидыНоменклатуры.Материал
Класс Справочники
У всех справочников есть стандартные реквизиты: Код и Наименование. Справочник обновляется в момент обращения или изменения со стороны пользователя, при изменении другим пользователем или программным изменением автоматического обновления нет, данные кэшируются, поэтому нужно вручную обновить справочник.
Существует тип данных Составной реквизит, создается при помощи троеточия в поле настройки типа данных в свойстве реквизита.
Настройка внешнего вида
У реквизита есть свойство Использование. При создании иерархических справочников можно указать, для чего использовать этот реквизит. При использовании "Для элемента" этого реквизита не будет у группы.
Предопределенные элементы. ПКМ на справочнике -> Открыть предопределенные данные. Используется в частности для настройки значений по умолчанию в Документах, ... Для запрета удаления предопределённых элементов нужно выключить во всех ролях следующие права (по умолчанию выключены):
- «ИнтерактивноеУдалениеПредопределённыхДанных»
- «ИнтерактивнаяПометкаУдаленияПредопределённыхДанных»
- «ИнтерактивноеСнятиеПометкиУдаленияПредопределённыхДанных»
- «ИнтерактивноеУдалениеПомеченныхПредопределённыхДанных».
Подчиненные справочники. В свойствах справочника -> Владелец добавить справочник-владелец. Может быть несколько справочников-владельцев, но владелец конкретного элемента подчиненного справочника может быть один элемент одного из справочников-владельцев. Множественное владение не поддерживается. Детали удаления элемента родительского справочника
Связь параметров выбора. Предположим, необходимо хранить список наших автомобилей. Среди параметров в частности есть модель, марка, и т.д. (гос. номер, ...). У одной модели может быть несколько марок. Логично создать справочник Модель и подчиненный справочник Марка. Однако если просто в справочнике Автомобили в реквизитах указать ссылки на Модель и Марка, то при поиске марки будут отображаться все марки, а не только для выбранной модели. Для исправления этого поведения в свойствах реквизита Марка используется "Связи параметров выбора".
Табличные части. Используется для отражения информации, связанной с данным элементом, но не имеющей связанной объектной сущности. Например, для справочника "Товары" может быть создана табличная часть "ЕдиницыИзмерения".
Выбор между подчиненным справочником и табличной частью.
Это близкие элементы, поэтому нужно хорошо подумать перед выбором.
- При использовании табличной части нельзя ссылаться на строки табличной части, т.е. нельзя будет создать реквизит, соответствующий понятию «строка табличной части».
- Если в перспективе может возникнуть потребность ссылаться на подчиненные объекты, например, создавать ссылающиеся на них реквизиты документов или других справочников, то лучше сразу завести подчиненный справочник. Если же ссылка на такие сведения не имеет смысла и никогда не может быть типом какого-либо реквизита, тогда можно завести табличную часть.
Пример ситуаций и выбор между подчиненным справочником и табличной частью.
Ситуация 1 В базе данных необходимо хранить список расчетных счетов каждого контрагента. Почти наверняка в платежных документах будет необходимо, кроме контрагента, указывать его расчетный счет. Такая информация имеет объектную связь и может быть идентифицирована как "расчетный счет". Возможное решение: Справочник "Контрагенты" и подчиненный ему справочник "РасчетныеСчета" с полями "Банк", "Номер", "КоррСчет".
Ситуация 2 Для справочника "Номенклатура" нужно хранить список единиц измерения для каждого товара с указанием коэффициента пересчета в основную единицу измерения. Эти сведения подбираются из справочника "ЕдиницыИзмерения", который хранит все существующие в природе единицы измерений. Каждая строка такого подчиненного списка не имеет собственной объектной сущности, а нужна только для пересчета из одной единицы измерения в основную. Возможное решение: Справочник "Номенклатура" и табличная часть "ЕдиницыИзмерения" с полями "ЕдиницаИзмерения" и "КоэффициентПересчета".
Ситуация 3 Допустим, встроенной системы задания прав пользователей не хватает для некоторых специальных приложений. Например, часто требуется разработать механизм утверждения документов разными пользователями. Тогда для сотрудника нужно хранить список документов, которые он может утверждать, и с этим отлично справится табличная часть "УтверждаемыеДокументы" справочника "Сотрудники". Такая информация не имеет объектной связи, а просто связывает документ и сотрудника, поэтому вряд ли понадобится когда-либо в будущем создавать ссылки на нее. Возможное решение: Справочник "Сотрудники" и табличная часть "УтверждаемыеДокументы" с полем "Документ" и флажком "Утверждается". Заметим, что эту задачу также можно решить с использование регистров сведений.
Ситуация 4 Для справочника "Сотрудники" требуется хранить сведения о составе семьи сотрудника, т.е. вносить информацию о членах семьи и их родственных отношениях к сотруднику (муж, жена, сын, дочь и т.д.). Обычно эта списковая информация полностью подчинена элементу справочника "Сотрудники", и возникает мысль о том, чтобы завести табличную часть. Но если подумать, то такая информация имеет четкую объектную природу и может быть идентифицирована как "член семьи". Для некоторых приложений может потребоваться создавать ссылки на членов семьи сотрудника. Аналогичная ситуация наблюдается со сведениям об образовании и о предыдущих местах работы сотрудника. Возможное решение: Выбор между подчиненным справочником и табличной частью зависит от назначения конфигурации. Если в будущем может возникнуть потребность создавать ссылки на такие сведения, то лучше завести подчиненные справочники "СоставСемьи", "Образование" и "ТрудоваяДеятельность".
Важное замечание. Необходимо помнить, что при обращении к элементу справочника он весь, вместе со всеми табличными частями, считывается из базы данных в память. Если табличная часть содержит достаточно большое количество строк это может заметно сказаться на производительности системы.
Таким образом, табличную часть стоит использовать, если не надо хранить ссылки на элементы, и количество элементов ограничено.
Программная работа с элементами справочника
Подборка примеров кода ссылка
Поиск по реквизиту. Код обработки, есть справочник Цвета.
&НаКлиенте
Процедура ПолучитьОбъектПоНаименованию(Команда)
ТекстНаименования = НайтиОбъект(Объект.Наименование);
Сообщить(ТекстНаименования);
КонецПроцедуры
&НаСервереБезКонтекста
Функция НайтиОбъект(Наименование)
ЦвСсылка = Справочники.Цвета.НайтиПоНаименованию(Наименование);
Если ЦвСсылка = Справочники.Цвета.ПустаяСсылка() Тогда
Возврат("Цвет не найден");
Иначе
Возврат(ЦвСсылка.Наименование + ": " + ЦвСсылка.Код);
КонецЕсли;
КонецФункции
P.s. На клиент нельзя вернуть объект. Можно при желании вернуть структуру, или например ссылку, которую можно использовать в других подпрограммах:
&НаКлиенте
Процедура ПолучитьОбъектПоНаименованию(Команда)
СсылкаНаЦвет = НайтиОбъект(Объект.Наименование);
Если СсылкаНаЦвет = Неопределено Тогда
Сообщить("Цвет не найден");
Иначе
ВывестиПоСсылке(СсылкаНаЦвет);
КонецЕсли;
КонецПроцедуры
&НаСервереБезКонтекста
Функция НайтиОбъект(Наименование)
ЦвСсылка = Справочники.Цвета.НайтиПоНаименованию(Наименование);
Если ЦвСсылка = Справочники.Цвета.ПустаяСсылка() Тогда
Возврат(Неопределено);
Иначе
Возврат(ЦвСсылка);
КонецЕсли;
КонецФункции
&НаСервереБезКонтекста
Процедура ВывестиПоСсылке(ЦветСсылка)
Сообщить(ЦветСсылка.Код);
КонецПроцедуры
Создание групп или элементов.
НовыйЭлемент = Справочники.Номенклатура.СоздатьЭлемент();
НовыйЭлемент.Реквизит1 = "КакоеТоЗначение";
НовыйЭлемент.Записать();
Выборка элементов
Выборка = Справочники.Номенклатура.Выбрать();
Пока Выборка.Следующий() Цикл
ТекСсылка = Выборка.Ссылка;
Сообщить(ТекСсылка.Наименование);
КонецЦикла;
Автоматическое заполнение реквизитов. Например есть справочник Сотрудники, у которого есть реквизит Рабочий телефон. Есть справочник Автомобили, у которого есть реквизит Водитель и Рабочий телефон. Нужно, чтобы при выборе водителя, происходило заполнение рабочего телефона.
Вариант 1. В редактировании формы элемента ПКМ на реквизите - События - ПриИзменении
&НаКлиенте
Процедура ВодительПриИзменении(Элемент)
Объект.ТелефонВодителя = ПолучитьТелефон(Объект.Водитель);
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПолучитьТелефон(СсылкаНаВодителя);
Возврат СсылкаНаВодителя.РабочийТелефон;
КонецФункции
Однако, при изменении в справочнике Сотрудники внутреннего телефона, обновление не происходит.
Вариант 2. Обновление будет при создании связанных справочников Сотрудники - ТелефоныСотрудников и т. д. Обработчик, который добавляет первый указанный телефон пользователя
&НаКлиенте
Процедура ВодительПриИзменении(Элемент)
Перем Телефон;
НайтиТелефоныВодителя(Объект.Водитель, Телефон);
Если Телефон <> Неопределено Тогда
Объект.ТелефонВодителя = Телефон;
КонецЕсли;
КонецПроцедуры
&НаСервереБезКонтекста
Процедура НайтиТелефоныВодителя(СсылкаНаСотрудника, СсылкаНаТелефон)
Запрос = Новый Запрос(
"ВЫБРАТЬ
| Телефоны.Ссылка как ТелефонВодителя
|ИЗ
| Справочник.ТелефоныСотрудников КАК Телефоны
|ГДЕ
| Телефоны.Владелец = &Ссылка");
Запрос.УстановитьПараметр("Ссылка", СсылкаНаСотрудника);
Результат = Запрос.Выполнить();
Если не Результат.Пустой() Тогда
ВыборкаДетальныеЗаписи = Результат.Выбрать();
ВыборкаДетальныеЗаписи.Следующий();
СсылкаНаТелефон = ВыборкаДетальныеЗаписи.ТелефонВодителя.Ссылка;
КонецЕсли;
КонецПроцедуры
Можно доработать процедуру, возвращая массив ссылок, на клиенте сохраняя первую и сообщая остальные в виде всплывающего сообщения.
Есть косяк: При изменении владельца номера телефона, в справочнике Автомобили остается старый Водитель и не меняется ссылка на номер телефона. Возможно, необходима обработка При изменении на ТелефоныСотрудников. Типа уведомления о том, что нужно обновить данные в таком-то справочнике для такой-то записи.
Обработка события удаления элементов
Справочник Менеджеры подчинен справочнику Прайс-лист. В модуле объекта справочника Прайс-лист обработка удаления элемента.
Процедура ПередУдалением(Отказ)
НайтиПодчиненныеЭлементы(ЭтотОбъект.Ссылка, Отказ);
КонецПроцедуры
&НаСервере
Процедура НайтиПодчиненныеЭлементы(СсылкаНаОбъект, Отказ)
Запрос = Новый Запрос(
"ВЫБРАТЬ
| Менеджеры.Ссылка.Наименование как ИмяМенеджера
|ИЗ
| Справочник." + Метаданные.Справочники["Менеджеры"].Имя + " КАК Менеджеры
|ГДЕ
| Менеджеры.Владелец = &Ссылка");
Запрос.УстановитьПараметр("Ссылка", СсылкаНаОбъект);
Результат = Запрос.Выполнить();
Если Результат.Пустой() Тогда
Отказ = Ложь;
Иначе
Сообщить("Нельзя удалить элемент, так как он владелец элементов.");
ВыборкаДетальныеЗаписи = Результат.Выбрать();
СписокЗависимостей = "";
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
СписокЗависимостей = СписокЗависимостей + " " + ВыборкаДетальныеЗаписи.ИмяМенеджера;
КонецЦикла;
Сообщить(СписокЗависимостей);
Отказ = Истина;
КонецЕсли;
КонецПроцедуры
Группа или элемент
Метод «ЭтоГруппа()» возвращает 1 в случае группы и 0 в случае элемента.
Доступ к табличной части
&НаСервереБезКонтекста
Процедура ПолучитьТабличнуюЧастьНаСервере(КанцелярияСсылка)
Набор = КанцелярияСсылка.СоставНабора;
Если Набор.Количество() > 0 Тогда
Сообщить("Состав набора:");
Иначе
Сообщить(КанцелярияСсылка.Наименование + " не набор.");
КонецЕсли;
Для каждого СтрокаТаблицы из Набор Цикл
Сообщить(СтрокаТаблицы.Канцелярия.Наименование + ", " + СтрокаТаблицы.Количество + " шт.");
КонецЦикла;
КонецПроцедуры
Класс Документы и Журналы документов
Стандартные реквизиты: Номер документа и Дата документа.
Заполнение реквизита значением по умолчанию. В свойствах реквизита есть параметр Значение заполнения. Для простых типов оно заполняется вручную. Для типов СправочникСсылка список значений берется из предопределенных данных справочника.
Ввод на основании: В разделе настройки "Ввод на основании" добавляется документ, который является основой для ввода и в модуле объекта создается процедура ОбработкаОснования.
Процедура ОбработкаЗаполнения(ДанныеЗаполнения, СтандартнаяОбработка)
//{{__КОНСТРУКТОР_ВВОД_НА_ОСНОВАНИИ
// Данный фрагмент построен конструктором.
// При повторном использовании конструктора, внесенные вручную изменения будут утеряны!!!
Если ТипЗнч(ДанныеЗаполнения) = Тип("ДокументСсылка.ПрибытиеВГараж") Тогда
// Заполнение шапки
Автомобиль = ДанныеЗаполнения.Автомобиль;
Гараж = ДанныеЗаполнения.Гараж;
КонецЕсли;
//}}__КОНСТРУКТОР_ВВОД_НА_ОСНОВАНИИ
КонецПроцедуры
Обработка событий формы. Управление отображением и событиями платформы
Обработка табличной части документа:
&НаКлиенте
Процедура ПересчитатьИтоговуюСумму()
ТабЧасть = Объект.ПереченьТоваров;
ФиналСумма = 0;
Для каждого Товар из ТабЧасть Цикл
ФиналСумма = ФиналСумма + Товар.Сумма;
КонецЦикла;
Объект.СуммаПоДокументу = ФиналСумма;
КонецПроцедуры
&НаКлиенте
Процедура ПереченьТоваровКоличествоПриИзменении(Элемент)
СтрТабЧасти = Элементы.ПереченьТоваров.ТекущиеДанные;
СтрТабЧасти.Сумма = СтрТабЧасти.Цена * СтрТабЧасти.Количество;
ПересчитатьИтоговуюСумму();
КонецПроцедуры
&НаКлиенте
Процедура ПереченьТоваровЦенаПриИзменении(Элемент)
СтрТабЧасти = Элементы.ПереченьТоваров.ТекущиеДанные;
СтрТабЧасти.Сумма = СтрТабЧасти.Цена * СтрТабЧасти.Количество;
ПересчитатьИтоговуюСумму();
КонецПроцедуры
Добавление данных в табличную часть Есть справочники Канцелярия и НаборыВыдачиКанцелярии и документ ВыдачаКанцелярии. Нужно добавить опцию заполнения табличной части документа стандартными наборами. В документе нет реквизита НаборыВыдачиКанцелярии, так как наборы могут меняться, в документ может быть добавлено несколько наборов, но само название набора не важно, а фактически важен добавленный состав. На форму был добавлен реквизит СтандартныеНаборыВыдачи и кнопка Добавить набор.
&НаСервере
Процедура ПолучитьСоставНабора()
ТекСоставНабора = СтандартныеНаборыВыдачи.СоставНабора;
Для Каждого ЭлемНабора из ТекСоставНабора цикл
НовыйЭлем = Объект.ТаблицаВыдачиКанцелярии.Добавить();
НовыйЭлем.НазваниеПредмета = ЭлемНабора.Канцелярия;
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Процедура ДобавитьНабор(Команда)
ПолучитьСоставНабора();
КонецПроцедуры
Создание документа
&НаКлиенте
Процедура СоздатьНовыйДокумент(Команда)
Если СоздатьНовыйДокументНаСервере() = 0 Тогда
Сообщить("Не удалось создать новый документ");
КонецЕсли;
КонецПроцедуры
&НаСервере
Функция СоздатьНовыйДокументНаСервере()
НоваяРасходнаяНакладная=ДокРасходнаяНакладная.СоздатьДокумент();
НоваяРасходнаяНакладная.Дата= ТекущаяДата();
НоваяРасходнаяНакладная.Фирма =Справочники.Фирмы.ОсновнаяФирма;
НоваяРасходнаяНакладная.Контрагент=Справочники.Контрагенты.НайтиПоКоду("000000001");
НоваяРасходнаяНакладная.Склад=Справочники.Склады.ОсновнойСклад;
СтрокаТЧ=НоваяРасходнаяНакладная.ТЧТовары.Добавить();
СтрокаТЧ.Товар=Справочники.Номенклатура.НайтиПоКоду("000000002");
СтрокаТЧ.Цена=СтрокаТЧ.Товар.РозничнаяЦена;
СтрокаТЧ.Количество= 2;
СтрокаТЧ.Сумма=СтрокаТЧ.Цена*СтрокаТЧ.Количество;
Попытка
НоваяРасходнаяНакладная.Записать();
Возврат 1;
Исключение
Возврат 0;
КонецПопытки;
КонецФункции
Дополнительные опции:
- Нумераторы - отвечают за сквозную нумерацию для разных документов, сначала создается нумератор, затем в разделе Нумерация нужных документов указывается нумератор.
- Последовательности - отвечают за контроль целостности данных при изменении проведенного документа. Например, при изменении документа в уже закрытом периоде. Нужно разобраться.
Журналы документов
Не создают дополнительных данных. Только для визуального объединения разных документов в одном списке.
В разделе Данные в Регистрируемые документы добавляются нужные документы, в разделе Графы - поля из документов.
Класс Регистры
Детали хранения информации в регистрах
Регистр сведений, накопления, бухгалтерии, расчета относятся к необъектным сущностям. Примеры для регистра накопления и регистра сведений относятся ко всем классам регистров. Для регистра сведений есть возможность использования без регистратора, поэтому модель его использования шире.
Модель хранения данных. В базе данных хранятся записи. Запись не является объектом базы данных, нет внутреннего идентификатора. Запись полностью описывается значениями своих полей. Т е удалив некоторую запись и записав новую с точно такими же значениями всех полей, мы получим то же состояние базы данных с точки зрения логики прикладного решения. Это принципиально отличает запись от объекта в объектных сущностях, так как объект базы данных имеет внутренний идентификатор и один и тот же объект нельзя создать дважды.
Например, если у нас есть регистр накопления, хранящий движения складских запасов товаров в разрезе товаров и складов, то каждая запись полностью определяется товаром, складом и количеством. Действительно, с точки зрения логики прикладного решения такая запись описывает движение некоторого товара по некоторому складу в некотором количестве. Можно записать вторую такую же запись, и они ничем не будут отличаться, если не отличаются значения полей.
Уникальность записей. Нельзя записывать ссылки на записи в поля базы данных, но есть уникальный ключ. Для необъектных сущностей с регистратором уникальный ключ включает регистратор и номер строки. Номер строки используется для обеспечения уникальности записей и для упорядочивания записей в пределах регистратора.
Для регистров сведений не подчиненных регистратору уникальным ключ это совокупность измерений и периода, если регистр периодический. В случае подчинения регистратору уникальность поддерживается по сочетанию полей регистратор и номер строки и по измерениям и периоду. Первое определяется его подчинением регистратору, а второе его основной прикладной логикой – хранением значений ресурсов по комбинации значений измерений и периоду. Если для регистра выбрана периодичность по позиции регистратора, то в уникальный ключ по измерениям входит и регистратор, как дополнительная детализация периода в пределах секунды.
Подчинение регистратору. Записи регистров подчиненные регистратору называются движениями. Подчинение записей регистратору определяет время жизни записей. Регистратор определяет наличие этих записей. Записи регистров создаются документом в процессе проведения. При удалении регистратора подчиненные ему записи удаляются.
Записи регистров подчинены регистратору, но не являются его частью. При считывании документа подчиненные ему записи регистров не считываются, а при записи автоматически не записываются. Обеспечивается только удаление записей при удалении регистратора. Также существует возможность автоматического удаления записей при проведении и отмене проведения. Эта возможность настраивается в свойствах документа в конфигурации и является сервисной.
Наличие записей регистров не связано с состоянием "проведен" и с пометкой удаления. Допускается наличие записей и у непроведенного документа и у помеченного на удаление. Например, это используется для создания документов предназначенных для непосредственного ввода движений регистров – ручного ввода. В этом случае пользователь непосредственно вводит записи регистров и понятие проведения бессмысленно. При непосредственном изменении полей Проведен и ПометкаУдаления (без использования методов УстановитьПометкуУдаления() и записи с режимом ОтменаПроведения) удаление движений не производится.
Поэтому организация редактирования движений документа в форме сложнее, чем организация редактирования табличной части. Наиболее простой моделью использования регистров является создание движений при проведении. В этом случае достаточно реализовать запись движений в обработчике проведения, а вся остальная логика будет поддерживаться системой автоматически.
Типы данных. Тип РегистрыНакопленияМенеджер предназначен для доступа к менеджерам конкретных регистров. К нему можно обратиться с помощью свойства глобального контекста РегистрыНакопления.
Тип РегистрНакопленияМенеджер предоставляют доступ к общим действиям, относящимся к конкретному регистру накопления. С помощью его методов выполняются действия, относящиеся к регистру, а не к его конкретным записям. Например, методы менеджера позволяют создать объект, предназначенный для манипулирования записями (НаборЗаписей), получить выборку регистра и т.д.
Менеджер регистра имеет набор методов для выполнения действий связанных с основным назначением регистра. Например, для регистра накопления это получения остатков и оборотов, а у регистра сведений получение среза первых и среза последних записей. Также данные могут быть получены виртуальными таблицами запросов, в них обеспечивается большая гибкость.
Тип РегистрНакопленияНаборЗаписей предназначен для чтения, модификации и удаления записей регистра. Набор записей оперирует множеством записей отбираемых по некоторому условию. Для описания условия есть свойство Отбор. Для регистров подчиненных регистратору отбор устанавливается по регистратору.
Набор записей это коллекция, которую можно прочитать и записать. Набор записей имеет только один метод для изменения данных – Записать(). Нет понятия удаления. Набор записей может быть только записан. При этом выполняется замещение всех существующих записей удовлетворяющих текущему отбору на записи, хранящиеся в наборе. Для удаления множества записей следует установить отбор и, не добавляя записей в набор, выполнить запись набора.
Можно записать набор без замещения, параметр метода Записать(). Запись без замещения выполняет добавление записей. Будет обеспечиваться корректировка номеров строк, для обеспечения последовательной нумерации записей в пределах регистратора. Обычно используется при необходимости записи большого объема движений регистров.
Набор записей необязательно считывать, чтобы выполнить запись. Не существует понятия блокировки, поэтому при записи набора могут быть изменены данные, которые были изменены другой сессией или другим набором в этой сессии уже после считывания набора записей.
Для регистров сведений не подчиненных регистратору может использоваться отбор с различными комбинациями измерений и периода. Допускается чтение и запись набора без установки отбора. В этом случае будет выполняться чтение и соответственно запись всех записей регистра. При ошибках в написании модулей (например, пропущенном вызове чтения набора или пропущенной установке отбора) запись набора может привести к полной очистке регистра, так как запись при неустановленном отборе фактически замещает весь регистр на содержимое набора записей.
Запись в наборе записей регистра накопления имеет тип РегистрНакопленияЗапись. Данный тип используется только для записи в наборе записей. Это значение не используется отдельно от набора записей.
Для регистра сведений не подчиненного регистратору кроме набора записей существует тип РегистрСведенийМенеджерЗаписи. Этот тип предназначен для чтения и записи одной записи регистра. Используется для организации редактирования одной записи в форме. Позволяет прочитать запись с определенными значениями ключевых полей, изменить поля, в том числе и ключевые, и записать. Является вспомогательным. Для работы с регистром он использует два набора записей (с отборами соответствующими соответственно ключевым полям считанной и записываемой записи). Соответственно реализация обработчиков в модуле набора записей позволят полностью контролировать изменения данных регистра, в том числе и тогда, когда они выполняются с помощью менеджера записи.
Тип РегистрНакопленияКлючЗаписи предназначен для уникальной идентификации записи регистра. Например, он используется для идентификации строки табличного поля отражающего список регистра. Это позволяет активизировать необходимую строку. Свойства ключа определяются полями образующими уникальный ключ регистра. Для регистров сведений это измерения, период и регистратор, если используется периодичность по позиции регистратора. Для других регистров это регистратор и номер строки. Ключ записи регистра может быть создан с помощью менеджера.
Тип РегистрНакопленияВыборка предназначен для динамического обхода записей регистра. Механизм выборок для необъектных таблиц не имеет существенных отличий. Следует учитывать, что выборка всегда считывает данные записей целиком (считываются все поля).
Тип РегистрНакопленияСписок предназначен для динамического просмотра записей регистра в элементе управления ТабличноеПоле. У него может быть настроен состав считываемых полей (колонок), отбор и сортировка. Список осуществляет считывание данных порциями в процессе навигации пользователем в табличном поле.
Кроме указанных типов значений регистр определяет несколько расширений элементов управления и форм, предназначенных для интерактивного ввода и просмотра, данных регистра. Расширения не являются типами данных, а добавляют специфические свойства, методы и события к соответствующим объектам. Кроме того, расширения определяют некоторое специфическое поведение форм и элементов управления при конфигурировании и работе пользователя с системой.
Для регистров сведений кроме расширений для показа в форме списка и набора записей поддерживается расширение для редактирования в форме одной записи. В этом случае в качестве основного реквизита формы выступает менеджер записи регистра сведений.
Оборотный регистр накопления
Создается только одна виртуальная таблица "Обороты". Остатки не регистрируются. Тип настраивается во вкладке Основное.
Регистр накопления
Движения. Накапливает числовой итог в разрезе измерений по ресурсам. Остатки - только итоговое значение, обороты - состояние регистра на конкретную дату.
Необходимо указать регистраторы и затем в настройках каждого документа создать обработчик проведения. Можно через конструктор движения. Пример обработки проведения в модуле объекта документа
Процедура ОбработкаПроведения(Отказ, Режим)
//{{__КОНСТРУКТОР_ДВИЖЕНИЙ_РЕГИСТРОВ
// Данный фрагмент построен конструктором.
// При повторном использовании конструктора, внесенные вручную изменения будут утеряны!!!
// регистр ОстаткиКанцелярии Приход
Движения.ОстаткиКанцелярии.Записывать = Истина;
Для Каждого ТекСтрокаТаблицаПоступленияКанцелярии Из ТаблицаПоступленияКанцелярии Цикл
Движение = Движения.ОстаткиКанцелярии.Добавить();
Движение.ВидДвижения = ВидДвиженияНакопления.Приход;
Движение.Период = Дата;
Движение.Предмет = ТекСтрокаТаблицаПоступленияКанцелярии.НазваниеПредмета;
Движение.Количество = ТекСтрокаТаблицаПоступленияКанцелярии.Количество;
КонецЦикла;
//}}__КОНСТРУКТОР_ДВИЖЕНИЙ_РЕГИСТРОВ
КонецПроцедуры
Получение данных через запрос. Интересный набор статей про регистр накоплений. Регистр накопления с видом "Остатки" позволяет использовать виртуальные таблицы "Обороты" и "Остатки".
Используем Конструктор запроса. Так как нужно просто получить остатки на указанную дату, выбираем регистр, таблицу и поля
Итоговая процедура:
&НаСервереБезКонтекста
Процедура ВзятьОстаткиНаСервере(НужнаяДата)
Запрос = Новый Запрос;
Запрос.Текст ="ВЫБРАТЬ
| КоличествоТоваровОстатки.Товар.Ссылка.Описание как Товар,
| КоличествоТоваровОстатки.Филиал.Ссылка.Наименование как Филиал,
| КоличествоТоваровОстатки.КоличествоОстаток как Колво
|ИЗ
| РегистрНакопления.КоличествоТоваров.Остатки(&Дата) КАК КоличествоТоваровОстатки";
Запрос.установитьпараметр("Дата",НужнаяДата);
Результат = Запрос.Выполнить();
Если не Результат.Пустой() Тогда
ВыборкаДетальныеЗаписи = Результат.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
Сообщить(ВыборкаДетальныеЗаписи.Филиал + ВыборкаДетальныеЗаписи.Товар + ВыборкаДетальныеЗаписи.Колво);
КонецЦикла;
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ВзятьОстатки(Команда)
Если не ЗначениеЗаполнено(ДатаФормированияОстатков) тогда
ДатаФормированияОстатков = ТекущаяДата();
КонецЕсли;
ВзятьОстаткиНаСервере(ДатаФормированияОстатков);
КонецПроцедуры
Получение данных через менеджер.
&НаСервереБезКонтекста
Процедура ВзятьОстаткиНаСервере2()
РегМенеджер = РегистрыНакопления.КоличествоТоваров;
Остатки = РегМенеджер.Остатки();
Для каждого ТекОст из Остатки Цикл
Сообщить(Строка(ТекОст.Филиал) + " " + Строка(ТекОст.Товар)+ ": " + ТекОст.Количество);
КонецЦикла;
КонецПроцедуры
Значения в возвращенной таблице являются ссылками, из которых еще нужно получить значения. А это дополнительные запросы к базе. В примере прокатило, т к в этих справочниках основное представление в виде наименование. Если изменить в справочнике на в виде кода, то данный пример выведет числа вместо наименований филиалов и товаров. Т е если в базе 10 филиалов, 10 товаров и представление в виде кода, то будет генериться 100 запросов к базе просто для получения имени. А это очень неэффективно. Так что этот способ использовать осознанно.
Регистры сведений
Объекты конфигурации для хранения данных (ресурсов) в структурированном виде (в разрезе измерений) с необязательной дополнительной информацией (реквизиты). Периодические регистры определяют минимальный период, после которого информация может измениться. Режим записи может быть независимый или подчиненный (подчинен регистратору). Обеспечивается контроль уникальности, т.е. записей, у которых совпадают значения измерений, период (если регистр периодический) и регистратор (если регистр подчинен регистратору).
Непереодический независимый регистр сведений отличается от справочника только контролем уникальности и
Можно использовать объект МенеджерЗаписи, но лучше использовать НаборЗаписей.
Добавление и удаление записей. Общая схема взаимодействия:
- создание объекта НаборЗаписей;
- наложение отборов на измерения, период (если периодический) и регистратора (если подчинен регистратору); Из регистра будет извлечен набор в соответствии с условиями и будет заменен на созданный нами набор.
- добавление и заполнение значений полей записей;
- запись набора записей.
// Добавление записи в независимый непериодический регистр сведений
НаборЗаписей = РегистрыСведений.ВерсииПодсистем.СоздатьНаборЗаписей(); // Этап 1
НаборЗаписей.Отбор.ИмяПодсистемы.Установить(ИмяПодсистемы); // Этап 2
// Этап 3
НоваяЗапись = НаборЗаписей.Добавить();
НоваяЗапись.ИмяПодсистемы = ИмяПодсистемы;
НоваяЗапись.Версия = НомерВерсии;
НаборЗаписей.Записать(); // Этап 4
Если не сделать отбор, то перезапишется весь регистр. В случае с отбором, перезапишется та часть регистра, которая была выбрана.
Например, есть регистр, в котором МояСтрока и МоеЧисло - измерения, результат - Ресурс. Есть такие записи:
МояСтрока |
МоеЧисло |
Результат |
олдж |
7 |
67 |
олдж |
8 |
67 |
фыва |
4 |
67 |
Если будет установлен один отбор по МояСтрока значение "олдж" и будет записана одна строка, то в регистре останется 2 строки (фыва и олдж). Нельзя устанавливать в новой записи измерения, отличные от заданных при отборе измерений. Т е если будет двойной отбор олдж, 7, а в новой записи будет указано значение олдж 8, будет ошибка. Но если укажем один отбор олдж, то можем перезаписать все значения МоеЧисло.
// Добавление записи в независимый периодический регистр сведений
НаборЗаписей = РегистрыСведений.КурсыВалют.СоздатьНаборЗаписей(); // Этап 1
// Этап 2
НаборЗаписей.Отбор.Валюта.Установить(Доллар);
НаборЗаписей.Отбор.Период.Установить(НачалоДня(ТекущаяДата()));
// Этап3
НоваяЗапись = НаборЗаписей.Добавить();
НоваяЗапись.Период = ТекущаяДата();
НоваяЗапись.Валюта = Доллар;
НоваяЗапись.Курс = 57.92;
НоваяЗапись.Кратность = 1;
НаборЗаписей.Записать(); // Этап 4
Изменение записей. При помощи функции Прочитать создается итератор для перебора существующих значений. Можно модифицировать записи.
// Редактирование записей с использованием объекта НаборЗаписей
НаборЗаписей = РегистрыСведений.КурсыВалют.СоздатьНаборЗаписей(); // Этап 1
// Этап 2
НаборЗаписей.Отбор.Период.Установить(ДатаКурса);
НаборЗаписей.Отбор.Валюта.Установить(Доллар);
НаборЗаписей.Прочитать(); // Этап 3
Для Каждого Запись Из НаборЗаписей Цикл
Запись.Курс = 57.84; // Этап 4
КонецЦикла;
НаборЗаписей.Записать(); // Этап 5
Чтение записей. Желательно проводить через запрос.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| КурсыВалют.Период,
| КурсыВалют.Валюта,
| КурсыВалют.Курс
|ИЗ
| РегистрСведений.КурсыВалют КАК КурсыВалют";
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
// обход результата выполнения запроса
КонецЦикла;
Для периодических регистров есть виртуальная таблицы СрезПоследних (период которых меньше указанной даты) и СрезПервых (период которых больше указанной даты).
// Получение записи, у которой валюта равна значению из переменной «ВыбраннаяВалюта»
// и период БОЛЬШЕ или равен значению из переменной «ВыбраннаяДата»
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| КурсыВалютСрезПервых.Период,
| КурсыВалютСрезПервых.Валюта,
| КурсыВалютСрезПервых.Курс
|ИЗ
| РегистрСведений.КурсыВалют.СрезПервых(&Период, Валюта = &Валюта) КАК КурсыВалютСрезПервых";
Запрос.УстановитьПараметр("Валюта", ВыбраннаяВалюта);
Запрос.УстановитьПараметр("Период", ВыбраннаяДата);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
// обход результата выполнения запроса
КонецЦикла;
Либо через функцию на сервере и пример на клиенте для подстановки цены при изменении номенклатуры:
Функция РозничнаяЦена(АктуальнаяДата, ЭлементНоменклатуры) Экспорт
// Создать вспомогательный объект "Отбор".
Отбор = Новый Структура("Номенклатура", ЭлементНоменклатуры);
// Получить актуальные значения ресурсов регистра.
ЗначенияРесурсов = РегистрыСведений.Цены.ПолучитьПоследнее(АктуальнаяДата, Отбор);
Возврат ЗначенияРесурсов.Цена;
КонецФункции
// Получить текущую строку табличной части.
СтрокаТабличнойЧасти = Элементы.ПереченьНоменклатуры.ТекущиеДанные;
// Установить цену.
СтрокаТабличнойЧасти.Цена = РаботаСоСправочниками.РозничнаяЦена(
Объект.Дата, СтрокаТабличнойЧасти.Номенклатура);
// Пересчитать сумму строки
РаботаСДокументами.РассчитатьСумму(СтрокаТабличнойЧасти)
Проведение одним документом в нескольких регистрах через конструктор
Справа добавить регистры и настроить сопоставление полей.
Класс Отчеты
Визуальная разработка отчета
Создание схемы компоновки данных - центральная задача при создании отчета. Открывается из раздела Основные отчета.
Схема компоновки данных (СКД).
На основе схемы компоновки и примененных к этой схеме настроек, компоновщик макета формирует макет компоновки данных. Далее этот макет обрабатывается процессором компоновки и преобразуется в результат компоновки данных. В свою очередь, результат компоновки может быть выведен в табличный документ, либо в объект – таблицу значений или дерево значений.
Компонент схемы | Назначение |
Наборы данных | Данные для дальнейшего представления. Могут быть запросы, объекты, объединения. Объединение объединяет из нескольких наборов данных (внешнее соединение). |
Связи наборов данных | Если есть несколько наборов данных и нужно использовать левое соединение. |
Вычисляемые поля | Значения этих полей получаются в результате вычисления выражений, написанных разработчиком в схеме компоновки данных, или в результате выполнения функций, описанных в общих модулях конфигурации. Дополнительные столбцы. |
Ресурсы | Групповые итоговые данные. Не отдельные столбцы, как в случае с вычисляемыми полями. |
Параметры | Параметры могут быть явно определены в запросе, например вид номенклатуры (&ВидНоменклатуры), а могут быть параметрами виртуальных таблиц базы данных, например начало и конец отчетного периода. Как правило, параметры выводятся пользователю перед формированием отчета. Затем заданные пользователем значения параметров передаются в отчет, и отчет формируется заново, например с новым отчетным периодом |
Макеты | |
Вложенные схемы | Для многократного использования разработанной схемы в других отчетах, связав родительский и вложенный отчеты по общему полю. |
Настройки | Содержит 4 типа блоков: группировка, таблица, диаграмма, вложенный отчет. |
Пример создания отчета для документа с табличной частью.
Сначала заполняется наборы данных. После этого в разделе Поля появляются указанные в запросе. Варианты наборов данных: запрос, объект и объединение.
Выбираем Запрос и переносим нужные поля.
Задаем псевдонимы и порядок и создадим запрос. Из запроса создается список полей.
На вкладке Настройки Добавляем в Отчет группировку. Поле не указываем. Теперь настроим поля. На вкладку Выбранные поля и перенести. В параметрах указать оба поля даты, перейти в каждый и Включить в пользовательские настройки.
Вкладка Ресурсы СКД для добавления расчета итогов.
Для изменения имени столбца нужно добавить вычисляемое поле и заменить в нем заголовок. Учесть: флаг Группа криво объединяет, например если будет две записи с разными ценами, то объединение возьмет общее количество и первую цену.
Макеты
Присутствует во многих классах системы.
Хранит формы представления данных. Может быть текстовый документ, двоичные данные, HTML-документ или Active Document, графическую или географическую схему, схему компоновки данных или макет оформления схемы компоновки данных.
При помощи конструктора может быть создана из блока настроек класса Макеты.
Печатная форма.
Создаются области, затем при помощи встроенного языка области заполняются конкретными данными.
Добавление поля/полей: в макете выделить строки и установить имя через Таблица - Имена - Назначить имя. Для нужной строки можно назначить тип Параметр, указываем его имя. В модуле менеджера после отработки конструктора будет процедура Печать.
Процедура Печать(ТабДок, Ссылка) Экспорт
...
ОбластьКолВоСотрудников = Макет.ПолучитьОбласть("КоличествоСотрудников");
//формируем число
ОбластьКолВоСотрудников.Параметры.ВсегоСотрудников = КолВоСотрудников;
ТабДок.Вывести(ОбластьКолВоСотрудников);
Периодические задания
Расположены в Общие - Регламентные задания
В файловом варианте (8.3), задания инициирует первый запущенный клиент. Первый период пропускается.
Может выполняться подпрограмма неглобального общего модуля, у общего модуля должно быть установлено свойство Сервер и Вызов сервера.
При создании задания, галочка "Предопределенное" означает запуск задания автоматически, иначе нужно запускать отдельно средствами языка. В Расписании в разделе Общие нужно выставить минимум один день, затем в разделе Дневное установить период (минимум 60 секунд для файловой версии).
План видов характеристик
Задача элементов данного типа состоит в предоставлении пользователю возможности произвольным образом описывать наборы характеристик и вести учет в разрезе этих наборов.
Каждый вид характеристики обязательно описывается наименованием и типом значения. Все возможные типы должны быть перечислены в поле Тип значения характеристики, возможен составной тип.
Для предоставления пользователю возможности дополнительного создания характеристик, нужно создать справочник, Владельцем установить созданный план видов характеристик и указать этот справочник в Дополнительных значениях характеристик.
Пример: учет номенклатуры по заранее неизвестному набору характеристик. Под термином "Партия" будем понимать некий набор товаров с одинаковыми характеристиками, партии могут отличаться по наборам характеристик. Т е если нам пришли на склад например ручки (характеристики цвет и тип) и бумага (характеристики размер и толщина), то с точки зрения учета это две партии товара.
Для учета характеристик партий создадим справочник ВариантыНоменклатуры, подчиненный справочнику Номенклатура.
Для плана видов характеристик типы значения укажем строка, число, дата, булево, ДополнительныеСвойстваНоменклатуры.
Создадим Регистр сведений ЗначенияСвойствНоменклатуры. Измерения регистра: НаборСвойств, ведущее, тип СправочникСсылка.ВариантыНоменклатуры и ВидСвойства, тип ПланВидовХарактеристикСсылка.СвойстваНоменклатуры. Ресурс регистра: Значение, Характеристика.СвойстваНоменклатуры (берется из плана видов характеристик, может иметь значение любого типа из тех, которые описаны в типе значения плана видов характеристик). Зададим Связь по типу: Вид свойства. Это будет обеспечивать соответствие типа значений, вводимых в это поле, и типа характеристики, выбранной в поле Вид свойства. В Связях параметров выбора, также укажем Вид свойства. Это обеспечит при выборе значений, содержащихся в справочнике Дополнительные свойства номенклатуры, для выбора будут предлагаться только те значения, которые относятся к выбранной характеристике, а не все, которые есть в этом справочнике
Для справочника ВариантыНоменклатуры опишем, где хранятся свойства вариантов номенклатуры и как получить значения
этих свойств. Это описание платформа будет использовать автоматически при выполнении отчетов и при формировании различных динамических списков, в которых задействуются варианты номенклатуры. В контекстном меню справочника ВариантыНоменклатуры выберем команду Характеристики. Добавим новую запись. В качестве источника характеристик выберем план видов характеристик СвойстваНоменклатуры. Перейдем к описанию того, где и как хранятся значения
свойств. В качестве источника значений характеристик выберем регистр сведений ЗначенияСвойствНоменклатуры. Платформа автоматически определит, что в этом регистре полем объекта является измерение НаборСвойств, а полем вида – измерение ВидСвойства. Поэтому единственное, что нам останется указать самостоятельно, что значения свойств хранятся в ресурсе Значение.
Запросы
Одноуровневые запросы
Хранение данных в 1С.
Реляционная схема. Для ссылочных данных набор реквизитов хранится в основной таблице. В ней есть поле Ссылка, это ключ. Для табличной части создается подчиненная таблица со стандартными полями Ссылка, НомерСтроки и реквизитами табличной части. Связь с основной таблицей реализовано через поле Ссылка подчиненной таблицы. Кол-во подчиненных таблиц равно количеству табличных частей.
Для нессылочных данных (например регистр сведений), ключом является совокупность измерений (и периода в случае периодического регистра).
Есть реальные и виртуальные таблицы, виртуальные создаются динамически автоматически. Также есть реальные и виртуальные поля. Важно: поле Представление – виртуальное, генерируется в момент выполнения запроса.
Состав и описание таблиц в синтаксис-помощнике в разделе Работа с запросами - Таблицы запросов.
Запросы
Пример работы с запросом:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Наименование
|ИЗ
| Справочник.Товары";
РезультатЗапроса = Запрос.Выполнить();
ВыборкаЗапроса = РезультатЗапроса.Выбрать();
Пока ВыборкаЗапроса.Следующий() Цикл
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = ВыборкаЗапроса.Наименование;
Сообщение.Сообщить();
КонецЦикла;
Запрос состоит из следующих секций:
- описание запроса,
- объединение запросов,
- упорядочивание результатов,
- автоупорядочивание,
- описание итогов.
Для реальных полей поддерживается * для выбора всех полей. Виртуальные поля нужно задавать явно.
ВЫБРАТЬ
Справочник.Клиенты.*
Полный текст с получением столбцов в запросе:
&НаСервереБезКонтекста
Процедура ПолучитьВсюТаблицуНаСервере()
Запрос = Новый Запрос;
Запрос.Текст ="ВЫБРАТЬ
| Справочник.Филиалы.*";
Результат = Запрос.Выполнить();
Если не Результат.Пустой() Тогда
ВыборкаДетальныеЗаписи = Результат.Выбрать();
РезультатЗапроса = ВыборкаДетальныеЗаписи.Владелец();
ПолнаяСтрокаОтвета = "";
Для Каждого Кол ИЗ РезультатЗапроса.Колонки Цикл
ПолнаяСтрокаОтвета = ПолнаяСтрокаОтвета + Кол.Имя + " ";
КонецЦикла;
Сообщить(ПолнаяСтрокаОтвета);
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
ПолнаяСтрокаОтвета = "";
Для Каждого Кол ИЗ РезультатЗапроса.Колонки Цикл
ПолнаяСтрокаОтвета = ПолнаяСтрокаОтвета + ВыборкаДетальныеЗаписи[Кол.Имя] + " ";
КонецЦикла;
Сообщить(ПолнаяСтрокаОтвета);
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Настройка параметров запроса
Запрос.УстановитьПараметр("НачалоПериода", '20140101000000');
Условия и преобразования в ВЫБРАТЬ
Операция выбора (ВЫБОР (КОГДА ТОГДА) ИНАЧЕ КОНЕЦ). После ключевого слова КОГДА записывается условие выбора, после ключевого слова ТОГДА значение поля выборки в случае, если условие истинно. В общем случае в операции выбора может указываться неограниченное количество альтернативных одиночных выборов КОГДА … ТОГДА. Значение выражения, указанного после слова ИНАЧЕ, используется в качестве результата операции выбора в том случае, если ни одно из ранее указанных условий выбора не было выполнено.
ВЫБРАТЬ
Товары.Наименование КАК Наименование,
ВЫБОР
КОГДА (Товары.Производитель) ЕСТЬ NULL ТОГДА "NULL"
ИНАЧЕ Товары.Производитель
КОНЕЦ КАК Производитель
ИЗ
Справочник.Товары КАК Товары
Также в ВЫБРАТЬ могут содержаться следующие элементы:
- Литералы типов: число, строка (в кавычках), булево (значения Истина и Ложь), Null, Неопределено. Чтобы указать литерал типа Дата, можно воспользоваться ключевым словом языка запросов ДАТАВРЕМЯ или пере-
дать дату через параметр запроса. - Арифметические операции (+, -, /, *). Операция получения остатка % в языке запросов не поддерживается.
- Операцию конкатенации строк (+). Операцию конкатенации нельзя использовать для виртуальных полей.
- Встроенные функции языка запросов (ДЕНЬ, МЕСЯЦ, ГОД и т. д.).
- Агрегатные функции (СУММА, МИНИМУМ, МАКСИМУМ, СРЕДНЕЕ, КОЛИЧЕСТВО).
- Операцию выбора ВЫБОР – позволяет получить одно из возможных значений в соответствии с указанными условиями.
- Операцию приведения типов ВЫРАЗИТЬ – позволяет привести значение составного типа к одному из составляющих это значение типов. А также функцию ВЫРАЗИТЬ() используют для получения результатов нужной
длины и точности.
ВЫБРАТЬ
Товары.Наименование + " (" + Товары.Код + ")" КАК Товар,
ВЫБОР
КОГДА Товары.ЭтоГруппа = ИСТИНА ТОГДА "Это группа"
ИНАЧЕ "Это элемент"
КОНЕЦ КАК ПризнакГруппы
ИЗ
Справочник.Товары КАК Товары
ВЫБРАТЬ
НАЧАЛОПЕРИОДА(ОстаткиТоваров.Период, НЕДЕЛЯ) КАК Период,
ВЫБОР
КОГДА (ОстаткиТоваров.Регистратор ССЫЛКА Документ.ПриходнаяНакладная)
ТОГДА ВЫРАЗИТЬ (ОстаткиТоваров.Регистратор КАК
Документ.ПриходнаяНакладная).Поставщик
КОГДА (ОстаткиТоваров.Регистратор ССЫЛКА Документ.РасходнаяНакладная)
ТОГДА ВЫРАЗИТЬ (ОстаткиТоваров.Регистратор КАК
Документ.РасходнаяНакладная).Покупатель
КОНЕЦ КАК Контрагент
ИЗ
РегистрНакопления.ОстаткиТоваров КАК ОстаткиТоваров
ГДЕ
ОстаткиТоваров.Период МЕЖДУ &ДатаНачала И &ДатаОкончания
Упорядочивание результата.
Раздел УПОРЯДОЧИТЬ ПО, обязательно добавлять для определенности. Есть ВОЗР (по умолчанию, можно не указывать) и УБЫВ. Можно использовать поля вне блока ВЫБРАТЬ.
ВЫБРАТЬ
Цены.Товар КАК Товар,
Цены.Цена КАК Цена
ИЗ
РегистрСведений.Цены КАК Цены
УПОРЯДОЧИТЬ ПО
Цены.Период УБЫВ,
Цена
По типу Ссылка управляемо упорядочить нельзя. Однако с помощью автоупорядочивания можно вывести записи таблицы в наиболее естественном (ожидаемом пользователем) порядке. Для этого нужно упорядочить записи таблицы непосредственно по ссылочному полю, а затем использовать конструкцию АВТОУПОРЯДОЧИВАНИЕ
ВЫБРАТЬ
ЗаказТовара.Дата,
ЗаказТовара.Номер,
ЗаказТовара.Клиент,
ЗаказТовара.СуммаЗаказа
ИЗ
Документ.ЗаказТовара КАК ЗаказТовара
УПОРЯДОЧИТЬ ПО
ЗаказТовара.Ссылка
АВТОУПОРЯДОЧИВАНИЕ
Текстовое представление ссылочного поля
При выводе значения ссылочного поля для получения его представления выполняется дополнительный запрос к той таблице, на которую ссылается это ссылочное поле. В результате процесс замедляется. Для ускорения, нужно в запросе сразу получить текстовое представление ссылочного поля и затем уже его, а не саму ссылку, выводить в отчет или сообщение.
Каждая объектная таблица в информационной базе имеет виртуальное поле Представление. Это текстовое представление объекта. При получении данного поля запрос получает несколько полей, которые соответствуют прикладной сущности
объекта, а при получении значения поля из результата запроса преобразовывает полученные значения в строку. Варианты ПРЕДСТАВЛЕНИЕ(Товар) аналогично Товар.Представление, но лучше первый.
ВЫБРАТЬ
ОстаткиТоваров.Период,
ПРЕДСТАВЛЕНИЕ(ОстаткиТоваров.Регистратор) КАК Регистратор,
ОстаткиТоваров.Количество,
ОстаткиТоваров.Сумма
ИЗ
РегистрНакопления.ОстаткиТоваров КАК ОстаткиТоваров
Но результат функции ПРЕДСТАВЛЕНИЕ() не может быть использован в выражении языка запросов, в условиях сравнения
в предложении ГДЕ, в любых операциях.
Ограничение по количеству записей
ВЫБРАТЬ ПЕРВЫЕ 3
Непересекающаяся выборка
ВЫБРАТЬ РАЗЛИЧНЫЕ
ЗаказТовара.Клиент,
ЗаказТовара.Дата
ИЗ
Документ.ЗаказТовара КАК ЗаказТовара
Если в запросе указано ключевое слово РАЗЛИЧНЫЕ и в предложении УПОРЯДОЧИТЬ ПО указано поле, отсутствующее в списке выборки, то при выполнении такого запроса будет выдана ошибка.
Получение данных табличной части
ВЫБРАТЬ
СоставЗаказа.Товар,
СоставЗаказа.Количество,
СоставЗаказа.Сумма
ИЗ
Документ.ЗаказТовара.Состав КАК СоставЗаказа
Этот запрос выведет все табличные части всех документов Заказ товара. Для получения также информации о реквизитах документа используется ссылка. Можно также установить условие.
ВЫБРАТЬ
СоставЗаказа.Ссылка.Номер,
СоставЗаказа.Ссылка.Клиент,
СоставЗаказа.Товар,
СоставЗаказа.Количество,
СоставЗаказа.Сумма
ИЗ
Документ.ЗаказТовара.Состав КАК СоставЗаказа
ГДЕ
СоставЗаказа.Ссылка = &Документ
Можно получить табличную часть в виде вложенной таблицы и затем обойти ее в цикле:
&НаСервереБезКонтекста
Процедура ПолучитьТабличнуюЧастьНаСервере()
Запрос = Новый Запрос;
Запрос.Текст ="
|ВЫБРАТЬ
| Фирмы.Наименование КАК Название,
| Фирмы.КонтактныеЛица КАК Контакты
|ИЗ
| Справочник.Фирмы КАК Фирмы";
Результат = Запрос.Выполнить();
Если не Результат.Пустой() Тогда
ВыборкаДетальныеЗаписи = Результат.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
ПолнаяСтрокаОтвета = ВыборкаДетальныеЗаписи.Название;
Сообщить(ПолнаяСтрокаОтвета);
ТекКонт = ВыборкаДетальныеЗаписи.Контакты.Выбрать();
Пока ТекКонт.Следующий() Цикл
Сообщить(ТекКонт.Сотрудник)
КонецЦикла;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Запрос с одной и двумя вложенными таблицами:
// Первый вариант – одна вложенная таблица
ВЫБРАТЬ
ЗаказТовара.Номер,
ЗаказТовара.Клиент,
ЗаказТовара.СуммаЗаказа,
ЗаказТовара.Состав.(
Товар,
Количество,
Сумма
)
ИЗ
Документ.ЗаказТовара КАК ЗаказТовара
// Второй вариант – две вложенные таблицы
ВЫБРАТЬ
ЗаказТовара.Номер,
ЗаказТовара.Клиент,
ЗаказТовара.СуммаЗаказа,
ЗаказТовара.Состав.Товар,
ЗаказТовара.Состав.Сумма
ИЗ
Документ.ЗаказТовара КАК ЗаказТовара
Получение иерархической структуры
Ключевое слово ИЕРАРХИЯ после поля, по которому происходит сортировка, позволяет сортировать в соответствии с настроенными группами.
ВЫБРАТЬ
Товары.Наименование КАК Наименование,
Товары.ЭтоГруппа,
ИЗ
Справочник.Товары КАК Товары
УПОРЯДОЧИТЬ ПО
Наименование ИЕРАРХИЯ
Получение групп
// Условие без параметров
ВЫБРАТЬ
Товары.*
ИЗ
Справочник.Товары КАК Товары
ГДЕ
Товары.ЭтоГруппа = ИСТИНА
Получение товаров определенной группы
ВЫБРАТЬ
Товары.*
ИЗ
Справочник.Товары КАК Товары
ГДЕ
Товары.ЭтоГруппа = &ЭтоГруппа
И Товары.Родитель = &Родитель
Получение корневых записей
ВЫБРАТЬ
Товары.*
ИЗ
Справочник.Товары КАК Товары
ГДЕ
Товары.Родитель = ЗНАЧЕНИЕ(Справочник.Товары.ПустаяСсылка
Получение записей принадлежащих группе
ВЫБРАТЬ
Товары.*
ИЗ
Справочник.Товары КАК Товары
ГДЕ
Товары.Ссылка В ИЕРАРХИИ (&ГруппаТоваров)
УПОРЯДОЧИТЬ ПО
Наименование ИЕРАРХИЯ
Ограничения на выборку и параметры запроса
ВЫБРАТЬ
Накладная.Дата КАК Дата,
Накладная.Номер КАК Номер,
Накладная.Поставщик
ИЗ
Документ.ПриходнаяНакладная КАК Накладная
ГДЕ
Дата >= ДАТАВРЕМЯ(2012, 11, 01)
ВЫБРАТЬ
Клиенты.Наименование КАК Наименование,
Клиенты.Адрес,
Клиенты.Телефон
ИЗ
Справочник.Клиенты КАК Клиенты
ГДЕ
Наименование ПОДОБНО "%Иван%"
В функции ПОДОБНО % - любое кол-во символов, _ - один символ,
Параметр запроса
Запрос = Новый Запрос;
Запрос.Текст =
"...
|ГДЕ
|И Задача.ГлавныйБП = &ГлавныйБП";
Запрос.УстановитьПараметр("ГлавныйБП", СсылкаНаБизнесПроцесс);
Агрегатные функции и группировка
Агрегатные функции обычно вызываются вместе с группировкой. При отсутствии СГРУППИРОВАТЬ ПО все записи исходной таблицы будут сгруппированы в одну строку.
ВЫБРАТЬ
КОЛИЧЕСТВО(*) КАК Всего,
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ЗаказТовара.Клиент) КАК РазныеКлиенты
ИЗ
Документ.ЗаказТовара КАК ЗаказТовара
ВЫБРАТЬ
НакладнаяСостав.Товар КАК Товар,
МИНИМУМ(НакладнаяСостав.Цена) КАК Минимум,
МАКСИМУМ(НакладнаяСостав.Цена) КАК Максимум,
СРЕДНЕЕ(НакладнаяСостав.Цена) КАК Среднее
ИЗ
Документ.РасходнаяНакладная.Состав КАК НакладнаяСостав
СГРУППИРОВАТЬ ПО
НакладнаяСостав.Товар
Всего 5 функций МИНИМУМ, МАКСИМУМ, СРЕДНЕЕ, КОЛИЧЕСТВО, СУММА. В предложении СГРУППИРОВАТЬ ПО должны указываться именно имена полей, а не их псевдонимы, определенные в запросе.
В случае группировки по значению нескольких полей нужно после ключевого слова СГРУППИРОВАТЬ ПО перечислить через запятую список полей группировки.
СГРУППИРОВАТЬ ПО
НакладнаяСостав.Ссылка.Покупатель,
НакладнаяСостав.Товар
ИМЕЮЩИЕ добавляет условие на значения агрегатных функций, применяемых к исходным записям с одинаковым значением поля группировки. Оно накладывает условие на записи, получившиеся в результате группировки.
ВЫБРАТЬ
НакладнаяСостав.Ссылка.Покупатель КАК Покупатель,
НакладнаяСостав.Товар КАК Товар,
СУММА(НакладнаяСостав.Количество) КАК Количество,
СУММА(НакладнаяСостав.Сумма) КАК Сумма
ИЗ
Документ.РасходнаяНакладная.Состав КАК НакладнаяСостав
СГРУППИРОВАТЬ ПО
НакладнаяСостав.Ссылка.Покупатель,
НакладнаяСостав.Товар
ИМЕЮЩИЕ
СУММА(НакладнаяСостав.Сумма) > 50000
Итоги
Итоги отличаются от группировки тем, что не сворачивают данные, а добавляют данные по итогам. Итоги можно считать не по всем полям.
ВЫБРАТЬ
НакладнаяСостав.Товар КАК Товар,
НакладнаяСостав.Количество КАК Количество,
НакладнаяСостав.Цена КАК Цена,
НакладнаяСостав.Сумма КАК Сумма
ИЗ
Документ.ПриходнаяНакладная.Состав КАК НакладнаяСостав
ИТОГИ
СУММА(Количество),
СРЕДНЕЕ(Цена),
СУММА(Сумма)
ПО
Товар
За счет ключевых слов ИЕРАРХИЯ и ТОЛЬКО ИЕРАРХИЯ можно считать итоги по иерархии (или только)
ВЫБРАТЬ
НакладнаяСостав.Товар КАК Товар,
НакладнаяСостав.Количество КАК Количество,
НакладнаяСостав.Цена КАК Цена,
НакладнаяСостав.Сумма КАК Сумма
ИЗ
Документ.ПриходнаяНакладная.Состав КАК НакладнаяСостав
ИТОГИ
СУММА(Количество),
СУММА(Сумма)
ПО
Товар ТОЛЬКО ИЕРАРХИЯ КАК ТоварТолькоИерархия
Если нужны итоги по нескольким полям, то их перечисляют через запятую в разделе ПО. Для расчета общих итогов используется слово ОБЩИЕ
ВЫБРАТЬ
НакладнаяСостав.Ссылка.Поставщик КАК Поставщик,
НакладнаяСостав.Товар КАК Товар,
НакладнаяСостав.Количество КАК Количество,
НакладнаяСостав.Сумма КАК Сумма
ИЗ
Документ.ПриходнаяНакладная.Состав КАК НакладнаяСостав
ИТОГИ
СУММА(Количество),
СУММА(Сумма)
ПО
ОБЩИЕ,
Поставщик
Вложенные запросы, соединение, объединение, пакетные запросы
Вложенные запросы
ВЫБРАТЬ
Расход.Ссылка КАК Документ,
Расход.Покупатель КАК Покупатель
ИЗ
Документ.РасходнаяНакладная КАК Расход
ГДЕ
Расход.Состав.Товар В
(
ВЫБРАТЬ
ПриходСостав.Товар КАК Товар
ИЗ
Документ.ПриходнаяНакладная.Состав КАК ПриходСостав
ГДЕ
ПриходСостав.Ссылка = &Документ
)
Вложенные запросы могут использоваться в аргументах конструктора виртуальных таблиц
ВЫБРАТЬ
Цены.Период,
Цены.Товар,
Цены.Цена
ИЗ
РегистрСведений.Цены.СрезПоследних( , Товар В
(
ВЫБРАТЬ
РасходСостав.Товар КАК Товар
ИЗ
Документ.РасходнаяНакладная.Состав КАК РасходСостав
ГДЕ
РасходСостав.Ссылка = &Документ
)
) КАК Цены
УПОРЯДОЧИТЬ ПО
Период
Соединения
Используются несколько источников данных, которые перечисляются после ключевого слова ИЗ. Обычно соединяются по ссылкам. Исходные таблицы запроса соединяются по условию связи. Условие связи источников запроса задается после ключевого слова ПО.
Внутреннее соединение. В результат запроса попадут записи из таблиц-источников, которые удовлетворяют заданному условию связи. Пересечение множеств, оператор И. Ключевое слово ВНУТРЕННЕЕ СОЕДИНЕНИЕ или СОЕДИНЕНИЕ.
ВЫБРАТЬ
Товары.Код,
Товары.Наименование,
Товары.Производитель,
Цены.Цена
ИЗ
Справочник.Товары КАК Товары
ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.Цены.СрезПоследних КАК Цены
ПО Товары.Ссылка = Цены.Товар
Если будет найдено несколько записей, удовлетворяющих условию соединения, то в результат запроса будут включены все эти записи. Т е строчек будет несколько на одну запись.
Левое / правое внешнее соединение. При левом соединении попадут все строки левой таблицы, добавятся указанные столбцы из правой, если в правой есть данные - добавятся, иначе null. Правое аналогично.
ВЫБРАТЬ
Товары.Код,
Товары.Наименование,
Товары.Производитель,
Цены.Цена
ИЗ
Справочник.Товары КАК Товары
ЛЕВОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ РегистрСведений.Цены.СрезПоследних КАК Цены
ПО Товары.Ссылка = Цены.Товар
Полное внешнее соединение. Добавляются указанные столбцы из обеих таблиц, попадают все строки из всех таблиц, если в какой-то нет данных - устанавливается NULL. Оператор ИЛИ.
При работе в клиент-серверном варианте с PostgreSQL производительность с конструкцией ПОЛНОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ
снижается. Особенно когда в запросе встречаются две и более такие конструкции. Не рекомендуется использовать полное внешнее соединение в запросах.
Соединение нескольких таблиц:
ВЫБРАТЬ
Товары.Наименование,
ОстаткиТоваров.КоличествоОстаток,
Продажи.КоличествоОборот
ИЗ
Справочник.Товары КАК Товары
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиТоваров.Остатки КАК ОстаткиТоваров
ПО Товары.Ссылка = ОстаткиТоваров.Товар
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.Продажи.Обороты КАК Продажи
ПО Товары.Ссылка = Продажи.Товар
ГДЕ
Товары.ЭтоГруппа = ЛОЖЬ
Здесь необходимо учитывать последовательность соединения и условие задачи, здесь начинает проявляться профессионализм составления оптимальных запросов.
При вложении запросов сначала выполняется самое глубокое вложение.
ВЫБРАТЬ
Товары.Наименование,
ОстаткиТоваров.КоличествоОстаток,
Продажи.КоличествоОборот
ИЗ
Справочник.Товары КАК Товары
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиТоваров.Остатки КАК ОстаткиТоваров
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.Продажи.Обороты КАК Продажи
ПО ОстаткиТоваров.Товар = Продажи.Товар
ПО Товары.Ссылка = ОстаткиТоваров.Товар
ГДЕ
Товары.ЭтоГруппа = ЛОЖЬ
Т е сначала левое соединение РегистрНакопления.ОстаткиТоваров.Остатки и РегистрНакопления.Продажи.Обороты, затем левое соединение Справочник.Товары и предыдущий результат.
Разыменование. Если присутствует ссылочное поле на другой элемент, то в 1С вместо соединения рекомендуют использовать вложенное обращение к полям. Это эквивалентно левому соединению, но проще выглядит.
ВЫБРАТЬ
Событие.Дата КАК Дата,
Событие.ВидСобытия,
Событие.Клиент,
Событие.Клиент.Адрес КАК Адрес,
Событие.Клиент.Телефон КАК Телефон
ИЗ
Документ.Событие КАК Событие
УПОРЯДОЧИТЬ ПО
Дата
Объединения запросов.
При объединении каждый запрос получает данные независимо, то есть у каждого из запросов – свое описание выбираемых полей (ВЫБРАТЬ), источников запроса (ИЗ), условий отбора (ГДЕ), полей группировки (СГРУППИРОВАТЬ ПО). Затем данные, получаемые в результате каждого запроса, объединяются, и уже над этим объединением выполняются такие операции, как упорядочивание результатов (УПОРЯДОЧИТЬ ПО) и расчет итогов (ИТОГИ ПО).
ВЫБРАТЬ
Заказ.Ссылка.Клиент КАК Клиент,
Заказ.Товар КАК Товар,
СУММА(Заказ.Количество) КАК Заказано,
СУММА(0) КАК Продано
ИЗ
Документ.ЗаказТовара.Состав КАК Заказ
СГРУППИРОВАТЬ ПО
Заказ.Ссылка.Клиент,
Заказ.Товар
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
Накладная.Ссылка.Покупатель,
Накладная.Товар,
СУММА(0),
СУММА(Накладная.Количество)
ИЗ
Документ.РасходнаяНакладная.Состав КАК Накладная
СГРУППИРОВАТЬ ПО
Накладная.Ссылка.Покупатель,
Накладная.Товар
ИТОГИ ПО
ОБЩИЕ,
Клиент
По умолчанию при объединении запросов полностью одинаковые строки в результате запроса, сформированные разными запросами, заменяются одной. Если требуется, чтобы были оставлены разные строки, необходимо указать ключевое слово ВСЕ. В общем случае следует использовать конструкцию ОБЪЕДИНИТЬ ВСЕ.
Пакетные запросы и временные таблицы.
Для работы с временными таблицами нужен менеджер временных таблиц. Однако, удалось только в пределах одного запроса с формы на сервер. Интересная статья Глобальные таблицы 1С не использует.
&НаСервереБезКонтекста
Процедура СоздатьВременнуюТаблицуНаСервере()
МенВТ = Новый МенеджерВременныхТаблиц;
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МенВТ;
Запрос.Текст ="
|ВЫБРАТЬ
| Поступление.Товар КАК Товар,
| Поступление.Цена КАК Цена,
| Поступление.Количество КАК Количество,
| Поступление.Сумма КАК Сумма
|ПОМЕСТИТЬ МоеПоступлениеТоваров
|ИЗ
| Документ.ПоступлениеТоваров.ПереченьТоваров КАК Поступление
|";
Результат = Запрос.Выполнить();
КонецПроцедуры
Этот менеджер будет актуален только до возврата из вызванной процедуры.
При Пакетном запросе менеджер создавать не нужно.
Временная таблица не существует в базе данных. Это область в памяти, созданная на ограниченное время. Эта область создается и заполняется данными при выполнении запроса, содержащего ключевое слово ПОМЕСТИТЬ, после которого следует произвольное имя временной таблицы.
ВЫБРАТЬ
Поступление.Товар,
Поступление.Ссылка.Дата КАК Дата,
Поступление.Ссылка.Поставщик
ПОМЕСТИТЬ ПоступлениеТоваров
ИЗ
Документ.ПриходнаяНакладная.Состав КАК Поступление
ГДЕ
МЕСЯЦ(Поступление.Ссылка.Дата) = 11
Для быстрой и эффективной выборки данных из временной таблицы желательно проиндексировать эту таблицу по полям, которые будут затем участвовать в условии отбора или в условии соединения. Делается это с помощью предложения ИНДЕКСИРОВАТЬ ПО.
Пакетный запрос содержит последовательность запросов, разделенных символом «;» (точка с запятой). При выполнении пакетного запроса входящие в него запросы выполняются друг за другом.
ВЫБРАТЬ
Поступление.Товар,
Поступление.Ссылка.Дата КАК Дата,
Поступление.Ссылка.Поставщик
ПОМЕСТИТЬ ПоступлениеТоваров
ИЗ
Документ.ПриходнаяНакладная.Состав КАК Поступление
ГДЕ
МЕСЯЦ(Поступление.Ссылка.Дата) = 11
;
ВЫБРАТЬ
Товары.Наименование,
Товары.Производитель,
ПоступлениеТоваров.Дата,
ПоступлениеТоваров.Поставщик
ИЗ
Справочник.Товары КАК Товары
ЛЕВОЕ СОЕДИНЕНИЕ ПоступлениеТоваров КАК ПоступлениеТоваров
ПО Товары.Ссылка = ПоступлениеТоваров.Товар
УПОРЯДОЧИТЬ ПО
Товары.Наименование ИЕРАРХИЯ
Конструктор запросов
Общая информация.
Запуск конструктора: ПКМ в тексте модуля - Конструктор запроса или Основное меню Текст - Конструктор запроса.
Если вызвать конструктор при размещении курсора внутри существующего запроса, запрос будет проанализирован и либо перенесен в конструктор, либо будут указаны ошибки и конструктор не запустится до ручного исправления. Используется для проверки запроса, созданного вручную.
Кнопка Запрос в левом нижнем углу отображает текущий запрос без завершения работы из конструктора.
Вкладки
Без входа во вкладку, автоматические элементы в пределах функции вкладки не создаются.
Пакет запросов. Настройка состава пакета запросов. По умолчанию один запрос. При количестве вкладок больше одной справа появляются вертикальные вкладки для каждого запроса.
Таблицы и поля. Указание нужных таблиц и их полей в пределах одного запроса. В разделе Таблицы создается вложенный запрос кнопкой "Создать вложенный запрос", для использования полей временной таблицы нужно создать описание временной таблицы, вручную указав название таблицы, поля и тип данных. Для создания псевдонима таблицы (обычной, вложенной, виртуальной), в разделе таблицы ПКМ на имени таблицы - Переименовать таблицу.
Объединения/псевдонимы. В разделе справа в столбце Имя поля задать нужный псевдоним. В разделе слева можно убрать дубли. Для объединения, нужно в левом столбце добавить запрос. В столбце справа будет отображаться итоговая структура таблицы, но несопостовляемые поля будут заменяться NULL. Чтобы установить нужное значение (например 0), во вкладке Таблицы и поля нужно добавить произвольное поле.
Порядок. Для нужных полей устанавливаются правила, добавляется Автоупорядочивание.
Условия. Произвольное условие заполняется вручную, непроизвольное - только сравнение указанных столбцов таблиц. Условия по И.
Связи. Если в Таблицы и поля добавлены 2+ таблицы, то это поле доступно. Без галочек Все - внутреннее соединение. Одна галочка Все создает левое соединение (если одна галочка для правой таблицы, то все равно левое, но порядок меняется). Обе галочки создают полное соединение.
Способы обхода результата запроса
Способы обхода выборки: в линейном порядке, в иерархическом порядке или по группировкам. Тип обхода выборки задается значением системного перечисления ОбходРезультатаЗапроса и передается в качестве параметра в метод Выбрать() объекта
РезультатЗапроса. При линейном обходе выборки будут последовательно получаться все записи из результата запроса, при иерархическом обходе получаются только записи результата запроса, находящиеся на одном уровне иерархии, при обходе по
группировкам будут получены только родительские записи, являющие групповыми итогами.
Тип выборки | Описание | Функция в коде |
Линейный | все записи из результата запроса |
Без указания способа или СпособВыборки = ОбходРезультатаЗапроса.Прямой; |
Иерархический | только записи результата запроса, находящиеся на одном уровне иерархии | СпособВыборки = ОбходРезультатаЗапроса.ПоГруппировкамСИерархией; |
По группировкам | только родительские записи, являющие групповыми итогами | СпособВыборки = ОбходРезультатаЗапроса.ПоГруппировкам; |
Запрос = Новый Запрос;
Запрос.Текст = "";
РезультатЗапроса = Запрос.Выполнить();
СпособВыборки = ОбходРезультатаЗапроса.Прямой;
ВыборкаЗапроса = РезультатЗапроса.Выбрать(СпособВыборки);
Сообщение = Новый СообщениеПользователю;
Пока ВыборкаЗапроса.Следующий() Цикл
Сообщение.Текст = "Товар: " + ВыборкаЗапроса.Товар.Наименование +
" Итого: " + ВыборкаЗапроса.Количество +
" Тип записи: " + ВыборкаЗапроса.ТипЗаписи() +
" Уровень: " + ВыборкаЗапроса.Уровень() +
" Группировка: " + ВыборкаЗапроса.Группировка();
Сообщение.Сообщить();
КонецЦикла
&НаСервереБезКонтекста
Процедура ИерархическийОбходНаСервере()
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Товары.Товар КАК Товар,
| Товары.Количество КАК Количество
|ИЗ
| Документ.ПоступлениеТоваров.ПереченьТоваров КАК Товары
|
|УПОРЯДОЧИТЬ ПО
| Товар
|ИТОГИ
| СУММА(Количество)
|ПО
| Товар Иерархия
|";
РезультатЗапроса = Запрос.Выполнить();
СпособВыборки = ОбходРезультатаЗапроса.ПоГруппировкамСИерархией;
ВыборкаЗапроса = РезультатЗапроса.Выбрать(СпособВыборки);
Сообщение = Новый СообщениеПользователю;
Пока ИерархическаяВыборка.Следующий() Цикл
Сообщение.Текст = "Товар: " + ИерархическаяВыборка.Товар.Наименование +
" Количество: " + ИерархическаяВыборка.Количество +
" Тип записи: " + ИерархическаяВыборка.ТипЗаписи() +
" Уровень: " + ИерархическаяВыборка.Уровень() +
" Группировка: " + ИерархическаяВыборка.Группировка();
Сообщение.Сообщить();
КонецЦикла;
КонецПроцедуры
Выгрузка в таблицу значений
Функция ПолучитьТекущиеЗадачиБизнесПроцесса(НазваниеЗадачиБП, СсылкаНаБизнесПроцесс) Экспорт
// Возвращает список задач
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
|Задача.Ссылка КАК ТекущаяЗадача
|ИЗ
|Задача.ЗадачаМониторингаИС КАК Задача
|ГДЕ
|(НЕ Задача.Выполнена)
|И Задача.БизнесПроцесс = &ГлавныйБП
|И Задача.БизнесПроцесс.Стартован";
Запрос.УстановитьПараметр("ГлавныйБП", СсылкаНаБизнесПроцесс);
РезультатЗапроса = Запрос.Выполнить();
ТЗ = РезультатЗапроса.Выгрузить();
Для Каждого СтрокаТЗ из ТЗ Цикл
Сообщить(СтрокаТЗ[0]);
КонецЦикла;
Возврат ТЗ;
КонецФункции
Бизнес процессы и задачи.
Общая информация
Определения
Руководство разработчика, глава 13
Общее взаимодействие
Бизнес процесс берет из задачи правила распределения (Адресацию в терминах 1С). Т е в бизнес процессе мы прописываем последовательность действий. Из объекта Задачи, привязанной к БП, берется алгоритм адресации. К тому же, для каждого шага БП создается одна и та же несколько модифицированная задача. В ней можно отобразить реквизиты БП, но изменять эти реквизиты можно только внутри БП. Взаимодействие БП - Задача довольно мутное, задачу нужно рассматривать как некий шаблон, из которого будет создаваться на каждом шаге конкретная задача.
Система адресации
Назначение – обеспечить возможность персональной и ролевой адресации задач участникам бизнес-процессов.
Ролевая адресация (ролевая маршрутизация) – набор правил, позволяющий определить конечного адресата (исполнителя) исходя из реквизитов адресации.
Определение конкретного исполнителя (разыменование) осуществляется с помощью свойств задачи – Адресация, Основной реквизит адресации и Текущий исполнитель.
Адресация – ссылка на непериодический независимый регистр сведений, который хранит актуальную на текущий момент информацию о соответствии исполнителей (основной реквизит адресации) всем остальным реквизитам адресации задач.
Реквизиты адресации - независимый элемент настройки, может не совпадать по названию с элементами регистра адресации. Есть настройка "Тип" (например, СправочникСсылка.Сотрудники). Сопоставление со значениями регистра сведений идет по свойству "Измерение адресации" Реквизита адресации. Т е возможна (и ошибок не выдается) ситуация, когда в регистре адресации измерение ссылается на один справочник, а реквизит адресации, ссылаясь на другой справочник, сопоставляется с этим измерением регистра. И оно вроде будет работать, но не правильно.
Основной реквизит адресации: конкретный сотрудник – исполнитель заданий. Должен ссылаться на реквизит адресации (не на измерение регистра, указанного в разделе Адресация).
Текущий исполнитель - переменная параметра сеанса. Может браться из справочника, например Сотрудники. В предлагаемых алгоритмах работы с заданиями / бизнес процессами корректность связи этой переменной с системным пользователем полностью лежит на разработчике. В ней просто ссылка. Можно установить и конкретное число или строку. Однако нет логической проверки корректности.
Важно! Сопоставление между Реквизитами адресации, установленными в Задаче, и измерениями РегистраАдресации настраиваются в свойствах каждого реквизита адресации, в разделе Адресация.
Последовательность настройки. Создается параметр сеанса, связанный со справочником сотрудников. При авторизации в параметр сеанса устанавливается ссылка, связанная с созданным нами справочником сотрудников.
Важно! Не системным Пользователи, а созданным вручную справочником.
Созданный параметр сеанса устанавливается в Задача - Текущий исполнитель. В нем ссылка на Справочники.Сотрудники.
В Адресации устанавливается регистр, в котором будет храниться информация о текущих сопоставлениях Сотрудник-Роль.
Эксперимент. Поскольку было неясно, каким образом сопоставляются значения роли и исполнителя, то к настроенной "по учебнику" схеме (Справочник.Сотрудники, регистр адресации, переменная ТекущийПользователь) был добавлен справочник Пользователи. В Задаче у реквизита адресации Исполнитель был заменен тип со СправочникСсылка.Сотрудники на СправочникСсылка.Пользователи. Распределение задач по пользователям осталось корректным, это повлияло лишь на поле выбора исполнителя, оно бралось из справочника Пользователи.
Т е если бы был добавлен алгоритм автоматического заполнения на основе ТекущийПользователь и данное поле было бы скрытым для пользователя, то появилась бы ошибка.
Бизнес процессы
Бизнес-процесс стартует при вызове метода Старт() или нажатии кнопки "Стартовать и закрыть" в форме объекта. Бизнес-процесс может быть записан, но не стартован.
БП = БизнесПроцессы.Согласование.СоздатьБизнесПроцесс();
БП.Дата = ТекущаяДата();
БП.Записать();
БП.Старт();
При вызове метода ВыполнитьЗадачу() осуществляется проверка выполнения, после которой задача помечается как выполненная и об этом оповещается бизнес-процесс. Если все необходимые условия выполнены, то бизнес-процесс осуществляет переход на следующую точку маршрута.
Свойство Групповая в Адресации создает задание каждому исполнителю в группе, поэтому, чтобы шаг был выполнен, необходимо выполнение всеми участниками группы.
Работа с точками процесса.
События
В свойствах задачи на схеме процесса настраиваются события.
"ПередСозданиемЗадач" – вызывается когда задачи еще не созданы, можно создать новые задачи и полностью заполнить их свойства.
"ПриСозданииЗадач" – задачи уже созданы их можно отредактировать.
Заполнение бизнес процессом реквизитов задачи
В связи с наличием одной формы для всех задач, может использоваться для детализации формы для пользователя.
Процедура ОтсутствиеСвязиССерверомИиЗПриСозданииЗадач(ТочкаМаршрутаБизнесПроцесса, ФормируемыеЗадачи, Отказ)
Для каждого Задача Из ФормируемыеЗадачи Цикл
Задача.ПингДоступен = ПингДоступен;
КонецЦикла;
КонецПроцедуры
Изменение реквизитов бизнес процесса при выполнении задачи
Процедура ОтсутствиеСвязиССерверомИиЗПриВыполнении(ТочкаМаршрутаБизнесПроцесса, Задача, Отказ)
ЭтотОбъект.ПингДоступен = Истина;
ЭтотОбъект.Записать();
КонецПроцедуры
Условия и выбор варианта
Для условного ветвления есть обработчик проверки условия, наличие которого обязательно и контролируется при проверке карты маршрута перед сохранением бизнес-процесса. Если обработчик отсутствует, то будет выдано предупреждение: Точка условия не имеет обработчика события "Проверка условия". Этот обработчик должен вернуть результат проверки условия, от которого будет зависеть выбор следующей точки маршрута. Если результат Истина, то бизнес-процесс пойдет по ветке Да, в противном случае – по ветке Нет. По умолчанию результат устанавливается равным значению Ложь.
Процедура ОграничениеСкидкиПроверкаУсловия(ТочкаМаршрутаБП, Результат)
Если ПолучитьСкидкуПоСчету() > ПолучитьОбычнуюСкидку() Тогда
Результат = Истина;
Иначе
Результат = Ложь;
КонецЕсли;
КонецПроцедуры
Для выбора одного из нескольких возможных путей используется точка выбора варианта. Для каждого варианта обязателен обработчик выбора варианта, контролируется при проверке карты маршрута. Если обработчик отсутствует, то будет выдано предупреждение: Точка выбора варианта не имеет обработчика события Выбор варианта. Этот обработчик должен установить параметр Результат равным одному из предусмотренных вариантов.
Процедура ВыборВарианта (ТочкаВыбораВарианта, Результат)
Если ВидОплаты = Перечисления.ВидОплаты.Наличная Тогда
Результат = ТочкаВыбораВарианта.Варианты.Наличная;
ИначеЕсли ВидОплаты = Перечисления.ВидОплаты.Безналичная Тогда
Результат = ТочкаВыбораВарианта.Варианты.Безналичная;
ИначеЕсли ВидОплаты = Перечисления.ВидОплаты.Взаимозачет Тогда
Результат = ТочкаВыбораВарианта.Варианты.Взаимозачет;
ИначеЕсли ВидОплаты = Перечисления.ВидОплаты.Кредит Тогда
Результат = ТочкаВыбораВарианта.Варианты.Кредит;
КонецЕсли;
КонецПроцедуры
//ВидОплаты – реквизит бизнес-процесса.
Шаблоны кода
Программный старт БП из формы нового БП с дополнительным изменением параметров
&НаСервере
Процедура СтартоватьБПНаСервере()
ТекОбъект = Объект.Ссылка.ПолучитьОбъект();
ТекОбъект.Старт();
КонецПроцедуры
&НаКлиенте
Процедура СтартоватьБП(Команда)
Если Не ЗначениеЗаполнено(Объект.Дата) Тогда
Объект.Дата = ТекущаяДата();
КонецЕсли;
Объект.СервисДоступен = Ложь;
ЭтаФорма.Записать();
СтартоватьБПНаСервере();
КонецПроцедуры
Проверка и выполнение задачи.
Например, если задача предусматривает проведение документа, то автоматическая процедура слежения за такими задачами может определять, что нужный документ уже проведен, и помечать задачу как выполненную путем вызова у нее метода Выполнить(). Для организации такого рода автоматизированных процедур предназначен метод ПроверкаВыполнения() у задачи и соответствующие ему обработчики у точек маршрута.
Если Задача.ПроверитьВыполнение() Тогда
Задача.ВыполнитьЗадачу();
КонецЕсли
Получить ссылки на процессы
СписокБП = БизнесПроцессы.ТестовыйПроцесс.Выбрать();
Пока СписокБП.Следующий() Цикл
Если Не СписокБП.Завершен Тогда
Сообщить(СписокБП.Номер);
КонецЕсли;
КонецЦикла;
Получить имена всех бизнес процессов
&НаСервереБезКонтекста
Процедура ВывестиВыполненныеПроцессыНаСервере()
// Получаем коллекцию всех объектов типа БизнесПроцессы
КоллекцияБизнесПроцессов = Метаданные.БизнесПроцессы;
Для Каждого БизнесПроцесс Из КоллекцияБизнесПроцессов Цикл
//БизнесПроцесс.Имя; БизнесПроцесс.Синхронизация; БизнесПроцесс.Комментарий;
Сообщить(БизнесПроцесс.Имя);
КонецЦикла;;
КонецПроцедуры
//В предыдущем скрипте можно заменить имя для просмотра в цикле
//ИмяШаблонаБП = БизнесПроцесс.Имя;
//СписокБП = БизнесПроцессы[ИмяШаблонаБП].Выбрать();
Получение текущей задачи для бизнес процесса
ВЫБРАТЬ
Задача.Ссылка
ИЗ
Задача.Задача КАК Задача
ГДЕ
(НЕ Задача.Выполнена)
И Задача.ГлавныйБП = &ГлавныйБП
И Задача.ГлавныйБП.Стартован
Получение всех точек бизнес процесса:
&НаСервереБезКонтекста
Процедура СписокТочекПроцессаНаСервере()
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| ПроцессМониторингаИиЗТочки.Ссылка КАК Ссылка,
| ПроцессМониторингаИиЗТочки.Порядок КАК Порядок
|ИЗ
| БизнесПроцесс.ПроцессМониторингаИиЗ.Точки КАК ПроцессМониторингаИиЗТочки";
РезультатЗапроса = Запрос.Выполнить();
ТЗ = РезультатЗапроса.Выгрузить();
Для Каждого СтрокаТЗ из ТЗ Цикл
Сообщить(Строка(СтрокаТЗ[1]) + ": " + Строка(СтрокаТЗ[0]));
КонецЦикла
КонецПроцедуры
Получение следующих точек для конкретной точки
&НаСервереБезКонтекста
Функция ПолучитьИсходящиеТочки(пТочкаМаршрута)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ПроцессМониторингаИиЗТочки.Ссылка
|ИЗ
| БизнесПроцесс.ПроцессМониторингаИиЗ.Точки КАК ПроцессМониторингаИиЗТочки";
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
лРезультат = Новый Массив;
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
лВходящиеТочки = ВыборкаДетальныеЗаписи.Ссылка.ПолучитьВходящиеТочки();
Если лВходящиеТочки.Найти(пТочкаМаршрута) <> Неопределено Тогда
лРезультат.Добавить(ВыборкаДетальныеЗаписи.Ссылка);
КонецЕсли;
КонецЦикла;
Возврат лРезультат;
КонецФункции
Создание бизнес процесса
Начало: База пустая.
Шаг 1. Создание системной роли и системного пользователя. Должен быть хотя бы один пользователь с правами администратора. Сейчас должна быть доступна авторизация пользователя с правами администратора.
Шаг 2. Настройка хранения ссылки на профиль пользователя в параметре сеанса. Детали о пользователях и ролях
Создать справочник Сотрудники, он будет содержать профиль пользователя. Для начала без реквизитов, по необходимости можно будет добавить.
Нужно создать параметр сеанса Текущий пользователь, тип - СправочникСсылка.Сотрудники. В модуле сеанса создается процедура, сохраняющая в этот параметр сеанса ссылку на нужную запись в справочнике.
Процедура УстановкаПараметровСеанса(ТребуемыеПараметры)
ИмяПольз = ИмяПользователя();
ТекПользователь = Справочники.Сотрудники.НайтиПоНаименованию(ИмяПольз, Истина);
Если Не ЗначениеЗаполнено(ТекПользователь) Тогда
НовыйПользователь = Справочники.Сотрудники.СоздатьЭлемент();
НовыйПользователь.Наименование = ИмяПольз;
НовыйПользователь.Код = ИмяПольз;
НовыйПользователь.Записать();
ТекПользователь = НовыйПользователь.Ссылка;
КонецЕсли;
ПараметрыСеанса.ТекущийПользователь = ТекПользователь;
КонецПроцедуры
Сейчас после входа в систему с пустым справочником Сотрудники, в нем должен создаться пользователь. Для проверки можно сделать обработку и кнопку "Вывести", которая отобразит запись из справочника о текущем пользователе.
Шаг 3. Создание справочника (структурные подразделения) и регистра сведений (Должности сотрудников). Нужно для организации модели распределения заданий бизнес процесса по должностям, а не по именам. Структурные подразделения - справочник с иерархией групп, группы - названия структурных подразделений, элементы - должности в структурных подразделениях. Структурные подразделения и должности должны быть предопределенными элементами. В регистре сведений два измерения: Должность и Сотрудник.
Сейчас можно добавить структурные подразделения, сотрудников и их должности.
Шаг 4. Создание задачи (напомню: из задачи в бизнес процесс берется алгоритм адресации).
Исполнитель и Должность должен браться из соответствующих справочников.
Шаг 5. Настраиваем бизнес процесс следующего вида:
В данных бизнес процесса создаем реквизит СервисДоступен, булево, по умолчанию истина.
Создаем форму бизнес процесса и выполняем следующее:
- добавляем реквизит СервисДоступен на форму, добавляем обработчик
&НаКлиенте
Процедура СервисДоступенПриИзменении(Элемент)
Элементы..Видимость = Истина;
КонецПроцедуры
- добавляем реквизит Графическая схема. Чтобы на форме отображалось текущее состояние процесса, создаем обработчик события ПриЧтенииНаСервере
В модуле формы нужно создать следующие процедуры:
&НаСервере
Процедура ОбновитьКартуМаршрута()
ОбъектБП = РеквизитФормыВЗначение("Объект");
СхемаПроцесса = ОбъектБП.ПолучитьКартуМаршрута(); //СхемаПроцесса - реквизит графическая схема
КонецПроцедуры
&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
ОбновитьКартуМаршрута();
КонецПроцедуры
Разработка интерфейса
Общая информация
Основа: "Разработка интерфейса прикладных решений на платформе 1С:Предприятие 8" от 2018 г., платформа 8.3
ВАЖНО. Отказ от модальности - необходимое условие для работы в веб-клиенте и на мобильных устройствах.
Разработчик создает описание блоков интерфейса и события, за формирование вида отвечает платформа. Описание включает факт наличия элемента, свойства элемента и принадлежность к блоку, точное попиксельное размещение недоступно. Факт отображения зависит от прав пользователя.
Форма как программный объект существует на клиенте и на сервере. При реализации логики в общем случае происходит передача контекста с клиента на сервер и обратно.
Существуют реквизиты формы и параметры формы. Реквизиты формы связаны с отображаемыми элементами интерфейса и существуют все время существования формы. Параметры нужны для управления функциональностью формы и существуют в момент создания и открытия формы. Затем все параметры, кроме ключевых, удаляются.
Есть 4 режима основного окна: Обычный, Рабочее место, Полноэкранное рабочее место, Киоск. Не нашел и не попробовал, статья Далее обычный режим.
Основной тип интерфейса - Такси. Блочный однооконный, в web версии по виду и функциям аналогично desktop версии. Пользователь может донастраивать сам почти весь интерфейс. Блоки интерфейса:
Блок | Информация |
Область системных команд | Общие действия по управлению. Не зависит от конфигурации. Не настраивается пользователем и разработчиком. |
Панель разделов |
Главное + подсистемы первого уровня. Не настраивается пользователем. Настройка Главной: ПКМ на корне - Рабочая область начальной страницы. Не зависит Настройка набора видимых подсистем: ПКМ на корне - Открыть командный интерфейс конфигурации. Делится по ролям пользователей. Т е можно в правах ролей задать доступ к подсистеме в целом, а можно скрыть из списка. Роли: жесткое ограничение. Сокрытие означает, что оно будет не видно, но часть функций можно включить в другие системы/подсистемы и будет видно. |
Панель функций текущего раздела |
4 части: Элементы и 3 выпадающих списка: Еще, Создать, Отчеты, Сервис. Элементы: Сначала списки. Важное выделены жирным, самые первые. Все, что не вошло, попадает в выпадающий список Еще. Зависит от размера окна, чем уже - больше элементов в Еще. Элементы из подчиненных подсистем независимо суммируются с набором текущей, могут повторяться, деление на подчиненные не видно. Увидеть деление на подсистемы через блок Панель инструментов. |
Панель инструментов | Состоит из Меню функций, Избранное, История, Поиск, Центр оповещений. В меню функций видно деление на подчиненные подсистемы. Через шестеренку пользователь может настроить под себя. Если оповещений в принципе нет - элемент Центр оповещений отсутствует. |
Панель избранного | По умолчанию выключена. Для включенной панели нельзя настроить отображение. |
Панель истории | По умолчанию выключена. Для включенной панели нельзя настроить отображение. |
Панель открытых | По умолчанию выключена. Одна строка внизу. |
Рабочая область | Отображение элемента из выбранного блока. |
Информационная панель |
Отображение режима работы и отладочной информации. |
Настройка блочного состава пользовательского интерфейса.
ПКМ на корне конфигурации - Открыть интерфейс клиентского приложения.
Настройка интерфейса подсистем
Настраивается в основном разделе настройки подсистемы, кнопка командный интерфейс.
Формы интерфейса
Здесь и далее под формой понимается управляемая форма (часть кода на сервере, часть на клиенте).
Виды форм интерфейса и взаимосвязь параметров и Основного параметра реквизитов
Существуют формы объекта и произвольные формы.
Форма объекта - форма с заранее установленным реквизитом в соответствии с типом объекта (например в форме элемента это называется Объект и содержит реквизиты соответствующего элемента, в форме списка это Список).
В случае наличия возвращаемого значения (в форме выбора), возврат создается автоматически.
Поддерживается полная программная настройка жизненного цикла формы (Обработка входных параметров - Начальное заполнение - Обработка событий - Возврат выходных параметров).
Термин "заранее установленный реквизит" соответствует реквизиту формы с установленной опцией "Основной параметр".
Для структуры Параметры при программном открытии формы, ключ "Ключ" ссылается на основной параметр. Внутри формы он может называться как угодно, связь происходит по свойству "Основной параметр". В произвольной форме признак основной параметр можно установить, если в типе реквизита указать ...Объект, например СправочникОбъект.
Есть критичная особенность обработки данных, связанная с механизмом блокировок и основным параметром. При установке в свойствах команды флага Изменяет сохраненные данные,
при попытке выполнения команды будут выполняться следующие действия:
- Попытка заблокировать основной параметр. При неудаче команда не будет выполнена.
- Будет установлен признак изменения у формы (флаг «Модифицированность»).
- Для нового и несохранённого объекта будет произведена попытка записи. При этом пользователю будет задан вопрос о необходимости записи. Если ответ будет отрицательный — команда не будет выполнена.
Отсутствие этого флага не влияет на возможности модификации, но забота о целостности и непротиворечивости данных ложится на плечи разработчика.
Эксперимент. Бессмысленный с практической стороны, только для демонстрации взаимосвязи ключа "Ключ" и основного параметра формы. Справочник Города. В форму элемента добавлена кнопка и реквизит ссылка на товары. Обработка формы:
&НаКлиенте
Процедура КомандаОткрытияТоваров(Команда)
Парам = Новый Структура;
Парам.Вставить("Ключ", НужныйТоварСсылка);
ОткрытьФорму("Справочник.Города.Форма.ФормаПростоТак", Парам);
КонецПроцедуры
В ФормеПростоТак такая настройка:
Имена параметров не совпадают, но когда он основной реквизит - выбранный товар открывается. Похоже, в этом случае ссылка автоматически преобразуется в объект. Если не основной - не открывается. А далее было получено парадоксальное (на момент написания этой строки) поведение: если реквизит основной, но в обработке формы меняю имя параметра на совпадающее название (Ключ1) - данные не подгружаются. После раскуривания умной книжки опять пришлось выдохнуть, улыбнуться, понять и простить разработчиков за использование одного и того же слова в разных контекстах и скрытое преобразование данных:
Взаимосвязь между структурой Параметры в методе Открыть форму (см. раздел Открытие другой формы), реквизитами и параметрами формы. Перед созданием формы, структура Параметры в методе Открыть форму сопоставляется с параметрами в разделе Параметры в форме и стандартными ключами.
При обработке события "При создании на сервере" доступна структура Параметры, в которой будут находиться все переданные параметры. Факт наличия конкретного параметра в списке параметров формы не важен (понять и простить). Указание в списке параметров влияет только на отображение этого параметра в списке контекстной подсказки, но при указании несуществующего параметра ошибки не происходит, и если этот параметр был передан - он считается.
Параметр "Ключ" передается в реквизит со свойством "Основной параметр" напрямую и это свойство может быть выставлено только у одного реквизита. Если в обработке события "При создании на сервере" не сделать заполнение реквизитов (или каких-либо других действий), все пользовательские параметры будут проигнорированы и затем структура Параметры очищается.
&НаСервере
Процедура СообщитьИнфу()
Сообщить(Параметры.Реквизит3);
КонецПроцедуры
&НаКлиенте
Процедура Команда1(Команда)
СообщитьИнфу();
КонецПроцедуры
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Реквизит1 = Параметры.Реквизит3;
КонецПроцедуры
Команда1 привязана к кнопке на форме. В параметрах формы - Реквизит2. Реквизит3 в параметрах формы отсутствует. В реквизитах формы - Реквизит1. Следующий код корректно открывает вышеуказанную форму и заполняет Реквизит1 значением 5:
&НаКлиенте
Процедура КомандаОткрытияФирм(Команда)
Парам = Новый Структура;
Парам.Вставить("Реквизит3", 5);
ОткрытьФорму("Справочник.Города.Форма.ФормаПростоТак", Парам);
КонецПроцедуры
При выполнении процедуры СообщитьИнфу выдается ошибка отсутствия поля Реквизит3. То есть структура Параметры после создания формы остается, но пустая. Если перенести Сообщить(Параметры.Реквизит3); в Команда1, то ошибка такая же.
Передача реквизита формы в серверную процедуру
Необходимость в данной технологии возникает, когда есть данные на форме, и нужно провести с ними манипуляции. Т е есть еще не записанные в базу данные и есть модули (общие, ...) и нужно передать туда данные без записи, модифицировать и отдать обратно в форму.
РеквизитФормыВЗначение() компилируется &НаСервере, контекст формы необходим. На клиенте не работает, поскольку в результате получаем прикладной объект.
ЗначениеВРеквизитФормы() для возврата данных на форму. Вторым параметром является тип значения, необязательный. Если обрабатываемый реквизит не является составным типом, то тип будет автоматически получен из реквизита формы. Иначе генерируется исключение времени выполнения.
&НаСервере
Процедура ЗаполнитьТЧПоДаннымПоследнегоДокумента(Контрагент)
ДокОбъект = РеквизитФормыВЗначение("Объект");
ДокОбъект.ЗаполнитьТЧПоДаннымПоследнегоДокумента(Контрагент);
ЗначениеВРеквизитФормы(ДокОбъект, "Объект");
КонецПроцедуры
Точки хранения форм
Формы могут храниться в Общие - Общие формы и в объектах конфигурации, раздел Формы. Произвольную форму можно создать во всех точках хранения.
В общих формах можно создать формы констант, отчетов, динамических списков, поиска, истории данных.
В объектах конфигурации - набор форм в соответствии с типом объекта. Создание произвольной формы в объекте конфигурации технически возможно, актуально если логически данная форма выполняет действия, связанные с этим объектом. Должны быть аргументы для размещения произвольной формы в объекте, в общем случае логичнее произвольную форму разместить в общих формах. Плюс размещения произвольной формы в объекте - возможность выбора этой формы в качестве формы чего-либо. Однако, стандартная форма ничем не хуже произвольной, кроме уже настроенного объекта и привязанного к нему свойству Основной реквизит.
Модальные и обычные окна
Модальные окна в 1С - это такой тип окна, вызываемый в среде 1С, который блокирует остальной интерфейс 1С 8. Сейчас устаревшая технология.
Способы взаимодействия между формы
Посмотреть интерактивное взаимодействие и оповещения
- ОткрытьМодально, параметр закрытия, метод Закрыть. - устаревший способ, не использовать.
//В первой форме ВозвращаемоеЗначение = ДругаяФорма.ОткрытьМодально(). //В другой форме ЭтаФорма.Закрыть(ВозвращаемоеЗначениеВПервуюФорму)
- Реквизиты формы (или свойства расширения формы). Реквизиты формы видимы снаружи как свойства объекта «Форма».
//В первой форме ДругаяФорма.ИмяРеквизита = Значение.
- Через ЭлементыФормы.
//В первой форме ДругаяФорма = ДокументСсылка.ПолучитьФорму(). ДругаяФорма.ЭлементыФормы.ИмяПоля.Значение = Значение.
- Оповещения.
//В первой форме оповещаются все открытые формы Оповестить("ИмяСобытия", "Форма1", Данные); //В другой форме следует назначить обработчик события оповещения. Процедура ОбработкаОповещения(Событие, Источник, Данные) Если Событие = "ИмяСобытия" И Источник = "Форма1" Тогда КонецЕсли; КонецПроцедуры
- Экспортные переменные модулей форм. Они становятся видимы снаружи примерно как реквизиты форм.
//В первой форме ДругаяФорма.ИмяПеременной = Значение; //В другой форме Перем ИмяПеременной Экспорт;
- Параметры сеанса.
//В первой форме ПараметрыСеанса.ИмяПараметра = Значение //В другой форме Если ПараметрыСеанса.ИмяПараметра = Значение Тогда КонецЕсли
Работа с элементами формы
Доступ к выбранному элементу табличной части. Контактные лица - имя табличной части.
&НаКлиенте
Процедура СообщитьВыбраннуюСтроку(Команда)
ВыбранныйКонтакт = Элементы.КонтактныеЛица.ТекущиеДанные;
Если ВыбранныйКонтакт = Неопределено Тогда
Сообщить("Контактов не существует");
Иначе
Сообщить(ВыбранныйКонтакт.Телефон);
КонецЕсли;
КонецПроцедуры
Проверка заполнения поля. Важный момент, потратил минут 30. ! Код нужно тестировать !
ЗначениеЗаполнено(Поле)
Открытие формы.
Статья по открытию форм, но стоит проверить данные в статье.
Существуют объекты ссылочного типа (Справочники, элементы справочника и т д) и нессылочного, например элементы регистра. Естественно, если в форме присутствует ссылка на объект, их можно передать в создаваемую форму в качестве параметра.
Способы открыть форму:
ОткрытьФорму | ПолучитьФорму | ПоказатьЗначение |
Основной универсальный способ. Сразу открывает форму. | Получаем форму без открытия, затем метод Открыть. Как ОткрытьФорму. | Типа упрощение, негибкое |
Метод ОткрытьФорму. Универсальный способ. Полный список параметров метода «ОткрытьФорму»: ИмяФормы, Параметры, Владелец, Уникальность, Окно
Свойство ИмяФормы. Пример открытия формы с передачей только имени формы. Параметром передается строка, подсказки нет, поэтому внимательно к именам (Справочник в единственном числе, Форма в единственном числе).
ОткрытьФорму("Справочник.Товары.ФормаЭлемента");//Основная форма
ОткрытьФорму("Справочник.Товары.Форма.ПроизвольнаяФормаТовара");// + слово Форма для неосновной формы
Нюансы: формы константы нет, нужно сначала создать общую форму констант.
Пример. Кнопка, к которой привязано действие, размещена в форме элемента справочника Города.
&НаКлиенте
Процедура КомандаОткрытияТоваров(Команда)
ОткрытьФорму("Справочник.Товары.Форма.ФормаСпискаТовары");
КонецПроцедуры
Свойство «Параметры» Тип Структура. Передать туда можно все, что можно передать с клиента на сервер.
Если объект ссылочный (например конкретный документ, на который есть ссылка), то необходимо в поле Ключ передать ссылку.
Пример: есть справочник, в котором есть табличная часть КонтактныеЛица. У табличной части есть реквизит ДокументТестовый типа ДокументСсылкаПоступлениеТоваров. Процедура обработки нажатия на кнопку:
&НаКлиенте
Процедура ОткрытьДокумент(Команда)
ВыбранныйКонтакт = Элементы.КонтактныеЛица.ТекущиеДанные;
Если ВыбранныйКонтакт = Неопределено Тогда
Сообщить("Контактов не существует");
Иначе
Док = ВыбранныйКонтакт.ДокументТестовый;
Если ЗначениеЗаполнено(Док) Тогда
Парам = Новый Структура;
Парам.Вставить("Ключ", Док);
ОткрытьФорму("Документ.ПоступлениеТоваров.ФормаОбъекта", Парам);
Иначе
Сообщить("Документ не привязан.");
КонецЕсли
КонецЕсли;
КонецПроцедуры
При передаче пустого ключа создастся новый документ.
В случае, если нужно создать новый объект на основании существующего, то нужно добавить параметр "Основание" со ссылкой на объект, на основании которого нужно сделать новый документ. В этом случае вызывается процедура «ОбработкаЗаполнения» модуля объекта. Эта процедура имеет единственный параметр «Основание». Если мы в параметры вставим ключ «Основание», то он будет передан в процедуру «ОбработкаЗаполнения».
Если нужно открыть форму создания группы, то в параметрах указать "ЭтоГруппа" Истина.
События формы
События при создании формы (сверху вниз)
Модуль формы клиент | Модуль формы сервер | Модуль объекта сервер |
При чтении на сервере (существующий объект) | Обработка заполнения (новый объект) | |
При создании на сервере | ||
При открытии |
Прикладные задачи
Передача параметров в произвольный запрос динамического списка. При открытии формы передаются конкретные значения параметров, в обработчике события формы При создании на сервере эти значения устанавливаются параметрами запроса в динамическом списке.
Эстетическое оформление
Цвет
ЭлементыФормы.ПолеВвода1.ЦветФонаПоля = WebЦвета.Красный;
ЭлементыФормы.ПолеВвода1.ЦветФонаПоля = Новый Цвет(51,51,51);
Цвет по-умолчанию задается пустым Цвет():
Если Объект.Завершен Тогда
Элементы.ПроцессЗавершенНадпись.ЦветТекста = Новый Цвет();
КонецЕсли;
Общая информация
Программное создание элементов оформления
Но создавать программно команды нельзя, а можно создавать ссылки на созданные команды.
Элементы оформления и представления реквизитов
Под элементом оформления будем понимать элемент, создаваемый без участия реквизита, а под представлением реквизита - элемент оформления, создаваемый из реквизита. Это почти одно и то же, но есть нюансы: есть 3 набора элементов, которые нельзя создать из реквизитов: Группа, Декорация и Дополнение элемента формы. А представления реквизитов - это настроенный под отображение реквизита определенного типа, один из трех оставшихся элементов оформления (поле, кнопка, Таблица). Так что привязанные к реквизиту элементы оформления проще создавать из реквизитов путем перетаскивания на форму. Дальше слово свойство подразумевает свойство элемента оформления.
Группы-Обычная группа контейнер компонентов, расположенных в соответствии с настройками (горизонтально или вертикально). Могут быть окружены рамкой, отображаться на общем фоне заданного цвета и иметь общий заголовок. Комбинируя свойства Поведение, горизонтально / вертикально и дочерние группы можно сделать очень навороченный интерфейс.
Группы-Страницы. Для страничного отображения. Внутри нужно добавить группы для отображения в виде страницы. Тип у дочерней группы становится Страница)
Группы-Командная панель. Отображает команды, созданные в форме или у существующих элементов (у кого команды предусмотрены). Хотя у меня не отобразилась команда в списке возможных, так что хз.
Декорация-Надпись и Декорация-Картинка есть события нажатие и обработка навигационной ссылки.
Дополнение элемента формы. Можно указывать строку поиска, управление поиском. Нужно указывать табличный элемент, по которому будет происходить поиск. Если нужно вынести блок поиска в другое место от шапки таблицы.
Общие свойства элементов оформления
Заголовок. Работает для простых типов - подпись около элемента. Для сложных - не работает.
Важность при отображении. Работает в случае мобильного клиента. Группирует менее важные элементы в выпадающий список.
Расположение. Ширина и Высота 0 - авто, однако старается вместить все элементы, комбинация например горизонтальная всегда и ширина 10 для 4 кнопок не работает. Однако например вертикальная и 10 сжимает каждую из 4 кнопок.
Детали для элемента Группа
Вид. Соответствует типам групп Обычная группа, Страницы, Командная панель.
Поведение. Два дополнительных способа - Свертываемая и Всплывающая.
Свертываемая - позволяет свернуть элементы. Должно быть задано свойство Заголовок (будет отображаться в раскрытом состоянии). Может быть задано свойство ЗаголовокСвернутогоОтображения и свойство Свернута. Свойство ОтображениеУправления (картинка или гиперссылка) определяет вид оформления заголовка.
Всплывающая - по умолчанию в виде ссылки, по клику всплывает дополнительное окно (не модальное).
Отображение. Степень акцента на группе при помощи размера шрифта заголовка и расстояния между группами, Нет соответствует группе без отображения.
Группировка. Порядок группировки вложенных элементов внутри группы.
Объединенная. Не понял, зачем нужно. Ведь если группа создается, то подразумевается, что элементы должны подчиняться правилам группы.
Сквозное выравнивание. Опция усреднения выравнивания элементов внутри разных групп.
Путь к данным заголовка. Если указано, то в скобках после названия группы это указывается.
Формат. Формат представлений чисел, дат и булева типа. - если указан путь к данным заголовка.
Использование ТекущейСтроки, ИспользуемаяТаблица. Для мобильного приложения.
Детали для элемента Строка.
Тип оформления может быть строкой ввода, подписью, переключателем, картинкой, HTML документом, PDF документом, текстовым документом.
Тип оформления Картинка Нужен для отображения сохраненной в базе в хранилище значений изображения.
Тип оформления Поле html документа. Позволяет загрузить html код, добавленный в виде текста. Может подгружать картинки из внешних источников (Интернета). Но грузился долго. Но если добавить в событие ПриОткрытии - остальная форма доступна.
МояСтрока = "<!DOCTYPE html><html lang=""en""><head><meta charset=""UTF-8""><meta name=""viewport"" content=""width=device-width, initial-scale=1.0""><title>Документ</title></head><body><h1>Привет!</h1><img src=""https://helpf.pro/uploads/avatars/00.gif""></body></html>"
Переадресация страницы сработала.
МояСтрока = "<!DOCTYPE html><html><head><meta http-equiv=""refresh"" content=""0;url=https://dzen.ru""></head></html>"
Если ссылка открывается в новой странице - тогда в браузере. JS скрипт вывода сообщения пользователю не выполнил. А скрипт отображения часов сработал:
МояСтрока = "<!DOCTYPE html><html></head><body><div id=""clock""></div><script>window.onload = function(){window.setInterval(function(){var now = new Date();var clock = document.getElementById(""clock"");clock.innerHTML = now.toLocaleTimeString();},1000);};</script></body></html>";
Поддержка стилей есть. Резюме: внешний html ресурс возможен, но стоит 2 раза подумать, выпить глоток кофе и еще раз подумать.
Создать html ссылку
Оказалось непростым делом. Аж уже начал думать, что через html документ делать - в топе поиска устаревшая информация. Создается команда формы,
&НаКлиенте
Процедура ОткрытьПомощьПинг(Команда)
ПерейтиПоНавигационнойСсылке("http://tvm16:81/doku.php/aisimushestvo/pingcheck");
КонецПроцедуры
перетаскивается на форму, и в свойствах кнопки выставляется вид Гиперссылка.
Интерактивное взаимодействие и оповещения
Вывод информации пользователю
Предупреждение("Текст", Таймаут_число, "Заголовок окна сообщения"); //окно сообщения
Сообщить("1!", СтатусСообщения.Важное); //в блоке сообщений
Получение информации от пользователя во всплывающем окне
ВвестиЧисло();
ВвестиЗначение();
ВвестиСтроку();
ВвестиДату();
Вариации модальных окон (предыдущие примеры) использовать нежелательно, скорее всего от данной технологии будут отказываться. Лучше использование асинхронного взаимодействия. В частности, можно использовать процедуру “ПоказатьВопрос()” в сочетании с механизмом описания оповещения.
&НаКлиенте
Процедура СоздатьДоговоры(Команда)
Если ЭтотОбъект.Модифицированность Тогда
ОписаниеОповещения = Новый ОписаниеОповещения("СоздатьДоговорыЗавершение", ЭтотОбъект);
ПоказатьВопрос(ОписаниеОповещения, "Документ должен быть записан. Записать и продолжить?", РежимДиалогаВопрос.ДаНет);
Иначе
//Если спрашивать не требуется вызываем процедуры завершения
СоздатьДоговорыЗавершение(КодВозвратаДиалога.Нет);
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура СоздатьДоговорыЗавершение(Результат, Параметры = Неопределено) Экспорт
Если Результат = КодВозвратаДиалога.Да Тогда
//Действия выполняемые при положительном ответе пользователя
КонецЕсли;
//Действия выполняемые независимо от ответа пользователя
КонецПроцедуры
Обновление данных на форме в пределах своей сессии
Оповещения
Статья про оповещения пользователю
Под термином "Оповещение" в одном контексте оповещения пользователю (ссылка выше), в другом - способ взаимодействия между формами в пределах одной сессии (это важно!). Для второго варианта в форме пишется обработчик оповещений, при генерации в форме-источнике запускается обработчик и в обработчике можно фильтровать события по источнику и названию. Типа шина межоконного клиентского взаимодействия в пределах одной сессии.
//В первой форме оповещаются все открытые формы
Оповестить("ИмяСобытия", Данные, "Форма1");
//В другой форме следует назначить обработчик события оповещения.
Процедура ОбработкаОповещения(Событие, Данные, Источник)
Если Событие = "ИмяСобытия" И Источник = "Форма1" Тогда
КонецЕсли;
КонецПроцедуры
И - нихера не заработало! А все потому, что процедуру ОбработкаОповещения нужно создавать не лапками, а через ПКМ на форме - События - ОбработкаОповещения либо указав созданную лапками процедуру в событии ОбработкаОповещения. И реально работает только если форма открыта.
Обновление данных на форме у всех пользователей
Здесь кроется одина из фундаментальных проблем 1С, понять и простить. При открытии формы редактирования (например элемента справочника, ... будем называть его объектом), до версии 8.3.14 объект блокировался на изменение у других пользователей. Т.е., если я открыл в справочнике Номенклатура объект Ручка красная, то если кто-то попытается его открыть у себя - получит сообщение о блокировке на запись и все. И пока я просто держу открытой эту вкладку- она заблокирована у всех остальных. После 8.3.14 стало чуть лучше, блокировка для данных открытой формы снимается через 1 минуту после сохранения. Работает на толстом клиенте в файловом режиме. Однако в web клиенте в файловом режиме блокировка устанавливается после первого нажатия Сохранить, затем не снимается до закрытия формы. Подробнее о механизме блокировок
Динамические списки: Элементы.ИмяДинамическогоСписка.Обновить()
Реквизиты формы: Методы ЭтаФорма.Прочитать() и ЭтаФорма.ОбновитьОтображениеДанных(). Метод Прочитать обновляет объект управляемой формы. Метод ОбновитьОтображениеДанных принудительно обновляет содержание элементов управления, особенно полезно, когда изменения значений реквизитов формы происходят вне самой формы. Это гарантирует, что каждый элемент в форме будет соответствовать последним изменениям данных в системе.
Динамическое обновление открытой формы. Методы в предыдущем разделе должны быть чем-то вызваны. Периодические задания исполняются только на сервере, для клиента не подходят. Шикарная статья про обработчики Понять и простить. С ностальгией вспомни школьные годы, метод обновления периодическими опросами сервера и вперед! Базовый код:
&НаКлиенте
Процедура ОболочкаОбработчика()
Элементы.СписокГородов.Обновить();
КонецПроцедуры
&НаКлиенте
Процедура ПодключитьОжидание(Команда)
ПодключитьОбработчикОжидания("ОболочкаОбработчика", 10, Ложь);
КонецПроцедуры
&НаКлиенте
Процедура ОтключитьОжидание(Команда)
ОтключитьОбработчикОжидания("ОболочкаОбработчика");
КонецПроцедуры
Это работает и в web клиенте. Не нашел способа получить список подключенных обработчиков, поэтому необходимы глазками-контролируемые правила создания и отключения обработчиков.
Важно: Если действие на сервере затратило меньше времени, чем таймаут, то обработчик строго по таймауту вызовет нужное, будто серверной приостановки и не было; а если больше, то "собьётся" и вызовется сразу по возвращении с сервера.
При высокой нагрузке на базу стоит усложнить алгоритм см. Динамические списки раздел Обновление данных.
Пример автоматического обновления данных в таблице значений.
Есть справочник Города, только Наименование. Есть обработка, где в таблице будем выводить и обновлять значения из справочника. Практически это может пригодиться только если форма объемная, нужно поддерживать актуальность одной таблицы из нескольких, а полное обновление формы замедлит работу.
У элемента Таблица нужно добавить колонки реквизитов, в этом случае - одну колонку Наименование. При добавлении на форму, будет предложено добавить колонки.
Вроде не может использоваться на веб клиенте, но у меня поехало.
&НаКлиенте
Процедура ОболочкаОбработчика()
//Элементы.СписокГородов.Обновить();
ОбновитьТаблицу();
КонецПроцедуры
&НаКлиенте
Процедура ПодключитьОжидание(Команда)
ПодключитьОбработчикОжидания("ОболочкаОбработчика", 10, Ложь);
КонецПроцедуры
&НаКлиенте
Процедура ОтключитьОжидание(Команда)
ОтключитьОбработчикОжидания("ОболочкаОбработчика");
КонецПроцедуры
&НаСервере
Процедура ОбновитьТаблицу();
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Города.Наименование КАК Наименование
|ИЗ
| Справочник.Города КАК Города";
РезультатЗапроса = Запрос.Выполнить();
//СпособОбхода = ОбходРезультатаЗапроса.Прямой;
СписокГородовТаблица.Загрузить(РезультатЗапроса.Выгрузить())
КонецПроцедуры
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
ОбновитьТаблицу();
КонецПроцедуры
Метод Загрузить(РезультатЗапроса.Выгрузить) работает если наименования колонок совпадают с наименованиями столбцов в запросе.
Заметил, что при обновлении динамического списка на указателе мыши возникает кружок ожидания, однако фокус в списке после обновления не смещается. У таблицы кружок не возникает, однако фокус смещается на первый элемент.
На потом, не завершено: Появилась идея в обновления таблицы только в случае изменения хэша. Нужно бы проверить скорость работы, но пока не до этого. Однако сам факт вычисления хэша затратен.
На потом, не завершено: Предположительный алгоритм обновления с динамическим изменением периода опроса.
Проблема: в случае большого количества клиентов со включенными обработчиками возможна нагрузка на сервер.
Задача: Необходим алгоритм, управляющий периодами обновления данных на клиентах с приоритетами по объектам. Также при необходимости (например, наличие ресурсоемких задач на сервере), должен быть способ общего увеличения периода. На сервере могут быть другие базы, иные серверные скрипты, поэтому у нас нет полного доступа ко всем процессам, только локальная оценка производительности. Все клиенты равнозначны (хотя для общего решения лучше делить по пользователям, но потом).
Решение:
На сервере:
Регистр сведений, измерения - НазваниеПроцедуры, Ресурсы - ВремяПоследнегоИзменения, ЗадержкаОбновления. Служит для серверного изменения при обновлении данных. Способ реализации обновления этого регистра - отдельный вопрос.
Зарезервированное название процедуры - ПериодОбновленияРегистра для управления обновлением регистра на клиенте. При нагрузке увеличить задержку обновления и общий период обновления.
На клиенте:
ПараметрСеанса Строка, сериализованный аналог полей регистра сведений об обновлениях, только индивидуально для каждого сеанса. Часть процедур, которые нужны конкретному сеансу. На формы добавить события ПриОткрытии/Закрытии, для поддержания актуальности о подписанных процедурах. Процедуры сериализации / десериализации данных и обновления регистра. При пустом параметре, обновления регистра прекращаются. Если ВремяПоследнегоИзменения в регистре больше чем в параметре сеанса, то через ЗадержкуОбновления произвести обновление. Т е у каждой формы практически одинаковый алгоритм проверки / обновления.
Вопросы к постановке задачи и алгоритму:
- Как определить, что количество клиентов стало "большим"
- А может быть это не нужно?
Динамические списки
Используется для отображения информации из любых таблиц независимо от их типа.
Похоже, динамический список формируется на сервере и затем представление передается на клиент. Поэтому использование именно динамического списка, а не например таблицы значений, должно быть осознанно. Динамический список предоставляет встроенные опции (стандартные команды, переходы для выделенных объектов), однако может сильно тормозить работу в случаях например часто меняющейся выборки из большого объема данных. Иногда эффективнее один раз загрузить на клиент данные и организовать фильтрацию на клиенте, без постоянной нагрузки на сервер и каналы связи.
Шаги использования динамического списка:
1 Наполнение данными
Данные могут быть получены из основной таблицы или через произвольный запрос. Способ получения данных настраивается в свойствах динамического списка, галочка Произвольный запрос.
Для обоих вариантов существует настройка Отбор (какие данные попадут в итоговый список), результат его работы пересекается с настройками запроса, поэтому требует углубленного понимания. Скорее всего, такая херня возникла из-за попытки сделать сложную вещь доступной прогерам-мышкотыкам (как и все в 1С), но потом пришли к выводу, что потенциал у данного типа данных большой, реализовать все возможные варианты через удобный графический интерфейс нельзя, а часть интерфейса создана, пусть будет. Понять и простить.
Основная таблица | Произвольный запрос | |
Набор данных | Поля одной таблицы | Поля любого запроса |
Интерактивная настройка (через отбор) | Настройка в конфигураторе повторяет настройку отображения в пользовательском интерфейсе. Ручное указание конкретного параметра либо общие типы (пустое, больше/меньше, ...) | Нельзя изменить запрос, остальное так же |
Программная настройка параметров, включая параметры из реквизитов | Нет | Есть |
Встроенный функционал редактирования списка | Да | Только если указана опция "Основная таблица". |
Можно сделать вывод: настройка динамического списка через отбор конфигуратора актуальна для простейших задач (убрать пустые, ограничить по фиксированному значению, ...). В остальных случаях эффективнее работать через фильтрацию в параметрах запроса. Поэтому настройку отбора через вкладки с получением данных из основной таблицы рассмотрим в разделе Настройка отображения, далее будем рассматривать фильтрацию через произвольный запрос.
Произвольный запрос. Выберем следующие данные:
ВЫБРАТЬ
ДокументПоступлениеТоваров.Ссылка,
ДокументПоступлениеТоваров.Номер,
ДокументПоступлениеТоваров.Дата,
ДокументПоступлениеТоваров.Фирма,
ДокументПоступлениеТоваров.Филиал,
ДокументПоступлениеТоваров.ПереченьТоваров
ИЗ
Документ.ПоступлениеТоваров КАК ДокументПоступлениеТоваров
ГДЕ
ДокументПоступлениеТоваров.Дата < &НужнаяДата
Для параметров необходимо задать значение перед использованием. Это настраивается в модуле формы в процедуре «ПриСозданииНаСервере».
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
ДокументыПоступленийТоваров.Параметры.УстановитьЗначениеПараметра("НужнаяДата", ТекущаяДата());
КонецПроцедуры
ДокументыПоступленийТоваров - имя реквизита Динамический список.
2 Настройка отображения
Для всех разделов.
Несколько правил объединяются по способу И, правила можно объединять в группы, а для групп настраивать способ И, ИЛИ, НЕ.
В рамках одного пользователя сохраняется последняя настроенная группа правил.
Можно создавать преднастроенные наборы правил.
Отбор. Задается фиксированная настройка динамического списка. Виды сравнения зависят от типа данных поля, бывают в частности фиксированные (равно, больше, меньше), в списке, заполнено, в группе и обратные операции.
Порядок. Задается поле и тип сортировки. Несколько правил применяются последовательно, в рамках одинакового первого правила сортируется по следующему и т д.
Условное оформление. Может быть несколько правил, для каждого правила параметры оформления, условия и оформляемые поля. Параметры оформления: цвет фона, цвет текста, шрифт, положение текста, выделение отрицательного, шаблон текста, видимость, доступность. Т е здесь, как и в правилах отбора, можно даже ограничить видимость элементов. Сравнение способов ограничения видимости:
Запрос | Отбор | Условное оформление | |
Точка фильтрации | На сервере | На сервере | На клиенте |
Простота | Сложно | Просто | Просто |
Скорость создания фильтра | Медленно | Быстро | Быстро |
Настраиваемость | Динамическая | Статическая | Статическая |
Объем передаваемых данных | Только попавшие в фильтр | Только попавшие в фильтр | Все |
Изменение пользователем | То что разрешено разработчиком | Да | Да |
Группировка. Несколько правил применяются последовательно, в рамках одинакового первого правила группируется по следующему и т д.
3 Интерактивное взаимодействие
В случае установленной Основной таблицы доступен стандартный набор команд (создание, удаление, изменение).
Элементы.элСписок.ТекущаяСтрока = НоменклатураСсылка; //получение и изменение текущей строки,
Сообщить(Элементы.элСписок.ТекущаяСтрока.Цена);// данные заново получаются из базы
Сообщить(Элементы.элСписок.ТекущиеДанные.Цена);// данные получаются из существующих данных
//перебор строк динамического цикла
&НаСервере
Процедура ЦиклПоСтрокамДинамическогоСписка()
ТЗ_ДС = СписокВТЗ();
Для Каждого Стр Из ТЗ_ДС Цикл
// .........
КонецЦикла;
КонецПроцедуры
5 Обновление данных
Сама по себе информация в списках не обновляется. Необходимо два компонента: процедура, генерирующая информацию о факте изменения данных и способ распространения информации об изменении по открытым формам (метод обновления). Стандартного общего события при обновлении данных например у справочника не нашел. Поэтому для реализации задачи поддержки актуальности чувствительных данных в открытых формах возможны следующие варианты:
- Отказаться от стандартного механизма работы с данными, переписать процедуры обновления в отдельные формы и добавить оповещение об обновлении (см. ниже). При небольшом количестве точек изменения это сработает, но поддержка муторная. И если кто-то из разработчиков случайно забудет о необходимости использования только специальных процедур и добавит случайно прямое изменение данных - появятся фантомные неактуальные данные. А еще - см. блок "Нае*али, но понять и простить"
- Периодический контроль на уровне таблицы средствами языка 1С и оповещения в случае изменения. Упрощает задачу с точки зрения контроля точек изменения данных, но хорошо нагружает сервер. К тому же, это будет обновление с задержкой (минимум в минуту для файловой базы). Если таблицы объемные, данные меняются относительно нечасто, то постоянное хеширование сильно замедлит работу.
- Вариации на тему генерации события изменения на уровне базы данных, дополнительных сервисов на чем-нибудь. Возможно с добавлением endpoint в 1С.
Например, клиент-серверный вариант, БД Postgresql (для mssql похоже все гораздо сложнее). В 1С поднимается web сервис, при обращении на который генерируются оповещения по открытым клиентским формам. На postgresql устанавливается расширение plpython3u, настраивается триггер на изменение нужных таблиц и за счет этого генерируется REST запрос при изменении данных. Решение на случай "ПИЗДЕЦ КАК НАДО СОБЫТИЙ ДОХЕРА В РАЗНЫХ ТОЧКАХ ПОЛЬЗЫ НЕ МОГУТ САМИ ПОСТОЯННО ОБНОВЛЯТЬ, НА СЕРВЕР НЕТ ДЕНЕГ ЗАТО ЕСТЬ ДЕНЬГИ НА РАЗРАБОВ".
Решение сложно сопровождаемое, зависящее от имен нужных таблиц, требующее разработчиков на других языках. Очень дорогое. - Периодический опрос сервера из формы. Нагрузка растет произведением от количества клиентов, количества контролируемых таблиц, их объема и минимального периода обновления. Если добавить возможности периодического регистра сведений, то нагрузка перестанет зависеть от количества клиентов. Возможно эту задачу вынести на отдельный сервер, организовав например кластер БД, скрипт по пересчету на другом сервере и еще какое-нибудь извращение. Но все равно обновление с задержкой, от 1 минимального периода обновления. Самый допотопный способ, но при некоторых условиях имеет право на использование. Дополнение: когда это писал, реально думал что это древняя технология и нужно просто узнать, как это реализуется в 1С. Но... Похоже это единственный рабочий способ,
- Есть отдельный продукт 1С:Предприятие - Сервер взаимодействия, но нужно тестировать.
Но в целом, 1С даже близко не позиционируется как система реального времени / мгновенного обновления / совместного редактирования, так что особых претензий к отсутствию данных технологий быть не может. Возможно, стоит пересмотреть формулировку задачи или вынести данный функционал совсем за пределы 1С.
В перечисленных способах используется термин "Оповещение об обновлении". Методы оповещения представлены ниже. Метод ОповеститьОбИзменении работает только для динамических списков, да и то только для списков с указанной основной таблицей. Метод Оповестить универсальный.
Здесь возникает парадокс: обычно начинает использоваться дополнительная технология в связи с упрощением решения нужной задачи. Однако если эта технология ведет к дополнительным трудностям, то стоит сопоставить получаемые преимущества, возникающее усложнение и степень решения задачи.
Методы обновления
стр. 576 книги Разработка интерфейсов.
Метод ОповеститьОбИзменении() В него передается ссылка на объект (или ключ записи), об изменении которого нужно оповестить формы. Он уведомит все динамические списки, расположенные в созданных на клиенте формах, об изменении этого объекта, и они обновят свои данные. Но этот метод не обновит те динамические списки, у которых не задана основная таблица. Преимущество: процесс автоматический, без изменения форм. Но этот метод можно использовать только из клиента. Как следствие, списки в другой сессии / у другого пользователя не обновляются.
//ДобавитьЭлементНаСервере() - функция, возвращающая ссылку на новый элемент
//в какой-то форме
СсылкаНаНовыйЭлемент = ДобавитьЭлементНаСервере();
ОповеститьОбИзменении(СсылкаНаНовыйЭлемент);
Метод Оповестить() Нужно добавить код обработки оповещений в формах, в которых нужно что-то обновлять. Метод
глобального контекста Оповестить() отсылает оповещение всем созданным (не обязательно открытым) формам. В форме в обработчике события ОбработкаОповещения() можно обработать это сообщение и выполнить нужную модификацию формы.
И один хер у другого пользователя не обновляется!
&НаКлиенте
Процедура ОбщееОповещение(Команда)
Элем = СоздатьСОповещениемНаСервере();
Оповестить("ДобавлениеЭлемента");
КонецПроцедуры
&НаКлиенте
Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
Если ИмяСобытия = "ДобавлениеЭлемента" Тогда
Элементы.ИзСправочника.Обновить();
КонецЕсли;
КонецПроцедуры
Нае*али, но понять и простить.
У 1С нет стандартных технологии а-ля longpool, только метод Обновить.
Сценарное тестирование
Эта тема, судя по количеству информации, только начинает развиваться.
Встроенный инструмент
Исполнение тестов: запуск тестируемой конфигурации с ключом /TESTCLIENT, написания тестов в другой конфигурации и запуском ее с ключом /TESTMANAGER. Пример теста
Готовые конфигурации для тестов
Корпоративный инструментальный пакет (КИП) 1С предлагает использовать КИП, в состав которого входит конфигурация Сценарное тестирование. Стоимость пакета 130 т. Отдельные высокоуровневые команды (хорошо хоть немного) + доп. инструменты упрощающие поиск элементов.
Тестер. Бесплатная конфигурация для сценарного тестирования решений на базе 1С:Предприятие 8.3, управляемые формы.. https://tester.help/ Последнее обновление в 2023.
Отчеты
Система компоновки данных: устройство
Доп. материалы к книге. Архив распаковывается, устанавливается база из папки report82/conf/setup.exe Весит немного. Затем при добавлении новой базы указать новую и в списке будет данный шаблон.
Этапы формирования отчета:
- Разработчик создает схему компоновки данных и стандартные настройки компоновки, которые содержат полную информацию о компоновке.
- На основе схемы компоновки данных и настроек компоновки, компоновщик макета создает макет компоновки данных, который является уже готовым заданием для процессора компоновки.
- Процессор компоновки данных в соответствии с макетом компоновки извлекает данные из информационной базы, агрегирует, оформляет эти данные и формирует результат компоновки. Результат компоновки состоит из массива элементов, которые можно получать последовательно, но в большинстве случаев результат компоновки получается целиком.
- Процессор вывода обрабатывает результат компоновки и выводит его в различные форматы: табличный документ, HTML-документ, таблица значений, дерево значений.
Схема компоновки данных
Схема компоновки данных (СКД) – декларативный инструмент создания отчетов. Состоит из набора элементов, у каждого свое декларативное описание и возможность XML сериализации. Создать СКД можно при помощи конструктора, через создание XML документа или через код.
Состав СКД:
Наборы данных.
Источник данных для отчета. Получают из информационной базы или из некоторых объектов в памяти (например, из таблицы значений). Один отчет может использовать одновременно несколько наборов данных. Виды наборов данных:
- Запрос – содержит запрос к базе данных на языке запросов с использованием дополнительных синтаксических элементов (расширений)
- Объект – содержит информацию о внешнем наборе данных, например, таблице значений;
- Объединение – объединяет информацию из нескольких наборов данных.
Связи наборов данных.
Используется для описания правил объединения наборов данных. Аналог соединения и объединения в языке запросов.
Вычисляемые поля.
Ресурсы.
Групповые итоговые данные. В большинстве случаев необходимо указывать.
Параметры.
Параметры для набора данных, обычно задается пользователем.
Макеты.
Вложенные схемы.
Использование данных одного отчета внутри другого.
Настройки.
Определение стандартных настроек. Аналогичное окно при пользовательской настройке.
Книги
Хрусталева Е. Ю. Разработка сложных отчетов
Алгоритм преобразования задачи в реализацию
Дано: есть представление в голове заказчика, как должен выглядеть отчет (таблицы, диаграммы).
Шаг 1. В 1С каждый отчет работает только с одной таблицей данных. Использование нескольких независимых (или почти независимых) таблиц достигается за счет вложенных схем и возможной передачи параметров из основной схемы во вложенную. Здесь начинается искусство, похожее на создание классов в нормальных языках: вариантов много, нужно выбрать более простой с одной стороны и функциональный с другой.
Результат: разделение всех необходимых данных на независимые таблицы. ВАЖНО. Под независимой таблицей данных отчета понимается таблица, получившаяся в результате шага 2, т е это может быть объединение нескольких таблиц базы.
Шаг 2. За счет наборов данных, связей наборов данных, вычисляемых полей, ресурсов и параметров получаем сырую таблицу, но полностью включающую в себя все строки и столбцы. Деталь: есть группировка на уровне запроса (при создании набора данных через запрос) и группировка на уровне настройки отчета. При работе с отчетами, в наборе данных нужно получать сырую таблицу, без группировок/итоговых расчетов.
Результат: неоформленная таблица с необходимыми данными и полями настроек.
Шаг 3. При помощи Настроек используя Макет (один из стандартных или созданный вручную), создается внешнее оформление.
Шаг 4. Сборка всего вместе и наслаждение результатом.
Макеты
Добавление параметра макета в отчёт: Для ячейки макета, в которой будет отображаться поле, в палитре свойств установить свойство «Заполнение» в «Параметр». В качестве значения свойства «Параметр» установить имя параметра макета. Затем в списке параметров макета установить в качестве выражения представление выводимого поля.