ПРИЛОЖЕНИЯ |
Приложение
A. Основные элементы встроенного языка Приложение
B. Построение отчета без использования макета В последующих разделах содержится дополнительный материал,
который по тем или иным причинам не вошел в основную часть курса. Большая часть материала предназначена для самостоятельного
изучения. Однако преподаватель вправе использовать ее как в основной части
курса, так и в качестве готовых ответов на дополнительные вопросы слушателей. Часть материала предназначена полностью для самостоятельного
закрепления материала основной части после окончания обучения. |
Приложение A. Основные элементы встроенного языка |
|||
A.1. Программный
модуль Это приложение предназначено для тех, кто не владеет в
достаточном объеме встроенным языком системы "1С:Предприятие".
Читатели, имеющие опыт программирования
в системе "1С:Предприятие 7.7", смогут систематизировать и углубить
свои знания по данной теме. Встроенный язык системы 1С:Предприятие 8.0 (далее – язык) является объектным языком
программирования. Он предназначен для описания прикладных алгоритмов
функционирования прикладной
системы (конфигурации). При этом существенная часть разработки такого
решения делается визуальным образом в Конфигураторе, а язык используется
только там, где необходимо выполнить алгоритмическую настройку
системы. Для облегчения написания текстов в языке имеется практически
полная двуязычность, которая выражается в том, что одни и те же структурные
конструкции, зарезервированные слова, имена объектов,
методов
и свойств
могут быть записаны как по-русски, так и по-английски в одном тексте программы. Язык обладает достаточным набором типов данных, которые Вы
можете использовать при обработке информации. Для удобства рассмотрения дальнейшего материала, а также для
закрепления основной части курса, создайте новую информационную базу,
выполнив упражнение:
|
A.1. Программный модуль |
Текст программы,
написанный на языке, размещается в программном
модуле конфигурации. Модули вызываются системой в строго определенные
моменты времени, в тех случаях, когда необходимо реализовать специальную
обработку данных. Программная часть системы производит вызов процедур
и функций
(размещенных разработчиком конфигурации) в модуле в строго определенные
моменты времени. Всякий раз, когда мы будем говорить о вызове той или иной
процедуры мы будем упоминать тот момент времени (событие), когда это
происходит. В этом смысле, написание текста программы языке системы
1С:Предприятие 8.0 – это ответ на вопрос: "Что нужно проделать, если произошло такое событие…?". Так, почти каждая команда
пользователя
к системе в режиме "1С:Предприятие" вызывает возникновение
некоторого события (или событий). Все события перечислены в
документации. Каждое событие, если не предпринять каких-либо действий на
встроенном языке, будет обрабатываться системой по умолчанию так, как это
определено при разработке программной части. Кроме того, события могут возникать в результате выполнения алгоритма
на встроенном языке системы. Для каждого программного модуля известен список событий, которые
он может обрабатывать. Если необходимо обработать возникновение конкретного
события, то текст модуля должен содержать текст соответствующей этому событию
процедуры-обработчика. Впрочем, существуют модули, которые не
предназначены для обработки событий. Вторым важным моментом для понимания логики работы модуля
является его размещение в дереве
объектов Конфигурации. Часто многие ошибки начинающих программистов,
использующих этот язык, связаны с неверным размещением процедур
и функций.
В зависимости от размещения модуля его относят к одному из видов
программных модулей, полный список которых имеется в описании встроенного
языка системы. Каждый модуль воспринимается системой как единое целое и, кроме
того, он связан с остальной частью Конфигурации. Эта связь называется контекстом
выполнения модуля. В некотором очень приблизительном смысле этого слова
контекст можно себе представить, как доступный в каком-либо месте набор имен
свойств и методов, которые Вы можете использовать. Различают глобальный
контекст и локальный контекст модуля. О том, что к какому
контексту относится, мы будем говорить при рассмотрении тех или иных
возможностей языка. |
A.2. Модуль приложения |
Как уже отмечалось выше, большинство модулей предназначены для
обработки определенных событий возникающих в системе, поэтому в конфигурации
может присутствовать модуль, который отвечает за сеанс работы пользователя
в целом. Этот модуль носит название Модуль приложения. В данном случае под приложением следует понимать
конкретное учетное решение, в качестве которого выступает конфигурация
и система программ
"1С:Предприятие", образующие в процессе своего исполнения единое
целое. Для того чтобы открыть этот модуль в Конфигураторе, необходимо в
окне
"Конфигурация" активизировать объект
Конфигурация и нажать правую кнопку мыши.
После чего выбрать пункт контекстного меню "Открыть модуль
приложения" (см. рис. A.1).
Отметим, что модуль приложения инициализируется
системой при ее запуске в режиме "1С:Предприятие" - это первое
действие, которое выполняет система сразу после открытия ИБ и считывания ее
Конфигурации, но до отображения основного окна приложения. После того как инициализация
модуля успешно завершилась, система приступает к обработке возникающих
системных событий. Поэтому в теле модуля могут содержаться тексты процедур
обработчиков событий, которые призваны реализовать прикладные алгоритмы
их обработки. |
A.3. Обработка событий в модуле приложения |
|||
Для Модуля приложения имена процедур-обработчиков событий строго
фиксированы:
Для каждой такой процедуры в документации описано, когда событие
возникает, а также какие действия можно выполнять в этой процедуре. Однако у начинающих программирование в этой системе часто
возникает вопрос: В каком порядке возникают события? Ниже мы дадим краткий ответ на этот вопрос, не повторяя описание
каждой из процедур-обработчиков, так как оно имеется в документации. Итак: Сразу после успешной инициализации
модуля
приложения система пытается разыскать процедуру ПередНачаломРаботыСистемы(Отказ), в которой вы можете выполнить
подготовительные действия перед началом работы системы или вообще отменить ее
запуск (до открытия основного окна). Если отмены сделано не было, то тогда система отображает
основное окно
приложения и пытается найти процедуру ПриНачалеРаботыСистемы(). Если такая
процедура есть, то система передает ей управление. В этой процедуре вы можете
уже вести диалог с пользователем. Если есть необходимость в этот момент времени завершить работу
системы, то можно применить одну из встроенных процедур для управления
системой:
Последняя из которых, принудительно прекращает работу системы,
блокируя работу других обработчиков событий. После того как процедура ПриНачалеРаботыСистемы() закончила
свою работу, система приступает к обработке событий, возникающих в процессе
работы пользователя в режиме "1С:Предприятие". При этом для их
обработки будут вызываться соответствующие процедуры-обработчики событий,
принадлежащие прикладным объектам в конфигурации. Такой порядок обработки событий будет продолжаться до тех пор,
пока, либо пользователь не даст команду на закрытие основного окна
приложения, либо в каком-либо программном
модуле не будет сделан вызов процедуры ЗавершитьРаботуСистемы(<Запрашивать
возможность>), после чего система сделает попытку
передать управление в процедуру - обработчик ПередЗавершениемРаботыСистемы(<Отказ>) модуля приложения. В этой процедуре вы можете запросить у пользователя
подтверждение и отменить закрытие основного окна приложения. Если отмены на этом этапе сделано не было, то система пытается
найти процедуру – обработчик ПриЗавершенииРаботыСистемы(). В которой можно выполнить заключительные действия, перед тем
как задача "1С:Предприятие" вернет управление операционной системе. Обработку событий мы рассмотрим на примере выполнения следующего
упражнения:
Для выполнения упражнения наберите следующий текст: //Модуль приложения Для того чтобы проверить работоспособность нашей процедуры
необходимо будет сохранить и обновить конфигурацию. После чего запустить
режим "1С:Предприятие". Если Вы все сделали правильно, то сразу после запуска
конфигурации на исполнение Вы получите диалог, изображенный на рисунке №А.2.
В случае положительного ответа наша конфигурация
продолжает работу, а противном случае работа будет прекращена немедленно. |
A.4. Системные перечисления |
В приведенном выше тексте процедуры мы при вызове функции
Вопрос(…) в качестве одного из фактических значений использовали значение
РежимДиалогаВопрос.ДаНет. Такой тип
данных в языке "1С:Предприятия" называется системным
перечислением. Системные перечисления были специально введены в язык
1С:Предприятия для того, чтобы сделать более читаемыми вызовы системных
процедур и функций. Если установить курсор в тексте процедуры на этом значении и
нажать на клавишу Ctrl+F1, то Конфигуратор откроет специальное справочное
окно "Синтакс – помощник", в котором мы сможем увидеть список всех
возможных значений. Кнопка
Следует заметить, что многие методы
глобального контекста (а также методы объектов) могут возвращать в качестве
значения – значение системного перечисления. Именно по этой причине мы при проверке ответа, который нам дал пользователь,
в условном операторе
написали следующее условие: Если Ответ = КодВозвратаДиалога.Нет Тогда |
A.5. Системные наборы значений |
Как уже отмечалось выше, системные перечисления содержат некоторые
заранее заданные наборы значений. В этом смысле, системные наборы значений на них очень
похожи (по форме записи). Разница между ними состоит в том, что системное перечисление
представляет собой некоторый тип
данных. При этом количество возможных значений и способ их записи
определяется именно этим типом данных. Системные наборы значений представляют собой просто некоторую
коллекцию предопределенных значений конкретного типа данных, но множество
значений соответствующего типа данных на этом не ограничивается. Приведем пример: Предположим, что текст сообщения в функции
Вопрос(…), что мы использовали выше, мы могли бы между двумя
предложениями вставить символ табуляции, просто набрав его на клавиатуре.
Тогда соответствующий фрагмент текста процедуры будет следующим: Ответ = Вопрос("Сейчас не
рабочее время! Будете работать?", Но кроме визуально большего расстояния между двумя символами нам
это ничего не даст, т.к. понять по тексту программы,
что в этом месте стоит символ табуляции, мы не сможем. Поэтому более читабельной будет запись с использованием
системного набора значений Символы: Ответ = Вопрос("Сейчас не
рабочее время!"+Символы.Таб+ |
A.6. Примитивные типы данных |
Среди всех типов данных, что есть в языке, имеются типы, которые
относятся к группе примитивных типов данных. Для большинства типов из
этой группы отличительной чертой является возможность записывать в тексте модуля
обращения к конкретным их значениям в виде литералов. Так, например, запись любого числа может быть произведена в
тексте модуля
явно: 1234567.89. Строка "Сейчас не рабочее время!", что мы использовали
выше по типу данных – это Строка. К примитивным типам относятся:
Для каждого из типов определен способ записи его конкретных
значений. А также список возможных операций, которые можно выполнять над
значениями данного типа. Эта информация
подробно изложена в документации, а именно в книге "1С:Предприятие 8.0.
Описание встроенного языка" (входит в поставку). Чуть ниже мы рассмотрим особенности использования некоторых
примитивных типов. A.6.1. Тип данных "Неопределено" Состоит из одного единственного значения - Неопределено. Его мы рассмотрим чуть ниже, когда будем говорить о переменных
модуля. A.6.2. Тип данных "Булево" Этот тип
данных имеет только два значения Истина и Ложь, которые образуются в
результате вычисления логических выражений. Например: 1>2 даст в качестве результата Ложь. Но если знак
неравенства изменить: 1<2, то в результате вычисления получится Истина. A.6.3. Тип данных "Число" Над числами в "1С:Предприятии" можно выполнять
основные арифметические операции. Кроме того, для этого типа в языке имеются
встроенные математические функции. Для читателей имеющих опыт программирования в
"1С:Предприятии" версии 7.7 следует заметить, что точность
выполнения арифметических операций – 38 знаков. A.6.4. Тип данных "Строка" Над строками определена только одна операция "+" -
сцепление строк. Кроме этой операции в языке имеется достаточно большое
количество встроенных функций обрабатывающих строковые данные. A.6.5. Тип данных "Дата" Первое, на что необходимо обратить внимание, так это, что данные
этого типа содержат не только дату, но и время. Конкретные
значения (литералы) записываются следующим образом: 'ГГГГММДДЧЧММСС'. Так, например если нужно указать конкретную дату, то следует
записать: '20030312' – это будет означать 12 марта 2003 года 0:00:00, так как
время в этой записи мы опустили. Но если нужно указать конкретный момент
времени, то тогда необходимо использовать полный канонический способ
записи: '20030312141122'. Что будет означать 12 марта 14 часов 11 минут 22 секунды. Если нужно указать только время, то тогда все равно перед
временем следует написать дату отсчета - '00010101': '00010101141122'.
Такая запись будет означать 1 января 0001 года (точка отсчета)
14:11:22, или просто 14 часов 11 минут 22 секунды. Над датами определены операции "+" и "-", а
также обычные операции сравнения: "<", "<=",
"=", ">=", ">" и "<>". При этом нужно помнить, что если вычесть одно значение типа Дата
из другого значения типа Дата, то результатом будет число секунд между этими
двумя моментами времени. Примеры: '20030312'-'20030311' даст в результате вычисления число 86 400. К дате можно прибавлять (отнимать) необходимое число секунд: '200303121430'+300 даст после вычисления момент 12.03.2003
14:35:00. A.6.6. Тип данных "Null" Используется в языке запросов. Мы рассмотрим его позже, когда
будем изучать объект
Запрос и язык запросов. A.6.7. Тип данных "Тип" Тип какого-либо значения – это такой же тип
данных, как и число, строка или, например, Null. Единственным его
отличием от типов, что были рассмотрены выше – это отсутствие литеральной
записи. Если возникает необходимость получить конкретное значение типа
"Тип", то следует применить функцию:
Тип("ИмяТипа"). Так, например
запись Тип("Число") позволит получить значение Тип
"Число". |
A.7. Разделы Модуля приложения |
|||
Большинство программных
модулей (но не все) имеют одинаковую структуру. Структурно модуль может состоять из трех разделов:
Разделы могут размещаться только в порядке перечисленном выше.
При этом какой-либо из разделов и даже все могут отсутствовать. Модуль
приложения может
иметь все три раздела перечисленных выше. Сейчас этот модуль содержит только
один раздел – раздел процедур
и функций,
в котором сейчас находится только одна процедура. Замечание: Не
рекомендуется в разделе основной программы
выполнять какие-либо интерактивные действия, т.е. задавать пользователю
вопросы и получать от него ответы. Как правило, для этой цели можно
использовать раздел процедур и функций модуля. Использование разделов модуля мы рассмотрим на примере решения
следующего упражнения:
Для начала нам необходимо будет сохранить время начала работы.
Но как это сделать? Единственный выход: объявить переменную
и присвоить ей значение сразу после запуска системы. А момент этот, напомним,
наступит сразу после завершения компиляции
модуля. Поэтому текст нашего модуля будет выглядеть следующим образом: // Модуль приложения В этом тексте ключевое
слово Перем объявляет переменную и ее начальное значение - типа Неопределено. Тут нужно отметить, что переменная в разные моменты времени
может принимать значения разных типов. Например: Перем А; Можно запомнить, что тип переменной определяется тем значением,
которое в нее записывается, например, с помощью оператора
присваивания. В связи с выше сказанным, значение Неопределено используется для того, чтобы определить было ли
присвоено переменной
какое-либо значение: // Пытаемся
восстановить значение сохраненное в предыдущем В этом примере функция глобального контекста ВосстановитьЗначение пытается восстановить значение
"А", которое возможно было предварительно сохранено с помощью
процедуры СохранитьЗначение в предыдущем сеансе работы
пользователя. Но вернемся к нашей задаче. Для формирования строки с длительностью интервала нам придется
написать текст функции
ИнтервалСтр(Начало,Конец), которая
должна возвращать строку с интервалом между значениями Конец и Начало. Для работы с датами (и временем!) имеется большое количество
процедур и функций. Есть даже функция ТекущаяДата(), которая возвращает текущее значение
системных часов компьютера (дату и время). Поэтому для решения задачи необходимо из этого значения типа
дата извлечь часы, минуты и секунды. В этом нам могут помочь функции:
Согласно структуре нашего модуля написать эту функцию мы сможем
только в разделе процедур и функций: //--------------------------------------------------------- Последнее, что осталось так это "поймать" и обработать
событие перед завершением работы системы: //ПередЗавершениемРаботыСистемы(Отказ) - запрашивает В этом тексте мы обратим ваше внимание на три момента: 1.
Для
того чтобы текст сообщения располагался бы на двух строках, мы применили
значение из системного набора значений Символы (Символы.ПС), которое соответствует символу
перевода строки. 2.
Для
того чтобы ожидание ответа пользователя
не было бы бесконечно долгим, мы использовали величину 30 (секунд) в качестве
продолжительности ожидания ответа (третий параметр). 3.
Для
того чтобы система могла бы принять решение об отмене команды пользователя,
мы должны установить формальный параметр Отказ в
значение Истина, если пользователь явно нажал на кнопку
"Нет", что обеспечивается выражением: Отказ = (Ответ = КодВозвратаДиалога.Нет); |
A.8. Преобразование типов и ошибки времени выполнения |
Если внимательно разобрать текст функции
ИнтервалСтр(Начало,Конец), то можно
обратить внимание на то, что при описании заголовка функции
мы нигде не указали ни тип возвращаемого функцией значения, ни типы
формальных параметров. Поэтому запомним, что функция (процедура) может принимать и
возвращать в качестве формальных параметров в разные моменты времени значения
разных типов. И тип возвращаемого функцией значения определяется типом
выражения записанного в операторе
Возврат. Очевидно, что наша функция должна возвращать строку текста, так
как мы будем отображать в окне
именно строку. Поэтому необходимо обеспечить, чтобы возвращаемое значение
имело бы тип Строка. Если бы мы записали в операторе Возврат следующее выражение: Стр= Часов+"ч"+Минут+"м"+Секунд+"с"; То мы получили бы ошибку времени выполнения (см. рис. №A.5).
Почему так получилось при вызове нашей функции? Потому, что
переменная Часов типа Число, а строка "ч" –
это Строка. Раз типы данных разные, то система выполняет неявное
преобразование типа. Но к какому типу? Если типы данных в выражении отличаются друг от друга, то все
операнды выражения всегда будут неявно преобразовываться к типу первого
операнда. Но строка "ч" не может быть преобразована в число,
так как с точки зрения системы содержит букву, а это уже не число. Для того чтобы выражение вычислялось бы правильно и операцию
"+" система рассматривала бы как сцепление строк необходимо,
чтобы первым операндом была бы строка хотя бы и пустая: Стр ="" Часов+"ч"+Минут+"м"+Секунд+"с"; Тогда в выражении ""+Часов… переменная Часов будет неявно преобразована в строку. По аналогии в тех случаях, когда необходимо обеспечить, чтобы
все операнды в выражении были бы числовыми, выражение начинают с 0: Т=0+… Впрочем, для явного преобразования типа имеются встроенные
функции: Число(…), Строка(…) и Дата(…). |
A.9. Ключевое слово Экспорт и глобальный контекст |
Очевидно, что наша функция
ИнтервалСтр(…) носит достаточно универсальный характер и может возникнуть
необходимость применить ее вызов в других модулях
конфигурации.
Но сейчас эта функция принадлежит локальному контексту Модуля приложения,
что делает невозможным ее использование в других модулях. Для того чтобы эта функция попала в глобальный контекст,
необходимо в ее заголовке написать добавочное ключевое
слово Экспорт: Функция ИнтервалСтр(Начало,Конец) Экспорт Теперь вызов этой функции можно будет сделать везде, где в
системе допускается запись выражений на встроенном языке системы. Все выше сказанное относится и к переменным. Так переменная НачалоРаботы сейчас принадлежит локальному
контексту. И для того чтобы она стала глобальной, необходимо добавить ключевое
слово Экспорт: // Раздел переменных------------------- |
A.10. Общие модули |
A.10.1.Назначение
Общих модулей В этом разделе мы рассмотрим Общий
модуль, который будет содержать примеры написания вспомогательных
процедур и функций. |
A.10.1. Назначение Общих модулей |
Если в окне "Конфигурация" раскрыть ветвь
"Общие" (см. рис. №A.6), то среди общих объектов конфигурации можно
увидеть отдельную ветвь для общих модулей. Общие используются для размещения процедур и функций,
вызов которых предполагается из других модулей
конфигурации.
Как было отмечено выше, такие процедуры и функции должны иметь добавочное ключевое
слово Экспорт. Общие
модули конфигурации существенным образом отличаются от большинства
остальных модулей своим назначением – они предназначены для размещения общих
процедур и функций, вызов которых предполагается делать из разных модулей
конфигурации. Вследствие выше изложенного факта, общий модуль не может
содержать процедур обработчиков событий. И его структура допускает наличие
только раздела процедур и функций. В общих модулях отсутствуют разделы переменных
и раздел основной программы. Поэтому обычно в Модуле
приложения размещают только процедуры-обработчики событий, а общие
процедуры и функции выносят в какой-либо общий модуль. |
A.10.2. Добавление Общего модуля в Конфигурацию |
|||||||||||
Добавим в нашу конфигурацию новый Общий
модуль, выполнив следующее упражнение:
Если Вы все сделали правильно, то текст этого общего модуля
будет выглядеть следующим образом: //Общий модуль служебных функций Обратите внимание на то, что теперь текст Модуля
приложения в разделе процедур и функций содержит только процедуры
обработчики событий: // Модуль приложения //--------------------------------------------------------- //--------------------------------------------------------- //ПриНачалеРаботыСистемы() - проверяет время входа в систему //ПередЗавершениемРаботыСистемы(Отказ) - запрашивает //--------------------------------------------------------- |
A.11. Самостоятельная работа |
||||||
Для закрепления материала этого раздела выполните самостоятельно
следующие упражнения.
Ответьте для себя на следующие вопросы:
|
A.12. Что мы узнали |
В этом приложении мы рассмотрели основные элементы встроенного
языка. Мы выяснили, что программные модули в конфигурации предназначены
для написания алгоритмов
обработки системных событий, которые возникают в системе как в результате
интерактивных действий пользователя, так и в результате выполнения алгоритмов
написанных на встроенном языке системы. Обработку событий мы подробно рассмотрели на примере
использования модуля приложения, который отвечает в конфигурации за весь
сеанс работы с пользователем. Мы также рассмотрели такие новые (по сравнению с системой
"1С:Предприятие 7.7") элементы встроенного языка, как системные
перечисления и системные наборы значений, и их место в системе
типов данных встроенного языка системы. Мы также рассмотрели некоторые примитивные
типы данных и преобразование типов данных при вычислении выражений. Модуль приложения, как и любой другой модуль, имеет определенную
структуру. В этом модуле Вы можете использовать все три раздела (переменных,
процедур и функций, основной программы). Мы также рассмотрели разницу между Модулем приложения и Общими
модулями в конфигурации их назначении и, как следствие, структуры. Ключевое слово Экспорт, которое можно применять в Модуле
приложения и в общих модулях конфигурации, позволяет внести с глобальный
контекст переменные, процедуры и функции, объявленные в этом модуле, если
предполагается обращение к ним из других модулей конфигурации. Архив ИБ, являющуюся результатом выполнения упражнений
Приложения A, Вы можете найти здесь. |
Приложение B. Построение отчета без использования макета |
||||||
B.1. Что
мы узнали Этот раздел полностью предназначен для самостоятельного
изучения. Для удобства рассмотрения дальнейшего материала, а также для
закрепления основной части курса, создайте новую информационную базу,
выполнив упражнение:
Обратите внимание, что после загрузки ИБ Конфигуратор закончил
свою работу – это его нормальное поведение, которое описано в документации к
программе. Формировать отчет
можно и без использования макета.
В этом случае необходимо, как и раньше, сначала создать объект
типа ТабличныйДокумент, а затем обращаться к его отдельным ячейкам через
метод Область: ТабДок = Новый ТабличныйДокумент(); Поскольку изначально табличный документ пуст, то в нем нет
никаких именованных областей, и, следовательно, к отдельным ячейкам можно
обратиться, только используя их адрес. Обратиться к группе ячеек можно путем явного указания номеров
строк и столбцов: Область=ТабДок.Область(НомерПервойСтроки,НомерПервогоСтолбца, НомерПоследнейСтроки,НомерПоследнегоСтолбца); Если необходимо обратиться к конкретной ячейке, то тогда
указываются только номера первой строки и столбца: Область=ТабДок.Область(НомерСтроки,НомерСтолбца); Получив ссылку на область (тип значения - ОбластьЯчеекТабличногоДокумента) мы можем обраться к атрибутам и методам
этого объекта с целью заполнения свойств ячеек, составляющих область.
Приведем текст процедуры ПечатьКурсаУЕ(), которая не использует макет
для построения отчета и является функциональным аналогом старого текста
процедуры, который использовал макет для построения отчета. ПечатьКурсаУЕ(): //ПечатьКурсаУЕ()2 - печать курса УЕ |
B.1. Что мы узнали |
В этом приложении мы рассмотрели основы формирования отчетов с
использованием объекта
"ТабличныйДокумент" без использования макета (исходного табличного
документа). Архив ИБ, являющуюся результатом выполнения упражнений
Приложения B, Вы можете найти здесь. |