Часть IV. Краткий справочник разработчика
Заключительная часть нашей книги содержит набор кратких справочных статей и описаний групп объектов встроенного языка используемых для работы с теми или иными данными базы данных. [529]
Имена обработчиков событий
Используются имена процедур-обработчиков событий, формируемые системой автоматически:
<имя элемента управления> + <название события>
Имена по умолчанию формируются при нажатии "лупы" около события в окне свойств реквизита диалога.
По таким же правилам следует образовывать имена обработчиков самостоятельно.
Именование функций-флагов
Функции, которые предназначены для проверки чего-либо, и возвращают в качестве результата проверки булево значение, следует именовать так, как называется результат проверки, имеющий тип Истина.
Например, если функция должна проверить наличие дублей строк в табличной части документа, то она должна называться "ЕстьДублиСтрок". Или если функция должна проверить принадлежность документа к накладным, то она должна называться "ЭтоНакладная".
Однако, если функция (или процедура) "ЕстьДублиСтрок" и проверяет наличие дублей строк, и выполняет объединение дублирующих строк, при этом не возвращает значения, ее следует именовать "СвернутьДублиСтрок".
Именование переменных-флагов
В процедурах периодически используются переменные, которые содержат в себе некий флаг. Такие переменные следует называть так, как называется истинное значение этого флага.
Например, если нужна переменная, в которой хранится признак наличия ошибок в процедуре, то такая переменная должна называться "ЕстьОшибки". Или если есть признак того, что товар относится к возвратной таре, то такой признак должен называться "ЭтоТара".
Кэш объектов
Система 1С:Предприятие 8.0 использует механизм кэширования данных объектов, считанных из базы данных при использовании объектной техники. Таким образом, для получения реквизитов какого-либо объекта через ссылку, выполняется обращение к кэшу объектов, расположенному в оперативной памяти.
Кэш объектов состоит из двух частей: транзакционного кэша и обычного кэша. В зависимости от того, происходит ли обращение в рамках транзакции или нет, в действие вступает тот или иной кэш:
Все данные, находящиеся в кэше, предназначены только для чтения (ReadOnly), таким образом чтение любых данных, получаемых через ссылку, выполняется только через кэш объектов, а запись – механизмами самих программных объектов.
Концепция оперативного и не оперативного проведения документов
При разработке конфигураций на платформе 1С:Предприятие 8.0 принято использовать концепцию оперативного и неоперативного проведения документов.
Эта концепция подразумевает, что работа пользователей может происходить в двух принципиально разных, по своей сути, режимах.
Оперативное проведение документов пользователями выполняется в режиме "реального времени", т.е. отображает изменения, факты, свершающиеся в настоящее время. Оперативное проведение особенно актуально при многопользовательской работе. Поэтому при оперативном проведении документов следует осуществлять максимум проверок, способных исключить ошибки при вводе данных пользователями. Например, при оперативном проведении следует выполнять контроль остатков на складе списываемой номенклатуры с тем, чтобы исключить одновременную продажу одного товара несколькими продавцами.
Неоперативное проведение документов подразумевает отражение в базе данных фактов, которые свершились в прошлом, или которые точно будут совершены в будущем. Поэтому задача неоперативного проведения документов заключается в том, чтобы просто отразить в информационной базе данные о совершенных операциях.
При неоперативном проведении документов не производится ряд проверок, в частности контроль остатков. Подразумевается, что если в процессе неоперативного проведения документов были допущены ошибки (например, списано такое количество номенклатуры, которого нет на складе), то анализ полученного состояния базы данных является отдельной задачей, не относящейся к неоперативному проведению и выполняющейся отдельно от него.
Таким образом, оперативное проведение служит для того, чтобы в реальном режиме многопользовательской работы определить возможность или невозможность выполнения той или иной операции (и выполнить ее, если возможно), а неоперативное проведение служит для безусловного отражения в базе операций, которые уже были совершены (или точно будут совершены). [541]
Манипулирование данными объектов
Несмотря на большое разнообразие объектов встроенного языка, предназначенных для работы с информационными структурами, создаваемыми на основе объектов конфигурации, лишь некоторые из объектов встроенного языка позволяют изменять данные, хранящиеся в этих информационных структурах. Такие объекты мы назовем объектами манипулирования данными.
Каждый тип объектов манипулирования данными имеет в конфигураторе соответствующий модуль, который называется либо модулем объекта, либо модулем набора записей, в зависимости от принадлежности к тому или иному объекту конфигурации. Для констант этот модуль называется модулем менеджера значений.
Так вот, модуль объекта манипулирования данными будет всегда выполняться при создании объекта манипулирования данными. Кроме этого, он будет всегда выполняться и при интерактивном обращении пользователя к самой структуре манипулирования данными, поскольку такое обращение будет вызывать создание соответствующего объекта манипулирования данными. Например, при открытии формы элемента справочника будет создаваться объект СправочникОбъект.<имя>.
В модуле объекта манипулирования данными, кроме всего прочего, могут быть описаны процедуры с ключевым словом Экспорт, что подразумевает вызов этих процедур как методов соответствующего объекта манипулирования данными. Здесь важно не путать объект манипулирования данными с другими объектами, позволяющими получить доступ к данным этой информационной структуры.
Например, если мы, для объекта конфигурации Справочник "Клиенты" опишем в модуле объекта процедуру:
Процедура Проверка() Экспорт
КонецПроцедуры; [561]
то в дальнейшем сможем вызывать ее как метод объекта СправочникОбъект.Клиенты:
Клиент = Справочники.Клиенты.НайтиПоКоду(1).ПолучитьОбъект();
Клиент.Проверка();
Однако следующий код будет приводить к ошибке, т.к. объект СправочникСсылка.Клиенты не имеет метода "Проверка":
Клиент = Справочники.Клиенты.НайтиПоКоду(1);
Клиент.Проверка();
Во-первых, для констант указаны три объекта манипулирования данными КонстантаМенеджерЗначения.<имя>, КонстантаМенеджер.<имя> и КонстантыНабор. На самом деле манипулирование данными константы осуществляется при помощи объекта КонстантаМенеджерЗначения.<имя>.
Два других объекта – КонстантаМенеджер.<имя> и КонстантыНабор – также позволяют изменять значения констант, хранящиеся в базе данных, однако они, при выполнении своих методов Установить() и Записать() вызывают создание объекта КонстантаМенеджер.<имя>, который и выполняет непосредственное изменение данных.
При выполнении метода Установить() объекта КонстантаМенеджер.<имя>, будет вызван модуль менеджера значения и обработчики событий ПриЗаписи() и ПередЗаписью() для изменяемой константы. При выполнении метода Записать() объекта НаборКонстант, модуль менеджера значения и соответствующие обработчики будут вызваны для каждой константы, входящей в набор.
Во-вторых, для регистра сведений указаны два объекта манипулирования данными. "В чистом виде" манипулирование данными регистра сведений осуществляется при помощи объекта РегистрСведенийНаборЗаписей.<имя>. [562]
Однако существует возможность манипулирования записями регистра сведений и при помощи объекта
РегистрСведенийМенеджерЗаписи.<имя>. Но объект РегистрСведенийМенеджерЗаписи.<имя> работает с данными регистра не напрямую, а через объект РегистрСведенийНаборЗаписей.<имя>. Таким образом, модуль набора записей, а также обработчики событий ПередЗаписью() и ПриЗаписи() набора записей, будут отрабатывать и при манипулировании объектом РегистрСведенийМенеджерЗаписи.<имя>. Однако процедуры и функции, описанные в модуле набора записей с ключевым словом Экспорт, не будут доступны как методы объекта РегистрСведенийМенеджерЗаписи.<имя>. [563]
структура манипулирования данными
объект манипулирования данными
(КонстантаМенеджер.<имя>, КонстантыНабор)
(РегистрСведенийМенеджерЗаписи.<имя>)
Механизм основных форм
У всех прикладных объектов конфигурации существует некоторое количество основных форм. Они служат для отображения данных объекта в том или ином виде. Если разработчик не назначит в качестве основных форм объекта свои собственные, система будет генерировать необходимые формы объекта самостоятельно, в те моменты, когда к ним происходит обращение. Наличие такого механизма позволяет разработчику не тратить время на создание форм для тестирования своей разработки, а воспользоваться тем, что платформа создаст по умолчанию.
Создание этих форм происходит динамически, в процессе работы системы. Форма создается в тот момент, когда к ней происходит обращение. Причем не важно, интерактивное это обращение или программное. Так для констант форма будет создана как при интерактивном выборе в меню Операции
Константы, так и при программном вызове метода ПолучитьФорму() объекта КонстантыМенеджер:Константы.ПолучитьФорму();
Также примечательным фактом является то, что состав основных форм, определенных для объекта конфигурации может не совпадать с перечнем тех форм, которые вообще можно создать для данного объекта, используя конструктор формы.
Например, для большинства регистров в конфигураторе можно задать основную форму списка. Однако если открыть конструктор форм для регистра, вы увидите, что кроме формы списка предлагается создать и форму набора записей регистра, которая отсутствует в перечне основных форм.
Дело в том, что состав основных форм определяется исходя из того, какое представление данных может понадобиться в процессе интерактивной работы пользователя. Для этих представлений разработчик может создать свои формы и указать их в качестве основных, а может использовать те формы, которые система создаст автоматически.
Конструктор форм, напротив, исходит из потребностей разработчика. Если разработчик посчитает нужным использовать для [542] какого-либо регистра вместо обычной формы списка форму набора записей – он сможет это сделать, воспользовавшись конструктором и определив ее в качестве основной формы регистра. Но для логики работы системы это не будет иметь принципиального значения [543]
Немного о конфигурациях
При первом знакомстве с системой 1С:Предприятие может возникнуть естественный вопрос: если у нас есть две конфигурации: одна, которую можно редактировать, и другая, с которой работают пользователи, то почему же тогда основной называется редактируемая конфигурация? Ведь с точки зрения конечного продукта, основной является именно конфигурация, с которой работают пользователи!
Дело в том, что в данном случае название "основная" дано с точки зрения разработчика и это имеет глубокий практический смысл.
В общем случае информационная база 1С:Предприятия хранит три конфигурации: основную конфигурацию, конфигурацию базы данных и несколько конфигураций поставщиков. Кроме этого вне информационной базы может существовать хранилище, в котором находится конфигурация, предназначенная для групповой разработки, и вне информационной базы может существовать некоторое количество файлов конфигураций, в том числе файлы новой поставки.
[535]
Конфигурация поставщика, находящаяся в информационной базе содержит предыдущее состояние поставки. Возможна ситуация, когда конфигурация находится на поддержке одновременно у нескольких поставщиков, каждый из которых поддерживает только свою часть в виде отдельной конфигурации. В этом случае информационная база будет хранить несколько конфигураций поставщиков (состояние предыдущей поставки для каждого поставщика отдельно).
Файлы новой поставки могут существовать в виде файлов конфигураций (полная поставка) и файлов обновлений (поставка обновлений).
Хранилище конфигурации содержит конфигурацию, предназначенную для групповой разработки. Эта конфигурация хранится не в виде единой конфигурации, а в виде отдельных объектов в разрезе версий конфигурации. Таким образом, мы можем получить из хранилища конфигурацию любой версии – для этого она "собирается" из объектов нужной версии.
Теперь представьте, что между всеми этими видами конфигураций существует возможность сравнения и обновления конфигураций. В этом случае очень легко запутаться и название Основная конфигурация как нельзя лучше отражает конечную цель всех изменений. [536]
Объекты, объекты, объекты...
Что такое объект, применительно к 1С? Этот вопрос зачастую ставит в тупик не только начинающих разработчиков, но и людей, имеющих определенный опыт разработки на платформе 1С.
Основная трудность заключается в том, что всегда нужно ясно представлять себе, в каком контексте употребляется этот термин.
Как правило, термин объект употребляется в одном из трех контекстов:
· | конфигурация, |
· | база данных, |
· | встроенный язык, |
Говоря о конфигурации, термином объект конфигурации мы обозначаем некоторую совокупность описания данных и алгоритмов работы с этими данными. Например, в конфигурации может существовать объект справочник "Сотрудники".
На основании каждого объекта конфигурации в базе данных создается информационная структура, в которой будут храниться данные.
Так вот, когда мы говорим о базе данных, термином объект мы обозначаем всего лишь некий элемент такой информационной структуры. Характерной особенностью такого элемента является то, что на него (как на совокупность данных) существует ссылка, которая может являться значением какого либо поля другой информационной структуры.
Например, в базе данных существует справочник "Сотрудники" в котором есть сотрудник Иванов. В этом случае элемент справочника, содержащий информацию о сотруднике Иванов, будет являться объектом базы данных. И если в документе "ПриходнаяНакладная" будет существовать реквизит "ОтветственноеЛицо", то тип значения этого реквизита будет ссылка на объект базы данных, т.е. на элемент справочника, содержащий информацию об Иванове.
Если же мы начинаем говорить о встроенном языке и о том, каким образом средствами встроенного языка работать со справочниками, то [537] термином объект мы обозначаем тип данных, позволяющий получить доступ к данным и обладающий набором свойств и методов.
Существует целый ряд объектов встроенного языка, позволяющих работать со справочниками (СправочникиМенеджер, СправочникМенеджер.<имя>, СправочникСсылка.<имя> и т.д.). Среди них есть один объект, который предоставляет доступ к объекту справочника в базе данных – СправочникОбъект.<имя>.
[538]
Объекты встроенного языка для работы с константами:
*Заливкой выделен объект манипулирования данными
Узнай больше!
Про основные виды объектов встроенного языка можно прочитать в главе "Виды объектов встроенного языка, предназначенные для работы с данными прикладных объектов конфигурации" на странице 551.
КонстантыНабор – предоставляет возможность проведения операций чтения и записи сразу для группы констант, в частном случае – для всех констант. Также используется в форме констант для хранения, записи и считывания констант.
КонстантаМенеджерЗначения<имя> – используется для доступа к константе. Любая запись константы (интерактивно в форме, объекты КонстантыНабор и КонстантаМенеджер.<имя>) создает объект этого типа и производит запись с его помощью, что обеспечивает вызов модуля и обработчиков событий этого объекта. [565]
// Константы
//Пример: Открыть основную форму констант
Форма = Константы.ПолучитьФорму();
Форма.Открыть();
// .<имя константы>
// [<имя константы>]
// Для Каждого ... Из ... Цикл ... КонецЦикла;
//Пример: Прочитать значение константы
Результат = Константы.ПрефиксНумерации.Получить();
Сообщить("Значение константы ПрефиксНумерации = "+Результат);
//Пример: Установить значение константы "ПрефиксНумерации" равным "ЦБ"
Константы["ПрефиксНумерации"].Установить("ЦБ");
Сообщить("Новое значение = "+Константы["ПрефиксНумерации"].Получить());
//Пример: Очистить значения всех констант
Для Каждого ОчереднаяКонстанта Из Константы Цикл
ОчереднаяКонстанта.Установить(Неопределено);
КонецЦикла;
// СоздатьНабор()
//Пример: Установить новые значения нескольких констант
Набор = Константы.СоздатьНабор("Руководитель, Бухгалтер");
Набор.Руководитель = "Николаев Денис Павлович";
Набор.Бухгалтер = "Николаева Людмила Сергеевна";
Набор.Записать(); [566]
Для Каждого ОчереднаяКонстанта Из Константы Цикл
ИмяКонст = ОчереднаяКонстанта.СоздатьМенеджерЗначения().Метаданные().Имя;
ЗначениеКонст = ОчереднаяКонстанта.Получить();
Сообщить("Константа "+ИмяКонст+" = "+ЗначениеКонст);
КонецЦикла; [567]
Объекты встроенного языка для работы с документами:
*Заливкой выделен объект манипулирования данными
Узнай больше!
Про основные виды объектов встроенного языка можно прочитать в главе "Виды объектов встроенного языка, предназначенные для работы с данными прикладных объектов конфигурации" на странице 551. [577]
// Документы
//Пример: вывести все типы ссылок на документы, существующие в конфигурации
Массив = Документы.ТипВсеСсылки().Типы();
Для Каждого ОчереднойТип Из Массив Цикл
Сообщить(ОчереднойТип);
КонецЦикла;
// .<имя документа>
// [<имя документа>]
// Для Каждого ... Из ... Цикл ... КонецЦикла;
//Пример: Открыть форму нового документа ОказаниеУслуги для интерактивного
//заполнения
Форма = Документы["ОказаниеУслуги"].ПолучитьФормуНовогоДокумента();
Форма.Открыть();
//Пример: Открыть формы списка всех документов, существующих в
// конфигурации
Для Каждого ОчереднойДокумент Из Документы Цикл
Форма = ОчереднойДокумент.ПолучитьФормуСписка();
Форма.Открыть();
КонецЦикла; [578]
// НайтиПоНомеру()
// НайтиПоРеквизиту()
// ПустаяСсылка()
//Пример: Проверить, проведен ли документ ПриходнаяНакладная с номером 3
Если Документы.ПриходнаяНакладная.НайтиПоНомеру(3).Проведен Тогда
Сообщить("Документ с номером 3 проведен");
КонецЕсли;
//Пример: Проверить, что во всех документах ПриходнаяНакладная заполнен
//реквизит Склад
ПустаяСсылкаСклада = Справочники.Склады.ПустаяСсылка();
Если Не Документы.ПриходнаяНакладная.НайтиПоРеквизиту("Склад", ПустаяСсылкаСклада).Пустая() Тогда
Сообщить("Есть документы, у которых не заполнен реквизит Склад");
КонецЕсли;
// Выбрать()
//Пример: Выбрать все документы ПриходнаяНакладная за текущий месяц
Выборка = Документы.ПриходнаяНакладная.Выбрать(НачалоМесяца(ТекущаяДата()),КонецМесяца(ТекущаяДата()));
Пока Выборка.Следующий() Цикл
Сообщить(Выборка);
КонецЦикла;
НовыйДокумент = Документы.ПриходнаяНакладная.СоздатьДокумент();
НовыйДокумент.Дата = ТекущаяДата();
НовыйДокумент.Склад = Справочники.Склады.Основной;
//Заполнить табличную часть
НоваяСтрокаТабличнойЧасти = НовыйДокумент.Материалы.Добавить();
НоваяСтрокаТабличнойЧасти.Материал = Справочники.Номенклатура.НайтиПоКоду(6);
НоваяСтрокаТабличнойЧасти.Количество = 10;
НоваяСтрокаТабличнойЧасти.Цена = 22.5;
НоваяСтрокаТабличнойЧасти.Сумма = 225;
НовыйДокумент.Записать(); [579]
Если Не ПроверитьЗаполнениеРеквизитов(ЭтотОбъект.Ссылка) Тогда
Сообщить("Реквизиты документа не заполнены!");
КонецЕсли;
// Скопировать()
НенужныйДокумент = Документы.ОказаниеУслуги.НайтиПоНомеру(13).ПолучитьОбъект();
НенужныйДокумент.УстановитьПометкуУдаления(Истина);
//текущий месяц
СписокНакладных = Новый СписокЗначений;
Выборка = Документы.ПриходнаяНакладная.Выбрать(НачалоМесяца(ТекущаяДата()),КонецМесяца(ТекущаяДата()));
Пока Выборка.Следующий() Цикл
СписокНакладных.Добавить(Выборка.Ссылка);
КонецЦикла; [580]
Выборка = Документы.ПриходнаяНакладная.Выбрать();
Пока Выборка.Следующий() Цикл
Выборка.ПолучитьОбъект().Удалить();
КонецЦикла;
Объекты встроенного языка для работы с перечислениями:
Узнай больше!
Про основные виды объектов встроенного языка можно прочитать в главе "Виды объектов встроенного языка, предназначенные для работы с данными прикладных объектов конфигурации" на странице 551.
Использование объектов:
// Перечисления
//Пример: Открыть форму списка перечисления
Форма = Перечисления.ВидыНоменклатуры.ПолучитьФормуСписка();
Форма.Открыть();[584]
// .<имя перечисления>
// [<имя перечисления >]
// Для Каждого ... Из ... Цикл ... КонецЦикла;
//Пример: Открыть форму выбора перечисления
Форма = Перечисления.ВидыНоменклатуры.ПолучитьФормуВыбора();
Форма.Открыть();
// .<имя значения перечисления>
// [<имя значения перечисления>]
// [<индекс элемента коллекции>]
// Для Каждого... Из ... Цикл ... КонецЦикла;
// ПустаяСсылка()
//Пример: Получить пустую ссылку на значение перечисления
...
ПустаяСсылкаПеречисления = Перечисления.ВидыНоменклатуры.ПустаяСсылка();
Если ТекущаяНоменклатура.ВидНоменклатуры = ПустаяСсылкаПеречисления Тогда
//предложить заполнение вида номенклатуры
...
КонецЕсли;
...[585]
Объекты встроенного языка для работы с планами видов характеристик
*Заливкой выделен объект манипулирования данными
Узнай больше!
Про основные виды объектов встроенного языка можно прочитать в главе "Виды объектов встроенного языка, предназначенные для работы с данными прикладных объектов конфигурации" на странице 551.[586]
Свойства и методы взаимодействия перечисленных объектов в большинстве своем аналогичны свойствам и методам объектов, предназначенных для работы со справочниками (см. раздел "Объекты встроенного языка для работы со справочниками" на странице 570).
*Заливкой выделен объект манипулирования данными
Узнай больше!
Про основные виды объектов встроенного языка можно прочитать в главе "Виды объектов встроенного языка, предназначенные для работы с данными прикладных объектов конфигурации" на странице 551. [588]
ПланСчетовВидыСубконто.<имя>. Используется для доступа к методам специальной табличной части счета ВидыСубконто в целом.
ПланСчетовВидыСубконтоСтрока.<имя>. Строка специальной табличной части счета ВидыСубконто.
Свойства и методы взаимодействия перечисленных объектов в большинстве своем аналогичны свойствам и методам объектов, предназначенных для работы со справочниками (см. раздел "Объекты встроенного языка для работы со справочниками" на странице 570).
*Заливкой выделен объект манипулирования данными
Узнай больше!
Про основные виды объектов встроенного языка можно прочитать в главе "Виды объектов встроенного языка, предназначенные для работы с данными прикладных объектов конфигурации" на странице 551. [609]
ЗаписьСообщенияОбмена – Объект предназначен для организации записи сообщения обмена данными.
ЧтениеСообщенияОбмена – Объект предназначен для приема сообщений обмена данными. При начале чтения он осуществляет проверку правильности задания заголовка сообщения, и отвергает неправильные сообщения. При завершении чтения данный объект модифицирует значение реквизита "НомерПринятого" соответствующего узла плана обмена в соответствии с номером принятого сообщения.
Свойства и методы взаимодействия перечисленных объектов в большинстве своем аналогичны свойствам и методам объектов, предназначенных для работы со справочниками (см. раздел "Объекты встроенного языка для работы со справочниками" на странице 570).
Объекты встроенного языка для работы с планом видов расчета
*Заливкой выделен объект манипулирования данными [590]
Узнай больше!
Про основные виды объектов встроенного языка можно прочитать в главе "Виды объектов встроенного языка, предназначенные для работы с данными прикладных объектов конфигурации" на странице 551.
ВытесняющиеВидыРасчета.<имя>. Предопределенная табличная часть вида расчета – список вытесняющих видов расчета. Такая табличная часть определена только для планов видов расчета с признаком ИспользуетПериодДействия. Имеет единственную колонку – ВидРасчета типа ПланВидовРасчетаСсылка.<имя>.
ВытесняющиеВидыРасчетаСтрока.<имя>. Строка предопределенной таблицы вытесняющих видов расчета.
ВедущиеВидыРасчета.<имя>. Предопределенная табличная часть вида расчета – список ведущих видов расчета. Имеет единственную колонку – ВидРасчета типа ПланВидовРасчетаСсылка.<имя>.
ВедущиеВидыРасчетаСтрока.<имя>. Строка предопределенной таблицы ведущих видов расчета.
БазовыеВидыРасчета.<имя>. Предопределенная табличная часть вида расчета – список ведущих видов расчета. Такая табличная часть (свойство БазовыеВидыРасчета) определена только для планов видов расчета со свойством ЗависимостьОтБазы не равным значению "Не зависит". Имеет единственную колонку – ВидРасчета типа ПланВидовРасчетаСсылка.<имя>.
БазовыеВидыРасчетаСтрока.<имя>. Строка предопределенной таблицы базовых видов расчета.
Свойства и методы взаимодействия перечисленных объектов в большинстве своем аналогичны свойствам и методам объектов, предназначенных для работы со справочниками (см. раздел "Объекты встроенного языка для работы со справочниками" на странице 570). [591]
Объекты встроенного языка для работы с регистрами сведений
*Заливкой выделен объект манипулирования данными
Узнай больше!
Про основные виды объектов встроенного языка можно прочитать в главе "Виды объектов встроенного языка, предназначенные для работы с данными прикладных объектов конфигурации" на странице 551.
РегистрСведенийМенеджерЗаписи.<имя>. Позволяет читать, записывать и удалять отдельную запись регистра сведений. Используется только для регистров сведений, не изменяемых [593] регистраторами, т.е. для которых в конфигураторе установлен режим записи "Независимый".
РегистрСведенийЗапись.<имя>. Предоставляет доступ к записи регистра сведений. Объект не создается непосредственно, а предоставляется другими объектами, связанными с регистром сведений. Например, данный объект представляет записи регистра в наборе записей.
РегистрСведенийКлючЗаписи.<имя>. Представляет собой набор значений, однозначно идентифицирующих запись регистра. Объект используется в тех случаях, когда необходимо сослаться на определенную запись. Например, он выступает в качестве значения свойства "ТекущаяСтрока" табличного поля, отображающего список записей регистра.
Использование объектов:
// РегистрыСведений
//Прнмер: Получить текущую цену из периодического регистра сведений Цены
Элемент = Справочники.Номенклатура.НайтиПоКоду(4);
Отбор = Новый Структура("Номенклатура",Элемент);
ЗначенияРесурсов = РегистрыСведений.Цены.ПолучитьПоследнее(ТекущаяДата(), Отбор);
// .<имя регистра сведений>
// [<имя регистра сведений>]
// Для Каждого ... Из ... Цикл ... КонецЦикла;
//Пример: Открыть форму списка регистра сведений Цены
ИмяРегистра= "Цены";
Форма = РегистрыСведений[ИмяРегистра].ПолучитьФормуСписка();
Форма.Открыть();[594]
// СоздатьКлючЗаписи()
//Пример: Активизировать требуемую строку списка регистра сведений
СтруктураКлючевыхПолей = Новый Структура;
СтруктураКлючевыхПолей.Вставить("Период", Дата("20040331000000"));
СтруктураКлючевыхПолей.Вставить("Номенклатура", Справочники.Номенклатура.НайтиПоКоду("0000006"));
ЭлементыФормы.ТабличноеПоле1.ТекущаяСтрока = РегистрыСведений.Цены.СоздатьКлючЗаписи(СтруктураКлючевыхПолей);
//дату и время
Набор = РегистрыСведений.Цены.СоздатьНаборЗаписей();
Набор.Отбор.Период.Установить(ЗаданнаяДата, Истина);
Набор.Прочитать();
Для Каждого ОчереднаяЗапись Из Набор Цикл
Сообщить("Номенклатура = "+ОчереднаяЗапись.Номенклатура+", цена = "+ОчереднаяЗапись.Цена);
КонецЦикла;
Запись = РегистрыСведений.Цены.СоздатьМенеджерЗаписи();
Запись.Период = ТекущаяДата();
Запись.Номенклатура = Справочники.Номенклатура.НайтиПоКоду("0000005");
Запись.Цена = 568;
Запись.Записать(); [595]
// Для ... По ... Цикл ... КонецЦикла;
//дату и время
Набор = РегистрыСведений.Цены.СоздатьНаборЗаписей();
Набор.Отбор.Период.Установить(ЗаданнаяДата, Истина);
Набор.Прочитать();
Для сч_к = 0 По Набор.Количество() - 1 Цикл
Сообщить("Номенклатура = "+Набор[сч_к].Номенклатура+", цена = "+Набор[сч_к].Цена);
КонецЦикла;
Выборка = РегистрыСведений.Цены.Выбрать(НачалоМесяца(ТекущаяДата()), КонецМесяца(ТекущаяДата()));
Пока Выборка.Следующий() цикл
Выборка.ПолучитьМенеджерЗаписи().Удалить();
КонецЦикла;
// ВыбратьПоРегистратору()
Отбор = Новый Структура("Номенклатура", Справочники.Номенклатура.НайтиПоКоду("0000005"));
Выборка = РегистрыСведений.Цены.Выбрать(НачалоГода(ТекущаяДата()),ТекущаяДата(),Отбор);
Пока Выборка.Следующий() Цикл
Сообщить("Дата = "+Выборка.Период+ ", цена = "+Выборка.Цена);
КонецЦикла; [596]
Объекты встроенного языка для работы с регистрами накопления
*Заливкой выделен объект манипулирования данными
Узнай больше!
Про основные виды объектов встроенного языка можно прочитать в главе "Виды объектов встроенного языка, предназначенные для работы с данными прикладных объектов конфигурации" на странице 551.
РегистрНакопленияЗапись.<имя>. Используется для доступа к записи регистра накопления. Объект не создается непосредственно, а предоставляется другими объектами, отвечающими за регистр накопления. Например, данный объект представляет записи регистра в наборе записей.
РегистрНакопленияКлючЗаписи.<имя>. Представляет собой набор значений, однозначно идентифицирующих запись регистра. [599] Объект используется в тех случаях, когда необходимо сослаться на определенную запись. Например, он выступает в качестве значения свойства "ТекущаяСтрока" табличного поля, отображающего список записей регистра.
Использование объектов:
// РегистрыНакопления
//Пример: Открыть форму списка регистра ОстаткиМатериалов
Форма = РегистрыНакопления.ОстаткиМатериалов.ПолучитьФормуСписка();
Форма.Открыть();
// .<имя регистра накопления>
// [<имя регистра накопления >]
// Для Каждого ... Из ... Цикл... КонецЦикла;
//Пример: Рассчитать итоги регистра ОстаткиМатериалов на указанную дату
УказаннаяДата = ЗаданнаяДата;
ИмяРегистра = "ОстаткиМатериалов";
РегистрыНакопления[ИмяРегистра].УстановитьПериодРассчитанныхИтогов(УказаннаяДата);
// СоздатьКлючЗапнси()
//Пример: Активизировать требуемую строку списка регистра накопления
СтруктураКлючевыхПолей = Новый Структура;
СтруктураКлючевыхПолей.Вставить("Регистратор", Документы.ПриходнаяНакладная.НайтиПоНомеру("0000002"));
СтруктураКлючевыхПолей.Вставить("НомерСтроки",2);
ЭлементыФормы.ТабличноеПоле1.ТекущаяСтрока = РегистрыНакопления.ОстаткиМатериалов.СоздатьКлючЗаписи(СтруктураКлючевыхПолей); [600]
НужныйДокумент = Документы.ПриходнаяНакладная.НайтиПоНомеру(4);
Движения = РегистрыНакопления.ОстаткиМатериалов.СоздатьНаборЗаписей();
Движения.Отбор.Регистратор.Значение = НужныйДокумент;
Движения.Прочитать();
// ВыбратьПоРегистратору()
Выборка = РегистрыНакопления.ОстаткиМатериалов.Выбрать(НачалоМесяца(ТекущаяДата()), КонецМесяца(ТекущаяДата()));
Пока Выборка.Следующий() Цикл
Сообщить("Регистратор: " + Выборка.Регистратор + " Материал: " + Выборка.Материал + " Кол-во: " + Выборка.Количество);
КонецЦикла;
// Для Каждого ... Из ... Цикл ... КонецЦикла;
НужныйДокумент = Документы.ПриходнаяНакладная.НайтиПоНомеру(4);
Движения = РегистрыНакопления.ОстаткиМатериалов.СоздатьНаборЗаписей();
Движения.Отбор.Регистратор.Значение = НужныйДокумент;
Движения.Прочитать();
Для Каждого ОчередноеДвижение Из Движения Цикл
//алгоритм обработки движений
КонецЦикла; [601]
Объекты встроенного языка для работы с регистрами бухгалтерии
*Заливкой выделен объект манипулирования данными
Узнай больше!
Про основные виды объектов встроенного языка можно прочитать в главе "Виды объектов встроенного языка, предназначенные для работы с данными прикладных объектов конфигурации" на странице 551.
РегистрБухгалтерииЗапись. Используется для доступа к записи регистра бухгалтерии. Объект не создается непосредственно, а предоставляется другими объектами, отвечающими за регистр [603] бухгалтерии. Например, данный объект представляет записи регистра в наборе записей.
РегистрБухгалтерииСубконто. Коллекция значений субконто записи регистра бухгалтерии. Установка и получение значения конкретного субконто осуществляется через оператор [], в качестве параметра которому передается вид субконто или через имя предопределенного субконто.
РегистрБухгалтерииКлючЗаписи. Набор значений, однозначно идентифицирующий запись регистра. Объект используется в тех случаях, когда необходимо сослаться на определенную запись. Например, он выступает в качестве значения свойства ТекущаяСтрока табличного поля, отображающего список записей регистра.
Свойства и методы взаимодействия перечисленных объектов в большинстве своем аналогичны свойствам и методам объектов, предназначенных для работы с регистрами накопления (см. раздел "Регистры накопления" на странице 599). [604]
*Заливкой выделены объекты манипулирования данными [606]
Узнай больше!
Про основные виды объектов встроенного языка можно прочитать в главе "Виды объектов встроенного языка, предназначенные для работы с данными прикладных объектов конфигурации" на странице 551.
РегистрРасчетаЗапись.<имя>. Используется для доступа к записи регистра расчета. Объект не создается непосредственно, а предоставляется другими объектами, отвечающими за регистр Расчета. Например, данный объект представляет записи регистра в наборе записей.
РегистрРасчетаКлючЗаписи.<имя>. Представляет собой набор значений, однозначно идентифицирующих запись регистра. Объект используется в тех случаях, когда необходимо сослаться на определенную запись. Например, он выступает в качестве значения свойства ТекущаяСтрока табличного поля, отображающего список записей регистра.
РегистрРасчетаПерерасчеты.<имя>. Менеджер всех менеджеров перерасчетов регистра расчетов.
ПерерасчетМенеджер.<имя>. Менеджер перерасчета служит для получения набора записей перерасчета.
ПерерасчетНаборЗаписей.<имя>. Набор записей перерасчета.
ПерерасчетЗапись.<имя>. Объект используется для доступа к записи перерасчета.
ФактическийПериодДействия. Массив значений типа ЭлементФактическогоПериодаДействия.
ЭлементФактическогоПериодаДействия. Элемент фактического периода действия.
Свойства и методы взаимодействия перечисленных объектов в большинстве своем аналогичны свойствам и методам объектов, предназначенных для работы с регистрами накопления (см. раздел "Регистры накопления" на странице 599). [607]
Объекты встроенного языка для работы со справочниками
*Заливкой выделен объект манипулирования данными
Узнай больше!
Про основные виды объектов встроенного языка можно прочитать в главе "Виды объектов встроенного языка, предназначенные для работы с данными прикладных объектов конфигурации" на странице 551. [570]
// Справочники
//Пример: Вывести все типы ссылок на элементы справочников, существующие
//в конфигурации
Массив = Справочники.ТипВсеСсылки().Типы();
Для Каждого ОчереднойТип из Массив Цикл
Сообщить(ОчереднойТип);
КонецЦикла;
// .<имя справочника>
// [<имя справочника>]
// Для Каждого ... Из ... Цикл ... КонецЦикла;
//Пример: Создать новую группу справочника Номенклатура
НоваяГруппа = Справочники.Номенклатура.СоздатьГруппу();
НоваяГруппа.Наименование = "Моя новая группа";
НоваяГруппа.Записать();
//Пример: Открыть форму выбора справочника Номенклатура
Форма = Справочники["Номенклатура"].ПолучитьФормуВыбора();
Форма.Открыть(); [571]
// НайтиПоКоду()
// НайтиПоНаименованию()
// НайтиПоРеквизиту()
// ПустаяСсылка()
// ПолучитьСсылку()
// .<имя предопределенного элемента справочника>
//Пример: Проверить, помечен ли на удаление элемент справочника Номенклатура
//c кодом 13
Если Справочники.Номенклатура.НайтиПоКоду(13).ПометкаУдаления Тогда
Сообщить("Элемент с кодом 13 помечен на удаление");
КонецЕсли;
//Пример: Является ли элемент справочника Номенклатура с наименованием
//"Услуги" группой
Если Справочники.Номенклатура.НайтиПоНаименованию("Услуги", Истина).ЭтоГруппа Тогда
Сообщить("Элемент Услуги является группой");
КонецЕсли;
//Пример: Проверить, что для всех элементов задан вид номенклатуры
ПустаяСсылкаПеречисления = Перечисления.ВидыНоменклатуры.ПустаяСсылка();
Если Не Справочники.Номенклатура.НайтиПоРеквизиту("ВидНоменклатуры", ПустаяСсылкаПеречисления).Пустая() Тогда
Сообщить(" Есть элементы для которых не задан вид номенклатуры");
КонецЕсли;
//Пример: Передать пустую ссылку в параметр метода
Выборка = Справочники.Номенклатура.Выбрать(Справочники.Номенклатура.ПустаяСсылка()); [572]
// ВыбратьИерархически()
Выборка = Справочники.Номенклатура.Выбрать(Справочники.Номенклатура.ПустаяСсылка());
Пока Выборка.Следующий() Цикл
Если Не Выборка.ЭтоГруппа Тогда
Сообщить(Выборка);
КонецЕсли;
КонецЦикла;
//Пример: Удалить все элементы иерархического справочника
Выборка = Справочники.Номенклатура.ВыбратьИерархически();
Пока Выборка.Следующий() Цикл
Выборка.ПолучитьОбъект().Удалить();
КонецЦикла;
// СоздатьЭлемент()
НовыйЭлемент = Справочники.Сотрудники.СоздатьЭлемент();
НовыйЭлемент.Наименование = "Смирнов Андрей Анатольевич";
//Заполнить табличную часть
НоваяСтрокаТабличнойЧасти = НовыйЭлемент.ТрудоваяДеятельность.Добавить();
НоваяСтрокаТабличнойЧасти.Организация = "OOO НТЦ";
НоваяСтрокаТабличнойЧасти.НачалоРаботы = Дата(2003,05,01);
НоваяСтрокаТабличнойЧасти.ОкончаниеРаботы = Дата(2003,12,31);
НоваяСтрокаТабличнойЧасти.Должность = "Программист";
НовыйЭлемент.Записать(); [573]
// Родитель
// Ссылка
//установлено соответствующее свойство "ИзмененияЗапрещены"
//в модуле формы элемента справочника
Процедура ПередЗаписью(Отказ)
Если Владелец.ИзмененияЗапрещены Тогда
Отказ = Истина;
КонецЕсли;
КонецПроцедуры
// Скопировать()
Элемент = Справочники.Номенклатура.НайтиПоКоду(10).ПолучитьОбъект();
Элемент.Наименование = "Мое новое наименование";
Элемент.Записать();
//Пример: Заполнить справочник тестовыми данными
Элемент = Справочники.Номенклатура.СоздатьЭлемент();
Элемент.Наименование = "Тестовый элемент";
Элемент.Записать();
Для сч_к = 1 по 1000 Цикл
НовыйЭлемент = Элемент.Скопировать();
НовыйЭлемент.Записать();
КонецЦикла; [574]
//элементами из указанной группы справочника Номенклатура
Выборка = Справочники.Номенклатура.ВыбратьИерархически(ПолеВвода1);
Пока Выборка.Следующий() Цикл
СсылкаНаНоменклатуру = Выборка.Ссылка;
Если СсылкаНаНоменклатуру.ЭтоГруппа Тогда
Продолжить;
КонецЕсли;
НоваяСтрока = Материалы.Добавить();
НоваяСтрока.Материал = СсылкаНаНоменклатуру;
КонецЦикла;
Выборка = Справочники.Клиенты.Выбрать();
Пока Выборка.Следующий() Цикл
Выборка.ПолучитьОбъект().УстановитьПометкуУдаления(Истина);
КонецЦикла; [575]
Обработчики событий
При работе с событиями в платформе 1С:Предприятие 8.0, следует различать два типа событий: события, связанные с формой и элементами управления, расположенными в форме, и все остальные события.
Разница заключается в том, что обработчики событий, связанных с формой и элементами управления, расположенными в форме назначаемые, а обработчики всех остальных событий фиксированные.
Фиксированный обработчик события должен иметь имя, совпадающие с именем события – только в этом случае он будет вызываться при возникновении соответствующего события.
Назначаемый обработчик может иметь произвольное имя, и если имя процедуры совпадает с именем события формы или элемента управления – этого совсем не достаточно для того, чтобы процедура вызывалась для обработки события с таким именем. Требуется явное назначение этой процедуры обработчиком этого события. Таким образом любая процедура, расположенная в модуле формы может быть назначена обработчиком любого события (или сразу нескольких событий) формы или элемента управления, расположенного в форме. Имя обработчика в этом случае не имеет значения, важно лишь то, что он назначен обрабатывать какое-либо событие.
Назначение обработчика может выполняться интерактивно, при работе с формой в конфигураторе, или программно, используя методы формы и элементов управления – УстановитьДействие(). [546]
Общие требования к имени объекта конфигурации
Имя объекта надо стремиться строить на основе синонима объекта так, как это делает система автоматически: пробелы и пр. недопустимые символы удаляются, первые буквы слов делаются заглавными. Сокращения слов (относительно синонима) допускаются только в крайних случаях, при этом необходимо, чтобы по сокращению можно было восстановить слово обратно. В случае длинных синонимов последние слова могут быть опущены, ели это не искажает смысла.
Для реквизитов объектов допускается переставлять слова из синонима местами, например: синоним "Полное наименование", имя "НаименованиеПолное".
Для ведущих объектов подобное не допускается.
Общие требования к комментарию объекта конфигурации
Комментарий задается только в тех случаях, когда необходимы какие-либо пояснения. Комментарий начинается с большой буквы, точки ставятся только после сокращений. Если в синониме использовано сокращение, в комментарии необходимо его расшифровать, например: "Общероссийский классификатор единиц измерения".
Для реквизитов объектов в комментариях в необходимых случаях должно содержаться уточнение, например: "Сумма со всеми налогами". [534]
Общие требования к синониму объекта конфигурации
Синоним объекта должен быть определен так, чтобы осмысленно описывать объект. Сокращения допускаются только общепринятые, например, "ОКЕИ", "ИНН". Следует избегать излишне длинных синонимов, но и укорачивать их с потерей смысла тоже плохо. Синоним начинается с большой буквы, точки ставятся только после сокращений.
Для ведущих объектов метаданных необходимо стремиться к тому, чтобы название объекта в меню, подпись в диалоговых формах совпадали с синонимом или, как минимум, начинались с него.
Для реквизитов объектов подписи в диалогах могут отличаться "в силу обстоятельств" – синоним надо подбирать так, чтобы он осмысленно описывал реквизит в возможных универсальных формах.
Для форм синоним должен начинаться со слов, генерируемых конструктором при создании формы ("Форма списка...", "Форма элемента..." и т. д.), далее, в случае наличия нескольких форм одного [533] назначения, обязательно должно следовать уточнение, например "Форма элемента полная", "Форма элемента упрощенная".
Для макетов унифицированных форм синоним должен состоять из названия формы, например: "ТОРГ-12".
Обычный кэш
Если при обращении к обычному кэшу требуемых данных в нем нет, то выполняется чтение данных объекта из базы данных и сохранение их в кэше. Уникальным идентификатором для кэша, в данном случае, будет являться ссылка на объект базы данных. Поэтому данные каждого считанного [554] объекта могут существовать в кэше в одном из двух видов: либо все данные объекта, либо представление объекта.
Таким образом, если мы обратимся к кэшу для получения представления объекта, и в кэше есть информация для нашей ссылки, данные будут взяты из кэша (если в кэше весь объект, нужное представление будет получено из данных объекта). Если в кэше нет информации для нашей ссылки – из базы данных в кэш будут считаны только поля, необходимые для формирования представления объекта.
Если мы обратимся к кэшу для получения реквизита объекта, и в кэше есть информация для нашей ссылки, дальнейшие действия будут зависеть от того, что находится в кэше. Если в кэше весь объект – значение реквизита будет получено из кэша. Если в кэше представление объекта – оно будет удалено из кэша и в кэш будут считаны все данные объекта. Если же при получении реквизита объекта в кэше нет информации для нашей ссылки – из базы данных будут считаны все поля объекта.
Считанные данные будут находиться в кэше до тех пор, пока не наступит одно из трех событий:
· | считанные данные будут вытеснены из кэша другими считанными данными других объектов (переполнение кэша), |
· | при очередном обращении к кэшу окажется, что считанные данные были изменены в базе данных, |
· | закончится интервал времени в 20 минут, |
· | данные будут изменены в базе данных. |
Все считанные данные помещаются в последовательную очередь и, поскольку объем кэша ограничен, наиболее старые данные будут вытесняться из кэша последними считанными данными.
При повторном обращении к кэшу за данными уже считанного объекта будет анализироваться интервал времени, прошедший с момента появления данных в кэше.
Если обращение происходит в пределах 20 секунд после поступления данных в кэш, данные считаются верными (валидными). Если интервал превысил 20 секунд, будет выполняться проверка на то, что версия данных, хранящихся в кэше, соответствует версии данных, находящихся в базе данных. В случае если окажется, что версии данных не совпадают (т.е. произошло изменение данных в базе данных), данные, находящиеся в кэше будут удалены из него и [555] выполнено повторное считывание данных из базы данных. Начиная с этого момента начнется отсчет следующего 20-ти секундного интервала валидности этих данных.
Кроме всех вышеперечисленных событий, считанные данные будут удалены из кэша по истечении 20 минут после их последнего считывания из базы данных.
Таким образом при последовательном выполнении двух операторов (где "Номенклатура" – это ссылка на объект справочника):
В = Номенклатура.ВидНоменклатуры;
Окно редактирования объекта конфигурации и палитра свойств
На первый взгляд окно редактирования объекта и палитра свойств дублируют друг друга. В самом деле, в палитре свойств отображены все свойства объекта конфигурации. Зачем было создавать еще и окно редактирования объекта? И если существует окно редактирования объекта, то зачем тогда палитра свойств, которая содержит все то же самое, только в другом виде?
Окно редактирования объекта конфигурации предназначено в первую очередь для быстрого создания новых объектов. Быстрое создание подразумевает ввод исчерпывающей информации об объекте. Значит нужно очень хорошо знать структуру объекта, а на это требуется время... Выходит, что быстро создать объект не получится? Получится! Окно редактирования объекта имеет в своей основе механизм "мастеров": разработчику в нужной последовательности предлагается ввести необходимые данные. Последовательность ввода данных разработана таким образом, чтобы предыдущие данные могли служить основой для ввода последующих данных. Движение управляется кнопками "Далее" и "Назад". На каждом шаге предлагается ввести группу логически связанных между собой данных.
Но, предположим, что вы уже освоились со структурой объектов или вам просто нужно изменить несколько свойств объекта. Чтобы при этом не нужно было опять "прокручивать" все с самого начала, окно редактирования объекта содержит закладки, которые позволяют вам перейти непосредственно к тому шагу, на котором вводятся интересующие вас данные.
Таким образом окно редактирования объекта помогает быстро создать незнакомый объект конфигурации и в то же время обеспечивает удобный доступ к нужным свойствам при редактировании существующих объектов.
Что же касается палитры свойств, то она предоставляет одну абсолютно незаменимую возможность. Дело в том, что она не привязана по своей структуре к какому-то конкретному виду объектов конфигурации, просто ее содержимое меняется в зависимости от того, какой объект является текущим. За счет этого она может [544] "запоминать", какое свойство объекта в ней выбрано, и при переходе в дереве к другому объекту, она будет подсвечивать "у себя" все то же свойство, но уже другого объекта.
Такая способность палитры свойств абсолютно незаменима, когда, например, среди трех десятков справочников конфигурации вам нужно быстро найти те, которые подчинены какому-нибудь другому справочнику. В этом случае вы выбираете мышью в палитре свойств свойство "Владелец" любого справочника, затем переходите в дерево объектов конфигурации и просто пробегаете его при помощи стрелок или . [545]
Получение представлений ссылочных объектов
При использовании объекта вида Ссылка в элементах управления, для отображения его на экране всегда используется представление объекта (например, элемент справочника может иметь представление в виде наименования или в виде кода). Поскольку объект вида Ссылка содержит только внутренний идентификатор, выполняется обращение к кэшу объектов за получением представления ссылочного объекта. Если в кэше есть валидное представление – берется оно. Если в кэше есть валидные данные объекта – представление получается из них.
В остальных случаях выполняется чтение в кэш полей объекта, необходимых для формирования представления.
Аналогичный механизм используется при вызове функции:
А = Строка(СсылкаНаЭлементСправочникаНоменклатура);
а также при неявном преобразовании ссылочной переменной к типу Строка.
Теперь, если вспомнить нашу работу с конструктором выходной формы, лишний раз становится понятно, почему конструктор, при выборе ссылочного поля, всегда добавляет к списку выбранных полей представление этого поля. Именно для того, чтобы не выводить в ячейку табличного поля ссылку и не вызывать тем самым преобразования ссылочной переменной к типу Строка со всеми вытекающими отсюда действиями. [558]
Понятие момента времени
Для определения положения документа на оси времени используется реквизит документа "Дата". Дата содержит время с точностью до секунды. Это позволяет контролировать последовательность записи документов. Однако при большом объеме создаваемых документов вероятна ситуация, когда несколько документов будут иметь одинаковое значение даты (т.е. будут созданы в течение одной секунды). Как в этом случае определить последовательность созданных документов?
Для обработки подобных ситуаций было введено понятие момент времени. Момент времени представляет собой совокупность даты, времени и ссылки на объект базы данных. Момент времени позволяет однозначно идентифицировать любой объект ссылочного типа базы данных на оси событий, но имеет смысл, в основном, только для документов. Кроме того, момент времени позволяет идентифицировать и не объектные данные, например, записи регистров, подчиненных регистратору.
Понятие момента времени реализовано во встроенном языке при помощи универсального объекта МоментВремени. Этот объект имеет свойства "Дата" и "Ссылка", которые позволяют получить "составляющие" момента времени, и один метод – Сравнить(), при помощи которого возможно сравнение двух моментов времени между собой. Кроме этого объект МоментВремени имеет конструктор и может быть создан в явном виде для любого объекта базы данных ссылочного типа.
Для нескольких документов, имеющих одинаковую дату и время, последовательность их на оси событий определяется системой исходя из ссылок на эти документы, может не совпадать с последовательностью создания документов, и не доступна для изменения пользователем. [540]
Последовательность событий при записи из формы записи регистра сведений
Замечание. Работа с формой записи регистра сведений осуществляется при помощи объекта РегистрСведенийМенеджерЗаписи.<имя>, который, в свою [597] очередь, использует объект РегистрСведенийНаборЗаписей.<имя>.
Особенности внутренней реализации объекта РегистрСведенийМенеджерЗаписи.<имя> таковы, что в случае записи существующей записи регистра сведений, обработчики события ПередЗаписью() и ПриЗаписи() модуля набора записей будут вызваны дважды: сначала для "старого" набора записей (с количеством записей 0) и затем для "нового" набора записей (с количеством записей 1).
Последовательность событий при записи констант из формы
Замечание. Работа с формой констант осуществляется при помощи объекта КонстантыНабор, который, в свою очередь, использует объект КонстантаМенеджерЗначения.<имя>. [568]
Особенности внутренней реализации объекта КонстантыНабор таковы, что при записи набора констант, обработчики события ПередЗаписью() и ПриЗаписи() модуля менеджера значения константы будут вызваны для каждой константы, входящей в записываемый набор. [569]
Правила образования имен элементов управления
Имена надписей образуются по следующим правилам:
· | если надпись относится к элементу управления, имя составляет как "Надпись"+ ИмяЭлементаУправления; |
· | в остальных случаях им составляется как "Надпись"+ИмяНадписи. |
Для имен рамок используется префикс "Рамка". Для командной панели формы используется префикс "КоманднаяПанель". [532]
Для имен командных панелей табличных частей формы используется префикс "КоманднаяПанель"+ИмяТабличнойЧасти, например, "КоманднаяПанельСпецификация".
Элементы управления, связанные с данными, называются так же, как данные.
Правила образования имен переменных
Имена переменных (параметров) следует образовывать от терминов предметной области. При именовании переменных следует использовать только термины, используемые в документации к 1С:Предприятию 8.0 или в методических материалах фирмы "1С" по 1С:Предприятию 8.0.
Из имени переменной должно быть понятно ее назначение. Имена следует образовывать путем "склеивания" слов – удаления пробелов между словами. Каждое отдельное слово в "склеенном" имени пишется с прописной буквы. Предлоги и местоимения из одной буквы также пишутся прописными буквами.
Например:
работа с каталогом – РаботаСКаталогом
количество пачек в коробке – КоличествоПачекВКоробке
Имена переменных не следует начинать с подчеркивания.
Имена переменных ни в коем случае не должны состоять из одного символа. Использование коротких имен переменных допускается только для счетчиков циклов. [530]
Правила образования имен процедур (функций)
Имена процедур в общем случае, следует образовывать от глаголов неопределенного вида, например:
правильно
ПроверитьДублиСтрок(),
неправильно
ПроверкаДублейСтрок();
правильно
ЗагрузитьКонтрагента(),
неправильно
ЗагрузкаКонтрагента().
Имена процедур и функции должны давать представление о характере выполняемых процедурой (функцией) действий.
Примеры хороших имен:
ПроверитьДублиСтрок(), ПодобратьВидРасчета(), ПолучитьИнформациюОПроводке()
Примеры плохих имен:
OK(), Есть(), ЕщеФлажки(), НамПодходит(). [531]
События, связанные с формой
События, обрабатываемые формой, довольно разнообразны и на них стоит остановиться отдельно.
Во-первых, для формы доступна обработка событий, связанных с изменением данных как самой формы, так и подчиненных форм. Поскольку данные формы могут быть самыми различными, определена только категория этих событий, но сами события определяются путем программного назначения обработчика конкретного события. Для этого используется метод объекта Форма – ПодключитьОбработчикИзмененияДанных() (есть и обратный метод – ОтключитьОбработчикИзмененияДанных()). В параметрах этого метода передается имя обработчика данных, а также путь к данным, изменение которых будет отлеживаться этим обработчиком.
Узнай больше!
В случае, когда в форме объекта редактируются дополнительные, логически связанные данные, существует два способа для отслеживания изменения объекта и синхронизации этих данных:
1. | Для синхронизации данных, которые изменяются и записываются синхронно с объектом, нужно использовать событие расширения формы объекта – "ПриИзмененииДанных". |
Примером таких данных могут служить наборы записей регистров у документа, или картинка у справочника.
2. | Для синхронизации данных, которые редактируются и записываются отдельно от самого объекта, нужно использовать обработчик события изменения данных назначенный на изменения ссылки объекта. |
Например, для формы справочника валют, в котором редактируется список курсов валюты, он может выглядеть следующим образом:
ПодключитьОбработчикИзмененияДанных( "СправочнжОбъект.Ссылка", "ПриИзмененииСсылки", Ложь); [547]
Сам же обработчик "ПриИзмененииСсылки()" будет выглядеть следующим образом:
Процедура ПриИзмененииСсылки(Путь)
СписокКурсов.Отбор.Валюта.Установить(Ссылка);
КонецПроцедуры
Также для объекта Форма существует возможность указать обработчик ожидания, который будет вызываться в период ожидания системы каждый раз по истечению указанного интервала времени. Для этого используется метод ПодключитьОбработчикОжидания() (соответственно обратный метод ОтключитьОбработчикОжидания()). В параметрах этого метода передается имя обработчика и интервал, с которым он будет вызываться.
Кроме этого существует ряд событий, позволяющих формам взаимодействовать друг с другом.
Прежде всего это события, связанные с подчиненностью одной формы другой.
Во-первых, форма может обрабатывать событие ОбработкаАктивизацииОбъекта(), которое возникает при изменении активного объекта в одной из подчиненных форм или при вызове в одной из подчиненных форм метода ОповеститьОбАктивизацииОбъекта().
Во-вторых, форма может обрабатывать событие ОбработкаВыбора(), которое возникает при выборе объекта в одной из подчиненных форм или при вызове в одной из подчиненных форм метода ОповеститьОВыбореОбъекта().
В-третьих, форма может обрабатывать событие ОбработкаЗаписиНовогоОбъекта(), которое возникает при записи объекта в одной из подчиненных форм или при вызове в одной из подчиненных форм метода ОповеститьОЗаписиНовогоОбъекта().
Но кроме этих трех событий существует еще одно событие объекта Форма, которое позволяет взаимодействовать не только подчиненным, но вообще любым открытым формам. Это событие ОбработкаОповещения(), которое возникает при оповещении всех открытых форм методом глобального контекста Оповестить(). [548]
В заключение следует отметить одну интересную особенность в обработке события модуля приложения ОбработкаВнешнегоСобытия(). Это событие возникает при посылке внешним приложением сообщения, сформированного в специальном формате. Так вот, внешнее событие сначала будет предложено обработать всем открытым формам (по событию ВнешнееСобытие()), а затем уже это внешнее событие может быть обработано обработчиком модуля приложения. [549]
Способы доступа к данным
Система 1С:Предприятие 8.0 поддерживает два способа доступа к данным, хранящимся в базе данных:
· | объектный (для чтения и записи), |
· | табличный (для чтения). |
Объектный способ доступа к данным реализован посредством использования объектов встроенного языка. При этом обращение к какому-либо объекту встроенного языка, является обращением к некоторой совокупности данных, как к единому целому.
Например, объект ДокументОбъект.ОказаниеУслуги будет содержать значения всех реквизитов документа "Оказание услуги" и всех его табличных частей.
Объектная техника обеспечивает сохранение целостности объектов, кэширование объектов, вызов соответствующих обработчиков событий и т.д.
Табличный доступ к данным реализован посредством использования запросов к базе данных. В этой технике разработчик получает возможность оперировать отдельными полями таблиц базы данных, в которых хранятся те или иные данные.
Табличная техника предназначена для получения информации из базы данных по некоторым условиям (отбор, группировка, сортировка, объединение нескольких выборок, расчет итогов и т.д.). Табличная техника оптимизирована для обработки больших объемов информации, расположенной в базе данных, и получения данных, отвечающих заданным критериям. [553]
Способы работы с коллекцией
Многие объекты встроенного языка являются коллекциями Коллекция представляет собой совокупность объектов. Существуют общие принципы работы с любой коллекцией. Во-первых, доступ к каждому объекту коллекции возможен путем перебора элементов коллекции в цикле. Для этого используется конструкция языка Для Каждого ... из ... Цикл ...:
Для Каждого СтрокаТабличнойЧасти из ТабличнаяЧасть Цикл
Сообщить(СтрокаТабличнойЧасти.Услуга);
КонецЦикла;
Во-вторых, возможен доступ напрямую к элементу коллекции, без перебора коллекции в цикле. Здесь возможны различные комбинации двух обращений:
1. Если каждому элементу коллекции можно сопоставить уникальное имя, тогда обращение к элементу коллекции, как правило, возможно по этому имени:
... = Справочники.Сотрудники;
... = Справочники ["Сотрудники"];
2. Если нет смысла в "персонификации" элементов коллекции, тогда обращение к элементу коллекции, как правило, возможно по индексу (индекс первого элемента коллекции – ноль):
ТабличнаяЧасть[0];
Следует отметить, что существуют коллекции, сочетающие оба вида обращений. Например, к коллекции колонок таблицы значений можно обращаться как по именам колонок, так и по индексу. [550]
Справочники и документы
Интересно обратить внимание на разницу в употреблении единственного и множественного числа при именовании объектов вида "Справочник" и объектов вида "Документ". Если вы откроете дерево типовой конфигурации, то увидите, что все объекты, расположенные в ветке "Справочники", как правило, именованы во множественном числе. В ветке же "Документы" все объекты, как правило, именованы в единственном числе. Может сложиться впечатление что, создавая объект "Справочник", мы создаем "хранилище" для записей этого справочника, а, создавая "Документ", мы создаем некий шаблон этого документа. На самом деле это не так.
Создавая в конфигураторе объект вида "Справочник" мы даем ему наименование во множественном числе ("Товары"), подразумевая тем самым, что в базе данных этот объект будет состоять из записей, каждая из которых описывает один товар (в единственном числе).
Создавая в конфигураторе объект вида "Документ" мы даем ему наименование в единственном числе ("Приходная накладная"), однако на самом деле мы создаем такое же "хранилище", как и в случае со справочником. Каждая запись этого "хранилища" будет описывать одну приходную накладную (в единственном числе). Поэтому концептуально правильно было бы в конфигураторе задавать наименование объекта вида "Документ" во множественном числе, подчеркивая тем самым описание набора документов этого вида (например, "Приходные накладные").
Однако, психология человека такова, что, открывая ветку "Документы", он ожидает увидеть перечисление их в единственном числе, а никак не во множественном. Так происходит потому, что в реальной жизни трудно найти подходящий термин для описания совокупности документов одного вида (совокупность записей одного вида обозначить гораздо проще – справочник, план и т.д.). Поэтому соответствующая ветка объектов конфигурации имеет название "Документы", а объекты, создаваемые в этой ветке, именуются в единственном числе, хотя, по сути, сама ветка содержит описания "хранилищ" документов разных видов, а каждый элемент в этой ветке описывает набор всех документов одного вида. [539]
Стандарты именования переменных, процедур и объектов конфигурации
Фирма "1С" использует ряд стандартов, регламентирующих порядок разработки типовых конфигураций на платформе "1С:Предприятие 8.0". В этой главе мы дадим некоторые выдержки из этих стандартов, которые касаются формирования имен объектов конфигурации, переменных, процедур, функций, элементов управления и т. д.
Транзакционный кэш
Если обращение к данным происходит в рамках транзакции, то оно переадресуется транзакционному кэшу. Транзакционный кэш, по сути, представляет собой ту же последовательную очередь, что и обычный кэш, за исключением того, что все данные, находящиеся в транзакционном кэше, являются валидными (гарантированно актуальными). При считывании данных в транзакционный кэш устанавливается блокировка на данные в базе данных, поэтому они гарантированно не могут быть изменены до окончания транзакции.
Транзакционный кэш хранит считанные данные до тех пор, пока они не будут вытеснены более поздними считанными данными, или пока не закончится транзакция.
По окончании транзакции транзакционный кэш очищается, однако действия, выполняемые при этом, зависят от состояния завершения транзакции. [556]
Если транзакция завершена успешно (Commit), данные всех объектов, содержащиеся в транзакционном кэше, переносятся в обычный кэш, а транзакционный кэш очищается.
Commit
Если был выполнен отказ от изменений (Rollback), то просто очищается транзакционный кэш.
Rollback
[557]
Виды объектов встроенного языка
Для обеспечения доступа к информационным структурам базы данных встроенный язык содержит набор унифицированных объектов. Их можно разделить на несколько видов, в зависимости от их назначения.
Менеджер информационных структур одного вида – этот вид объектов является коллекцией значений, содержащей менеджеры всех информационных структур этого вида, существующих в базе данных (например, менеджер справочников – СправочникиМенеджер – коллекция значений, содержащая объекты СправочникМенеджер.<имя>). Предназначен для доступа к отдельным менеджерам информационных структур.
Менеджер конкретной информационной структуры – этот вид объектов предоставляет средства для работы с конкретной информационной структурой (например, менеджер документа Приходная накладная – ДокументМенеджер.ПриходнаяНакладная).
Объект – с помощью объектов этого вида возможна манипуляция данными информационной структуры. Предоставляют доступ к объекту информационной структуры и позволяют изменять информацию в базе данных. Применяются для тех информационных структур, на объекты которых могут существовать ссылки (справочники – СправочникОбъект.<имя>, документы – ДокументОбъект.<имя> и т.д.).
Набор записей – с помощью объектов этого вида также возможна манипуляция данными информационной структуры. Предоставляют доступ к объекту информационной структуры и позволяют изменять информацию в базе данных. Применяются для тех информационных структур, ссылки на объекты которых в принципе не могут использоваться в базе данных (регистры – РегистрНакопленияНаборЗаписей.<имя>, перерасчеты – ПерерасчетНаборЗаписей.<имя> и т.д.).
Ссылка – объекты этого вида служат для указания ссылки на объект базы данных, и кроме этого предоставляют некоторую [551] информацию об этом объекте (например, документ ДокументСсылка.<имя>).
Выборка – объекты этого вида представляют собой набор данных содержащий данные объектов одной информационной структуры отобранных по определенному критерию. Обход выборки выполняется методом Следующий() и считывание данных из базы данных происходит динамически, по мере продвижения по выборке. Получение ссылки на объект возможно при помощи свойства Ссылка, а получение объекта – методом ПолучитьОбъект() (справочник – СправочникВыборка.<имя>).
Список – объекты этого вида предназначены для управления списком объекта, отображаемым в табличном поле (перечисление – ПеречислениеСписок.<имя>). Использовать эти объекты имеет смыл только при выводе информации в табличное поле. [552]
Виртуальные таблицы запросов
Как вы теперь знаете, при создании запроса система предоставляет нам в качестве источников данных некоторое количество виртуальных таблиц. Название "виртуальные" полностью соответствует их сути, поскольку эти таблицы, в свою очередь, также являются результатом запроса, который система формирует в момент выполнения соответствующего участка кода.
По большому счету разработчик может самостоятельно получить те же самые данные, которые система предоставляет ему в качестве виртуальных таблиц, однако алгоритм получения этих данных не будет оптимизирован в силу следующих двух причин.
Во-первых, все виртуальные таблицы параметризованы, т.е. разработчику предоставляется возможность задать некоторые параметры, которые система будет использовать при формировании запроса создания виртуальной таблицы. Примечательным здесь является то, что задание параметров виртуальной таблицы не всегда приводит к простой подстановке указанных разработчиком значений в текст запроса. В зависимости от того, какие параметры виртуальной таблицы указаны разработчиком, система может формировать РАЗЛИЧНЫЕ запросы для получения одной и той же виртуальной таблицы, причем эти запросы будут оптимизированы с точки зрения переданных параметров.
Во-вторых, не всегда разработчик имеет возможность получить доступ к тем данным, к которым имеет доступ система. Например, при использовании виртуальных таблиц регистров сведений, разработчику доступна, по большому счету, вся та же информация о данных регистров, которую использует система при формировании запроса виртуальной таблицы. Совсем иная картина с виртуальными таблицами регистров накопления, где система динамически формирует запрос в зависимости не только от переданных параметров, но и от периода рассчитанных итогов регистра, причем в запросе она использует данные рассчитанных итогов, которые просто не доступны для разработчика при создании запроса.
Конечно, разработчик может самостоятельно перебрать все записи регистра накопления и в итоге получить те же самые данные, которые система предоставляет в виде виртуальной таблицы, однако очевидно, [559] что такой запрос будет менее эффективным и потребует от разработчика гораздо больше трудозатрат. [560]